[GH-ISSUE #4526] [Bug] Darwin compiler failure projection loses original command-output facts #2358

Closed
opened 2026-10-17 21:03:43 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @morluto on GitHub (Oct 16, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/4526

Before submitting

  • Searched open/closed compiler-output reports and open PRs for overlap.
  • Used only an authored fixture; removed credentials and private target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

A controlled production-boundary run loses the compiler's observed stdout and changes the reported raw stderr byte count from 1 to 3. compilerOutcome() retains a stderr-only envelope and recomputes byte length from decoded text; normalizeCaptureFailure() then manufactures stdout: "" from that incomplete envelope.

Reproduction

Executed once on macOS arm64 / Node 24.18.0 against the current compiled source (base below plus local audit changes):

  1. Create an executable Node compiler fixture writing stdout owned compiler stdout, stderr Buffer.from([0xff]), and exit code 7.
  2. Select it as createDarwinProcessRunTokenReader({compiler:{kind:"xcrun",executable}}) and await prepare().
  3. Pass the failure to production normalizeCaptureFailure(failure, undefined).
  4. Close the reader and remove the owned fixture directory; both cleanup operations completed.

Observed normalized output:

{"stdout":"","stderr":"�","truncated":false,"stderr_bytes":3,"exit_code":7,"signal":null}

This is a real Node child/production producer-and-consumer control, not a native Swift compiler fault or public CLI/MCP reproduction.

Expected behavior

Preserve the original command-output envelope and producer-owned raw byte counts. Consumers should use the compiler owner's parsed captured-output facts. Stderr-only diagnostic metadata cannot establish that stdout was empty. Decode text separately from source byte accounting.

Impact and scope

Observed diagnostic/evidence loss at the Darwin ownership compiler error boundary. Ghidra and native/capture adapters consume these facts; their complete fault workflows were not executed for this report. Real Swift failure frequency and platform scope are NOT_ENOUGH_INFO. #4522 tracks compiler cleanup composition; this is the separate output-provenance representation.

REA version

Source base fe2a398dd9 plus uncommitted audit changes. The stderr-only compiler projection and downstream empty-stdout construction are also present in that base.

Runtime and platform

Node 24.18.0, macOS arm64; controlled Node compiler executable, no native Swift or Windows verification.

Target and artifact context

Authored compiler script; no private target and no analysis target executed.

Interface

Other (compiled producer and capture error projection)

Earliest failure stage

Transport or result projection

Evidence

src/process/DarwinProcessRunTokenReader.ts: compilerOutcome/ compilerInspectionError. src/process/ExecFileOutput.ts: retained stdout/stderr and raw stderrBytes already exist at the producing boundary. src/process/capture/ProcessCaptureError.ts: stderr-only metadata reconstructed into a complete captured-output envelope.

Originally created by @morluto on GitHub (Oct 16, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4526 ### Before submitting - [x] Searched open/closed compiler-output reports and open PRs for overlap. - [x] Used only an authored fixture; removed credentials and private target data. ### Area Evidence, artifacts, or reconstruction ### Observed behavior A controlled production-boundary run loses the compiler's observed stdout and changes the reported raw stderr byte count from 1 to 3. `compilerOutcome()` retains a stderr-only envelope and recomputes byte length from decoded text; `normalizeCaptureFailure()` then manufactures `stdout: ""` from that incomplete envelope. ### Reproduction Executed once on macOS arm64 / Node 24.18.0 against the current compiled source (base below plus local audit changes): 1. Create an executable Node compiler fixture writing stdout `owned compiler stdout`, stderr `Buffer.from([0xff])`, and exit code 7. 2. Select it as `createDarwinProcessRunTokenReader({compiler:{kind:"xcrun",executable}})` and await `prepare()`. 3. Pass the failure to production `normalizeCaptureFailure(failure, undefined)`. 4. Close the reader and remove the owned fixture directory; both cleanup operations completed. Observed normalized output: ```json {"stdout":"","stderr":"�","truncated":false,"stderr_bytes":3,"exit_code":7,"signal":null} ``` This is a real Node child/production producer-and-consumer control, **not** a native Swift compiler fault or public CLI/MCP reproduction. ### Expected behavior Preserve the original command-output envelope and producer-owned raw byte counts. Consumers should use the compiler owner's parsed captured-output facts. Stderr-only diagnostic metadata cannot establish that stdout was empty. Decode text separately from source byte accounting. ### Impact and scope Observed diagnostic/evidence loss at the Darwin ownership compiler error boundary. Ghidra and native/capture adapters consume these facts; their complete fault workflows were not executed for this report. Real Swift failure frequency and platform scope are NOT_ENOUGH_INFO. #4522 tracks compiler cleanup composition; this is the separate output-provenance representation. ### REA version Source base fe2a398dd9ab290ba6cb3411403d319cec8d07a2 plus uncommitted audit changes. The stderr-only compiler projection and downstream empty-stdout construction are also present in that base. ### Runtime and platform Node 24.18.0, macOS arm64; controlled Node compiler executable, no native Swift or Windows verification. ### Target and artifact context Authored compiler script; no private target and no analysis target executed. ### Interface Other (compiled producer and capture error projection) ### Earliest failure stage Transport or result projection ### Evidence `src/process/DarwinProcessRunTokenReader.ts`: compilerOutcome/ compilerInspectionError. `src/process/ExecFileOutput.ts`: retained stdout/stderr and raw stderrBytes already exist at the producing boundary. `src/process/capture/ProcessCaptureError.ts`: stderr-only metadata reconstructed into a complete captured-output envelope.
Author
Owner

@kaoru0822-kitauji commented on GitHub (Oct 17, 2026):

This appears fixed on current main (2092f90b7) by 9d940c2f2 and 0f61261e0 (the commit message references this issue).

Executed on main 2092f90b7 (macOS arm64, Node 24): npm run test:focused -- … including tests/boundary/process/darwinProcessRunTokenReader.test.ts (32 tests), tests/process-global/darwinCompilerCleanup.test.ts (14 tests) — all passed (205/205 across the 13 files checked in this batch).

I did not rerun the original fault injection from the report separately; the tests above are the regressions added with the fix. Leaving closure to a maintainer.

<!-- gh-comment-id:6232497702 --> @kaoru0822-kitauji commented on GitHub (Oct 17, 2026): This appears fixed on current main (2092f90b7) by 9d940c2f2 and 0f61261e0 (the commit message references this issue). Executed on main 2092f90b7 (macOS arm64, Node 24): `npm run test:focused -- …` including `tests/boundary/process/darwinProcessRunTokenReader.test.ts` (32 tests), `tests/process-global/darwinCompilerCleanup.test.ts` (14 tests) — all passed (205/205 across the 13 files checked in this batch). I did not rerun the original fault injection from the report separately; the tests above are the regressions added with the fix. Leaving closure to a maintainer.
Author
Owner

@morluto commented on GitHub (Oct 18, 2026):

Closing as fixed on main after reconciling this report with the landed owner/consumer changes.

  • 0f61261e0: fix(native): retain owned preparation failures through command adapters. Retain producer-owned compiler output and cleanup markers through xcrun resolution and native failure projection. Keep physical preparation failures primary and preserve separate command deadline classification for interrupted preparation. Omitted output facts stay unknown; client close does not resolve foreign helper cleanup. Include CLI failure output in native regression reports.
  • 9d940c2f2: fix(ghidra): preserve lifecycle ownership and failure provenance. Retain snapshot, endpoint, launch rollback and compiler cleanup owners. Join request finalization and cleanup cancellation. Preserve bounded compiler output and original byte counts through capture and Ghidra failures. Normalize execFile cancellation once at its producer.

Evidence scope: this closure uses the landed source, regression coverage and validation already recorded in the linked commits/thread. No new local tests or native-provider reproduction were run during this backlog pass; previously documented platform and real-provider gaps still apply.

<!-- gh-comment-id:6256006657 --> @morluto commented on GitHub (Oct 18, 2026): <!-- rea-backlog-reconciliation-2026-10-19-4526 --> Closing as fixed on `main` after reconciling this report with the landed owner/consumer changes. - [0f61261e0](https://github.com/morluto/rea/commit/0f61261e011ab520773fb51c07a494c98b6a73e5): fix(native): retain owned preparation failures through command adapters. Retain producer-owned compiler output and cleanup markers through xcrun resolution and native failure projection. Keep physical preparation failures primary and preserve separate command deadline classification for interrupted preparation. Omitted output facts stay unknown; client close does not resolve foreign helper cleanup. Include CLI failure output in native regression reports. - [9d940c2f2](https://github.com/morluto/rea/commit/9d940c2f284cc6f75b27900336e52ceeba4aa2af): fix(ghidra): preserve lifecycle ownership and failure provenance. Retain snapshot, endpoint, launch rollback and compiler cleanup owners. Join request finalization and cleanup cancellation. Preserve bounded compiler output and original byte counts through capture and Ghidra failures. Normalize execFile cancellation once at its producer. Evidence scope: this closure uses the landed source, regression coverage and validation already recorded in the linked commits/thread. No new local tests or native-provider reproduction were run during this backlog pass; previously documented platform and real-provider gaps still apply.
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#2358
No description provided.