aterm: render --dry-run for a person, and split failure exit codes #1254

Closed
opened 2026-08-26 02:49:18 +00:00 by coilyco-ops · 1 comment
Member

Part of #1245. Two output-surface changes in the same neighbourhood.

Readable --dry-run

runLaunch prints a raw indented JSON plan and nothing else. That is correct for aos-release-check, which asserts against it, and wrong for the operator squinting at a hex value to decide whether the brand looks right.

Compose a summary with truecolor blocks for the accent and the derived background alongside the identity and child argv. Move the current output behind --dry-run --json and keep release-check on that path.

Exit codes

Every failure out of main exits 1, so a caller distinguishing a stale role from a missing binary has to grep prose. Split:

  • 2 usage
  • 3 off-roster role or seat
  • 4 missing dependency on PATH
  • 5 spawn failure
  • child exit code passed through untouched

Release checks then assert behavior rather than wording. _session already exits 2 on a bad argument list, so that one is consistent already.

Opportunistic while in here

interactiveTTY requires stdin and stdout to both be character devices, so aterm > log disables the role picker rather than just redirecting output. Reproduced:

$ aterm > /tmp/log 2>&1 </dev/null
aterm: a role is required when aterm is not attached to a terminal

Roughly 8 lines to point the form at /dev/tty. It also almost never fires, since every path that genuinely lacks a terminal has no terminal to prompt on either. Fix it if the output routing is already open, do not schedule it separately.

aterm/main.go, aterm/picker.go, aterm/session.go.

Part of #1245. Two output-surface changes in the same neighbourhood. ## Readable `--dry-run` `runLaunch` prints a raw indented JSON plan and nothing else. That is correct for `aos-release-check`, which asserts against it, and wrong for the operator squinting at a hex value to decide whether the brand looks right. Compose a summary with truecolor blocks for the accent and the derived background alongside the identity and child argv. Move the current output behind `--dry-run --json` and keep release-check on that path. ## Exit codes Every failure out of `main` exits 1, so a caller distinguishing a stale role from a missing binary has to grep prose. Split: - 2 usage - 3 off-roster role or seat - 4 missing dependency on PATH - 5 spawn failure - child exit code passed through untouched Release checks then assert behavior rather than wording. `_session` already exits 2 on a bad argument list, so that one is consistent already. ## Opportunistic while in here `interactiveTTY` requires stdin **and** stdout to both be character devices, so `aterm > log` disables the role picker rather than just redirecting output. Reproduced: ``` $ aterm > /tmp/log 2>&1 </dev/null aterm: a role is required when aterm is not attached to a terminal ``` Roughly 8 lines to point the form at `/dev/tty`. It also almost never fires, since every path that genuinely lacks a terminal has no terminal to prompt on either. Fix it if the output routing is already open, do not schedule it separately. `aterm/main.go`, `aterm/picker.go`, `aterm/session.go`.
Author
Member

Re-verified on main at d24e5d5a. Both halves still hold, unchanged by the kitty swap.

--dry-run is still raw JSON: runLaunch does json.MarshalIndent(plan, "", " ") and prints it, with no human form.

Exit codes are still flat. main() has exactly three exits:

os.Exit(2)                    // _session bad argument list
os.Exit(runSession(...))      // child code passed through
os.Exit(1)                    // every launcher error, no exceptions

So the stale-role refusal, the missing-binary refusal, and the spawn failure are all indistinguishable at 1 today, as filed.

One addition from the kitty swap. scripts/check-aos-release.sh now asserts the brand survives into the terminal arguments, and the #1264 comment records that the old gate would have passed a assert plan["executable"] == "alacritty" check silently. Whatever moves behind --dry-run --json has to keep that gate green, so treat the release check as the compatibility contract for the JSON form rather than something to re-derive.

Re-verified on `main` at `d24e5d5a`. **Both halves still hold, unchanged by the kitty swap.** `--dry-run` is still raw JSON: `runLaunch` does `json.MarshalIndent(plan, "", " ")` and prints it, with no human form. Exit codes are still flat. `main()` has exactly three exits: ```go os.Exit(2) // _session bad argument list os.Exit(runSession(...)) // child code passed through os.Exit(1) // every launcher error, no exceptions ``` So the stale-role refusal, the missing-binary refusal, and the spawn failure are all indistinguishable at 1 today, as filed. **One addition from the kitty swap.** `scripts/check-aos-release.sh` now asserts the brand survives into the terminal arguments, and the #1264 comment records that the old gate would have passed a `assert plan["executable"] == "alacritty"` check silently. Whatever moves behind `--dry-run --json` has to keep that gate green, so treat the release check as the compatibility contract for the JSON form rather than something to re-derive.
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
coilyco-flight-deck/agentic-os#1254
No description provided.