[GH-ISSUE #3169] [Bug] Failed capture preparation omits cleanup states from terminal progress #1107

Closed
opened 2026-10-15 18:31:07 +00:00 by bsakaguchi · 1 comment
Owner

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

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Process capture or runtime observation

Observed behavior

When capture-process fails during preparation because TMPDIR points to a nonexistent directory, its final stderr progress object has phase=cleanup, terminal=true, and disposition=failed inside message, but the message omits owned_process_group, terminal_renderer, and temporary_root. The command exits 1 and returns a process_capture_failed error with category execution_failure. Its details contain only execution_failure, so details.cleanup_report does not recover the missing states.

The same scenario with an existing temporary directory exits 0 and reports all three states as cleaned. One failed attempt and one successful control were independently reproduced. No resource leak or loss of a completed capture was observed.

Reproduction

  1. Start from a clean checkout at the revision below on macOS with a supported Node.js runtime, the native PTY dependency, and the normal macOS ownership-inspection prerequisites. Install the locked dependencies and build the CLI:

    npm ci
    npm run build:cached
    
  2. From the repository root, create the isolated home and XDG directories, the existing temporary-directory control, and the scenario. Use a fresh checkout so repro-progress does not already exist. Leave repro-progress/missing-temp nonexistent:

    repro_root="$PWD/repro-progress"
    mkdir "$repro_root"
    mkdir -p "$repro_root/home/config" "$repro_root/home/cache" "$repro_root/home/data" "$repro_root/temp"
    cat > "$repro_root/scenario.json" <<'JSON'
    {"executable":"node","arguments":["-e","console.log('ready')"],"timeout_ms":5000}
    JSON
    test ! -e "$repro_root/missing-temp"
    
  3. Run the successful control with the existing temporary directory:

    env HOME="$repro_root/home" \
      XDG_CONFIG_HOME="$repro_root/home/config" \
      XDG_CACHE_HOME="$repro_root/home/cache" \
      XDG_DATA_HOME="$repro_root/home/data" \
      TMPDIR="$repro_root/temp" \
      node scripts/rea.mjs capture-process "$repro_root/scenario.json" --json \
      > "$repro_root/control.json" 2> "$repro_root/control.jsonl"
    printf 'control exit: %s\n' "$?"
    
  4. Run the same scenario with the nonexistent temporary directory. Preparation is expected to fail and exit 1 because it cannot allocate the ownership-helper directory:

    env HOME="$repro_root/home" \
      XDG_CONFIG_HOME="$repro_root/home/config" \
      XDG_CACHE_HOME="$repro_root/home/cache" \
      XDG_DATA_HOME="$repro_root/home/data" \
      TMPDIR="$repro_root/missing-temp" \
      node scripts/rea.mjs capture-process "$repro_root/scenario.json" --json \
      > "$repro_root/failure.json" 2> "$repro_root/failure.jsonl"
    printf 'failure exit: %s\n' "$?"
    
  5. Read the progress streams and the failed command's error envelope:

    cat "$repro_root/control.jsonl"
    cat "$repro_root/failure.jsonl"
    cat "$repro_root/failure.json"
    

    The control's terminal message includes owned_process_group=cleaned terminal_renderer=cleaned temporary_root=cleaned. The failed attempt's terminal message contains none of those keys, and its error details lack cleanup_report. Elapsed times vary.

The install and build commands are clean-checkout prerequisites. Independent verification used already installed dependencies and the prebuilt runtime, then executed both capture invocations.

Expected behavior

docs/process-capture.md:158-165 promises that the final progress line has phase cleanup, terminal=true, and a message containing a disposition plus the owned_process_group, terminal_renderer, and temporary_root cleanup states as key=value text. The documented terminal dispositions include failed, with no exception for preparation failures.

A failed attempt should report the applicable resource states even when no target process started. The expected behavior does not require capture to succeed with a nonexistent host temporary directory.

Impact and scope

This is a bounded failure of a documented machine-readable progress contract. A progress consumer cannot obtain the advertised resource states for this preparation failure, and the observed error envelope supplies no cleanup report as an alternative. Creating a valid temporary directory permits a later successful capture but does not recover the states for the failed attempt.

The reproduction covers the CLI on macOS. MCP calls the same capture producer, as shown by src/server/registerSessionTools.ts:94-126, but MCP execution was not part of this verification. No process leak, lost completed capture Evidence, or severe core-workflow failure was established.

REA version

6.4.0 (main at 5830088520)

Runtime and platform

Node.js v26.10.0; macOS arm64. The OS release was not recorded. This Node version is supported by the package engine range; verification did not use the development pin of Node.js 24.18.0.

Target and artifact context

A finite Node process that prints ready, described by the inline scenario above. The failure occurs during ownership-helper temporary-directory allocation before the target launches. The successful control produces capture Evidence and one terminal frame.

Interface

CLI

Earliest failure stage

Cleanup, cancellation, or lifecycle

Relevant output or evidence

Failed attempt: exit 1
{"rea_progress":{"phase":"cleanup","completed":0,"total":null,"message":"elapsed_ms=1 frames=0 samples=0 interactions=0 disposition=failed","terminal":true,"sequence":2}}
Successful control: exit 0
elapsed_ms=2190 frames=1 samples=0 interactions=0 disposition=exited owned_process_group=cleaned terminal_renderer=cleaned temporary_root=cleaned

The failed stdout envelope reports process_capture_failed, category execution_failure, and an ENOENT diagnostic from helper-directory allocation. Its details contain only execution_failure.

Typed outcome or recovery expected

Keep the preparation failure and its error envelope truthful. The terminal cleanup message must include disposition=failed and all three documented resource-state keys, with states matching the actual preparation outcome. Repeat the nonexistent-directory attempt to verify those fields, then repeat the existing-directory control to preserve successful status reporting and valid capture Evidence. Suppressing the failed terminal line or making the invalid directory succeed would not restore the contract.

Analysis or suspected cause

Source-derived reasoning at the stated baseline: src/application/process/ProcessCli.ts:52-100 validates the scenario and supplies the stderr progress reporter to the shared capture operation. src/process/DarwinProcessRunTokenReader.ts:327 allocates the ownership-helper directory beneath the host temporary directory before target launch.

src/process/capture/ProcessHarness.ts:648-666 catches a preparation error and reports terminal cleanup with a disposition but without a cleanup report. src/process/capture/ProcessCaptureProgress.ts:46-60 emits no resource-state text when that report is absent. This source trace explains the independently reproduced missing fields; it does not establish a failure to clean resources.

Additional context

Related to #3052, which corrected documentation about fields being inside message; this report concerns cleanup states missing from that message on a preparation failure.

P2 impact is supported because consumers lose documented status data for a bounded failure. The reproduction establishes no leaked process, lost capture Evidence, or severe core-workflow impact.

Originally created by @coygeek on GitHub (Oct 14, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/3169 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Process capture or runtime observation ### Observed behavior When `capture-process` fails during preparation because `TMPDIR` points to a nonexistent directory, its final stderr progress object has `phase=cleanup`, `terminal=true`, and `disposition=failed` inside `message`, but the message omits `owned_process_group`, `terminal_renderer`, and `temporary_root`. The command exits 1 and returns a `process_capture_failed` error with category `execution_failure`. Its details contain only `execution_failure`, so `details.cleanup_report` does not recover the missing states. The same scenario with an existing temporary directory exits 0 and reports all three states as `cleaned`. One failed attempt and one successful control were independently reproduced. No resource leak or loss of a completed capture was observed. ### Reproduction 1. Start from a clean checkout at the revision below on macOS with a supported Node.js runtime, the native PTY dependency, and the normal macOS ownership-inspection prerequisites. Install the locked dependencies and build the CLI: ```sh npm ci npm run build:cached ``` 2. From the repository root, create the isolated home and XDG directories, the existing temporary-directory control, and the scenario. Use a fresh checkout so `repro-progress` does not already exist. Leave `repro-progress/missing-temp` nonexistent: ```sh repro_root="$PWD/repro-progress" mkdir "$repro_root" mkdir -p "$repro_root/home/config" "$repro_root/home/cache" "$repro_root/home/data" "$repro_root/temp" cat > "$repro_root/scenario.json" <<'JSON' {"executable":"node","arguments":["-e","console.log('ready')"],"timeout_ms":5000} JSON test ! -e "$repro_root/missing-temp" ``` 3. Run the successful control with the existing temporary directory: ```sh env HOME="$repro_root/home" \ XDG_CONFIG_HOME="$repro_root/home/config" \ XDG_CACHE_HOME="$repro_root/home/cache" \ XDG_DATA_HOME="$repro_root/home/data" \ TMPDIR="$repro_root/temp" \ node scripts/rea.mjs capture-process "$repro_root/scenario.json" --json \ > "$repro_root/control.json" 2> "$repro_root/control.jsonl" printf 'control exit: %s\n' "$?" ``` 4. Run the same scenario with the nonexistent temporary directory. Preparation is expected to fail and exit 1 because it cannot allocate the ownership-helper directory: ```sh env HOME="$repro_root/home" \ XDG_CONFIG_HOME="$repro_root/home/config" \ XDG_CACHE_HOME="$repro_root/home/cache" \ XDG_DATA_HOME="$repro_root/home/data" \ TMPDIR="$repro_root/missing-temp" \ node scripts/rea.mjs capture-process "$repro_root/scenario.json" --json \ > "$repro_root/failure.json" 2> "$repro_root/failure.jsonl" printf 'failure exit: %s\n' "$?" ``` 5. Read the progress streams and the failed command's error envelope: ```sh cat "$repro_root/control.jsonl" cat "$repro_root/failure.jsonl" cat "$repro_root/failure.json" ``` The control's terminal message includes `owned_process_group=cleaned terminal_renderer=cleaned temporary_root=cleaned`. The failed attempt's terminal message contains none of those keys, and its error details lack `cleanup_report`. Elapsed times vary. The install and build commands are clean-checkout prerequisites. Independent verification used already installed dependencies and the prebuilt runtime, then executed both capture invocations. ### Expected behavior `docs/process-capture.md:158-165` promises that the final progress line has phase `cleanup`, `terminal=true`, and a message containing a disposition plus the `owned_process_group`, `terminal_renderer`, and `temporary_root` cleanup states as `key=value` text. The documented terminal dispositions include `failed`, with no exception for preparation failures. A failed attempt should report the applicable resource states even when no target process started. The expected behavior does not require capture to succeed with a nonexistent host temporary directory. ### Impact and scope This is a bounded failure of a documented machine-readable progress contract. A progress consumer cannot obtain the advertised resource states for this preparation failure, and the observed error envelope supplies no cleanup report as an alternative. Creating a valid temporary directory permits a later successful capture but does not recover the states for the failed attempt. The reproduction covers the CLI on macOS. MCP calls the same capture producer, as shown by `src/server/registerSessionTools.ts:94-126`, but MCP execution was not part of this verification. No process leak, lost completed capture Evidence, or severe core-workflow failure was established. ### REA version 6.4.0 (main at 58300885207133422af235e0f2b10658cf958b03) ### Runtime and platform Node.js v26.10.0; macOS arm64. The OS release was not recorded. This Node version is supported by the package engine range; verification did not use the development pin of Node.js 24.18.0. ### Target and artifact context A finite Node process that prints `ready`, described by the inline scenario above. The failure occurs during ownership-helper temporary-directory allocation before the target launches. The successful control produces capture Evidence and one terminal frame. ### Interface CLI ### Earliest failure stage Cleanup, cancellation, or lifecycle ### Relevant output or evidence ```text Failed attempt: exit 1 {"rea_progress":{"phase":"cleanup","completed":0,"total":null,"message":"elapsed_ms=1 frames=0 samples=0 interactions=0 disposition=failed","terminal":true,"sequence":2}} Successful control: exit 0 elapsed_ms=2190 frames=1 samples=0 interactions=0 disposition=exited owned_process_group=cleaned terminal_renderer=cleaned temporary_root=cleaned ``` The failed stdout envelope reports `process_capture_failed`, category `execution_failure`, and an ENOENT diagnostic from helper-directory allocation. Its details contain only `execution_failure`. ### Typed outcome or recovery expected Keep the preparation failure and its error envelope truthful. The terminal cleanup message must include `disposition=failed` and all three documented resource-state keys, with states matching the actual preparation outcome. Repeat the nonexistent-directory attempt to verify those fields, then repeat the existing-directory control to preserve successful status reporting and valid capture Evidence. Suppressing the failed terminal line or making the invalid directory succeed would not restore the contract. ### Analysis or suspected cause Source-derived reasoning at the stated baseline: `src/application/process/ProcessCli.ts:52-100` validates the scenario and supplies the stderr progress reporter to the shared capture operation. `src/process/DarwinProcessRunTokenReader.ts:327` allocates the ownership-helper directory beneath the host temporary directory before target launch. `src/process/capture/ProcessHarness.ts:648-666` catches a preparation error and reports terminal cleanup with a disposition but without a cleanup report. `src/process/capture/ProcessCaptureProgress.ts:46-60` emits no resource-state text when that report is absent. This source trace explains the independently reproduced missing fields; it does not establish a failure to clean resources. ### Additional context Related to #3052, which corrected documentation about fields being inside `message`; this report concerns cleanup states missing from that message on a preparation failure. P2 impact is supported because consumers lose documented status data for a bounded failure. The reproduction establishes no leaked process, lost capture Evidence, or severe core-workflow impact.
bsakaguchi 2026-10-15 18:31:07 +00:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

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

Delivered on main in fffb07419.

Preparation failures ended progress without explicit resource states. Terminal progress now preserves unverified cleanup states when no cleanup report exists.

Validation: Process harness/progress regressions. This corrects reporting; it does not claim that the original preparation failure leaked a resource. Full exact-revision qualification passed.

<!-- gh-comment-id:6177598189 --> @morluto commented on GitHub (Oct 14, 2026): Delivered on main in [fffb07419](https://github.com/morluto/rea/commit/fffb0741936067530d1ce9777461cd53e87398c2). Preparation failures ended progress without explicit resource states. Terminal progress now preserves unverified cleanup states when no cleanup report exists. Validation: Process harness/progress regressions. This corrects reporting; it does not claim that the original preparation failure leaked a resource. Full exact-revision [qualification](https://github.com/morluto/rea/actions/runs/38629313022) passed.
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#1107
No description provided.