[PR #2185] fix(setup): show non-interactive setup results in a terminal #5071

Open
opened 2026-10-31 01:02:45 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/2185
Author: @balkan16
Created: 10/12/2026
Status: 🔄 Open

Base: main ← Head: fix/setup-dry-run-terminal


📝 Commits (10+)

  • b66b5d2 fix(setup): show non-interactive setup results in a terminal
  • b455300 fix(setup): show manual remediation in terminal dry runs
  • 39bea98 fix(setup): show partial and unapproved terminal setup results
  • 577b258 fix(setup): preserve terminal summaries and structured output coverage
  • 6102fa2 fix(setup): render blocked dry-run plans before remediation
  • 9629ed1 test(setup): decode piped results with their TOON format
  • 7531971 test(setup): separate output and terminal summary coverage
  • 1049fc5 fix(cli): report failed setup actions in terminal
  • e916654 fix(setup): show pending actions after cleanup failure
  • bb9152b fix(setup): report revalidated client outcomes

📊 Changes

9 files changed (+558 additions, -33 deletions)

View changed files

📝 package-lock.json (+1 -0)
📝 package.json (+1 -0)
📝 src/application/Setup.planning.test.ts (+1 -0)
📝 src/application/Setup.ts (+11 -8)
📝 src/application/SetupHost.ts (+9 -3)
📝 src/cli/interactiveSetup.ts (+154 -12)
📝 src/cli/setupCommands.ts (+14 -1)
📝 tests/boundary/cli/cliSetup.test.ts (+360 -0)
📝 tests/boundary/filesystem/setupClientConfigCleanupOwnership.test.ts (+7 -9)

📄 Description

Summary

In a terminal, a non-interactive rea setup --yes applied changes without printing anything, because setup uses the agent-only output policy. This adds a human summary for non-interactive apply results. Dry-run plans are now rendered by main (renderSetupDryRun), so this PR no longer touches dry runs. Structured output for pipes and explicit --format is unchanged.

Fixes #2164

Problem and expected behavior

On main, with a terminal stdout and no --format:

rea setup --yes --client codex --skill=false   # writes ~/.codex/config.toml, prints nothing
rea setup --client codex < /dev/null           # needs approval, prints nothing

Expected: the terminal shows the outcome. When a later step fails, it shows what already changed, which client failed and why, and which planned changes did not complete.

Change and scope

  • setupCommands.ts: after a non-interactive, non-dry-run setup, render a terminal summary under the condition incur uses to hide agent-only output (process.stdout.isTTY && !formatExplicit). The dry-run branch is main's, unchanged.
  • interactiveSetup.ts, renderTerminalSetupSummary:
    • ready / cancelled: the existing interactive result view.
    • needs_confirmation (stdin redirected): the approval plan, then how to approve.
    • needs_human: already applied actions (with the backup each kept client actually wrote), each failed client with its own recovery message from failedConfigurationMessage, planned actions that did not complete with the full approval-view disclosures, then setup's remediation.
  • Setup.ts / SetupHost.ts: clients that are already current after Hopper installation are recorded as unchanged, so they are not shown as pending.

Merged with main f255899: main's dry-run renderer and refusal handling are kept; this branch's earlier dry-run summary, its heading option and its dry-run tests were removed.

Not included: an already-current skill that is reinstalled as unchanged is not recorded in SetupResult, so a later failure can list it as not completed. Fixing that needs a SetupResult change and is left as a follow-up.

Contribution scope: an ordinary fix within existing boundaries; a maintainer scope decision is not applicable.

Contract and boundary impact

  • Semantic owner and earliest changed stage: CLI result projection for setup (src/cli/setupCommands.ts, src/cli/interactiveSetup.ts); unchanged client outcomes recorded in Setup.ts
  • Contribution scope fit and linked maintainer decision: ordinary fix; not applicable
  • CLI and MCP/tool-catalog contract: no schema change; terminal-only human lines on stderr; clients may now include unchanged entries for clients revalidated as current after Hopper installation
  • Provider, bridge, target-format, or platform compatibility: none
  • Evidence, artifact, provenance, or reconstruction contract: none
  • Target selection, authority, upstream behavior, and cleanup details (if applicable): approval semantics unchanged
  • Generated metadata (docs/public/product-catalog.json), package, or installation impact: test-only devDependency @toon-format/toon 2.3.1, used to decode the piped setup result; no runtime dependency change

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

  • Tests added or updated (tests/boundary/cli/cliSetup.test.ts), public scripts/rea.mjs setup under a real pseudo-terminal with an isolated home unless noted:
    • --yes --client codex --skill=false prints "Restart Codex to load REA." and writes the config
    • redirected stdin shows the approval plan and how to approve, and writes nothing
    • --yes --client codex --client opencode where OpenCode's config directory is unwritable (/proc/self/fdinfo, Linux only): "Already applied" lists Codex and its config, "FAILED OpenCode" carries its recovery message, nothing is listed as not completed
    • module-level: two failed clients each show their own recovery reason, including a rollback backup path
    • module-level: a client kept after a later failure shows the backup setup actually wrote, not the planned path
    • module-level: planned actions that did not complete show backup, network, integrity, command, detail and external-software disclosures
    • --format json, --json and piped output stay structured with no human lines
  • Base reproduction: with this branch's src/cli and src/application/Setup* files replaced by main's, the 5 apply tests fail; with the change they pass. With f0499bb reverted, the two disclosure and per-client-reason tests fail; with c582f4c reverted, the written-backup test fails.
  • User-visible output (terminal, partial failure):
◆  Already applied
│  CREATE  Codex
│          <home>/.codex/config.toml
◆  Failed configuration
│  FAILED  OpenCode
│          <home>/.config/opencode/opencode.json
│          Agent configuration could not be updated. Check file permissions, then rerun setup.
!  Agent configuration could not be updated. Check file permissions, then rerun setup.
|
—  Run `rea doctor` for the remaining checks.
  • Remaining proof gaps: macOS and Windows terminals not run; the partial-failure workflow test is Linux only.

For evidence-bearing changes:

  • 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/cli/cliSetup.test.ts — 23 passed
  • Same file with main's setup sources — 5 failed (the apply tests), 17 passed
  • npm run test:focused -- src/application/Setup.planning.test.ts tests/boundary/filesystem/setupClientConfigCleanupOwnership.test.ts tests/boundary/cli/clientProfiles.test.ts tests/boundary/cli/packageRunnerRegistration.test.ts tests/boundary/cli/cliSetup.test.ts — 67 passed
  • npm run check:fast — pass
  • npm run check:ci — pass (includes knip)
  • npm run verify:test-discovery — pass (1334 files)

Compatibility, safety, and release

  • Breaking changes or migration steps: none
  • Real Hopper/Ghidra, browser, or OS coverage: Linux pseudo-terminal only
  • Package or release metadata impact: test-only devDependency added; no runtime change
  • Security, privacy, process, or containment review: output only; prints paths and messages the structured result already contains

Author readiness

Human owner: @balkan16

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Q3rXQaLacJ7gNBRkp7DovF


🔄 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/2185 **Author:** [@balkan16](https://github.com/balkan16) **Created:** 10/12/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/setup-dry-run-terminal` --- ### 📝 Commits (10+) - [`b66b5d2`](https://github.com/morluto/rea/commit/b66b5d2265eb7bf43a577c4cdedb0174024773b9) fix(setup): show non-interactive setup results in a terminal - [`b455300`](https://github.com/morluto/rea/commit/b45530077a7ffbd2343cdd6b07d7c6f2e62b2375) fix(setup): show manual remediation in terminal dry runs - [`39bea98`](https://github.com/morluto/rea/commit/39bea98e608467018f5d4359ccf2c1ce1b4777a1) fix(setup): show partial and unapproved terminal setup results - [`577b258`](https://github.com/morluto/rea/commit/577b2582ebd9b7e5a2252ff3dcd1006704a57b01) fix(setup): preserve terminal summaries and structured output coverage - [`6102fa2`](https://github.com/morluto/rea/commit/6102fa2cf3e215ad4414836f57ad9b17d9c3a851) fix(setup): render blocked dry-run plans before remediation - [`9629ed1`](https://github.com/morluto/rea/commit/9629ed163c6f5b70dbff61366e03df0abe65b079) test(setup): decode piped results with their TOON format - [`7531971`](https://github.com/morluto/rea/commit/75319717206eeddefd16ff587f867a59ea2f17fb) test(setup): separate output and terminal summary coverage - [`1049fc5`](https://github.com/morluto/rea/commit/1049fc5363227070677a67914b66df80ab3ba3e3) fix(cli): report failed setup actions in terminal - [`e916654`](https://github.com/morluto/rea/commit/e916654e99052e690b5318ad2d2f45d83269adec) fix(setup): show pending actions after cleanup failure - [`bb9152b`](https://github.com/morluto/rea/commit/bb9152b611d83919d7d4a3444ec3343250cd236c) fix(setup): report revalidated client outcomes ### 📊 Changes **9 files changed** (+558 additions, -33 deletions) <details> <summary>View changed files</summary> 📝 `package-lock.json` (+1 -0) 📝 `package.json` (+1 -0) 📝 `src/application/Setup.planning.test.ts` (+1 -0) 📝 `src/application/Setup.ts` (+11 -8) 📝 `src/application/SetupHost.ts` (+9 -3) 📝 `src/cli/interactiveSetup.ts` (+154 -12) 📝 `src/cli/setupCommands.ts` (+14 -1) 📝 `tests/boundary/cli/cliSetup.test.ts` (+360 -0) 📝 `tests/boundary/filesystem/setupClientConfigCleanupOwnership.test.ts` (+7 -9) </details> ### 📄 Description ## Summary In a terminal, a non-interactive `rea setup --yes` applied changes without printing anything, because `setup` uses the agent-only output policy. This adds a human summary for non-interactive apply results. Dry-run plans are now rendered by main (`renderSetupDryRun`), so this PR no longer touches dry runs. Structured output for pipes and explicit `--format` is unchanged. Fixes #2164 ## Problem and expected behavior On main, with a terminal stdout and no `--format`: ``` rea setup --yes --client codex --skill=false # writes ~/.codex/config.toml, prints nothing rea setup --client codex < /dev/null # needs approval, prints nothing ``` Expected: the terminal shows the outcome. When a later step fails, it shows what already changed, which client failed and why, and which planned changes did not complete. ## Change and scope - `setupCommands.ts`: after a non-interactive, non-dry-run setup, render a terminal summary under the condition incur uses to hide agent-only output (`process.stdout.isTTY && !formatExplicit`). The dry-run branch is main's, unchanged. - `interactiveSetup.ts`, `renderTerminalSetupSummary`: - `ready` / `cancelled`: the existing interactive result view. - `needs_confirmation` (stdin redirected): the approval plan, then how to approve. - `needs_human`: already applied actions (with the backup each kept client actually wrote), each failed client with its own recovery message from `failedConfigurationMessage`, planned actions that did not complete with the full approval-view disclosures, then setup's remediation. - `Setup.ts` / `SetupHost.ts`: clients that are already current after Hopper installation are recorded as `unchanged`, so they are not shown as pending. Merged with main f255899: main's dry-run renderer and refusal handling are kept; this branch's earlier dry-run summary, its heading option and its dry-run tests were removed. Not included: an already-current skill that is reinstalled as unchanged is not recorded in `SetupResult`, so a later failure can list it as not completed. Fixing that needs a `SetupResult` change and is left as a follow-up. Contribution scope: an ordinary fix within existing boundaries; a maintainer scope decision is not applicable. ## Contract and boundary impact - Semantic owner and earliest changed stage: CLI result projection for `setup` (`src/cli/setupCommands.ts`, `src/cli/interactiveSetup.ts`); `unchanged` client outcomes recorded in `Setup.ts` - Contribution scope fit and linked maintainer decision: ordinary fix; not applicable - CLI and MCP/tool-catalog contract: no schema change; terminal-only human lines on stderr; `clients` may now include `unchanged` entries for clients revalidated as current after Hopper installation - Provider, bridge, target-format, or platform compatibility: none - Evidence, artifact, provenance, or reconstruction contract: none - Target selection, authority, upstream behavior, and cleanup details (if applicable): approval semantics unchanged - Generated metadata (`docs/public/product-catalog.json`), package, or installation impact: test-only devDependency `@toon-format/toon` 2.3.1, used to decode the piped setup result; no runtime dependency change Expected effects: - [ ] Read existing files or captured data. - [ ] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [x] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage - Tests added or updated (`tests/boundary/cli/cliSetup.test.ts`), public `scripts/rea.mjs setup` under a real pseudo-terminal with an isolated home unless noted: - `--yes --client codex --skill=false` prints "Restart Codex to load REA." and writes the config - redirected stdin shows the approval plan and how to approve, and writes nothing - `--yes --client codex --client opencode` where OpenCode's config directory is unwritable (`/proc/self/fdinfo`, Linux only): "Already applied" lists Codex and its config, "FAILED OpenCode" carries its recovery message, nothing is listed as not completed - module-level: two failed clients each show their own recovery reason, including a rollback backup path - module-level: a client kept after a later failure shows the backup setup actually wrote, not the planned path - module-level: planned actions that did not complete show backup, network, integrity, command, detail and external-software disclosures - `--format json`, `--json` and piped output stay structured with no human lines - Base reproduction: with this branch's `src/cli` and `src/application/Setup*` files replaced by main's, the 5 apply tests fail; with the change they pass. With f0499bb reverted, the two disclosure and per-client-reason tests fail; with c582f4c reverted, the written-backup test fails. - User-visible output (terminal, partial failure): ``` ◆ Already applied │ CREATE Codex │ <home>/.codex/config.toml ◆ Failed configuration │ FAILED OpenCode │ <home>/.config/opencode/opencode.json │ Agent configuration could not be updated. Check file permissions, then rerun setup. ! Agent configuration could not be updated. Check file permissions, then rerun setup. | — Run `rea doctor` for the remaining checks. ``` - Remaining proof gaps: macOS and Windows terminals not run; the partial-failure workflow test is Linux only. For evidence-bearing changes: - [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/cli/cliSetup.test.ts` — 23 passed - Same file with main's setup sources — 5 failed (the apply tests), 17 passed - `npm run test:focused -- src/application/Setup.planning.test.ts tests/boundary/filesystem/setupClientConfigCleanupOwnership.test.ts tests/boundary/cli/clientProfiles.test.ts tests/boundary/cli/packageRunnerRegistration.test.ts tests/boundary/cli/cliSetup.test.ts` — 67 passed - `npm run check:fast` — pass - `npm run check:ci` — pass (includes knip) - `npm run verify:test-discovery` — pass (1334 files) ## Compatibility, safety, and release - Breaking changes or migration steps: none - Real Hopper/Ghidra, browser, or OS coverage: Linux pseudo-terminal only - Package or release metadata impact: test-only devDependency added; no runtime change - Security, privacy, process, or containment review: output only; prints paths and messages the structured result already contains ## Author readiness Human owner: @balkan16 - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01Q3rXQaLacJ7gNBRkp7DovF --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
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#5071
No description provided.