Commit 6c3ef6a
feat: terminal steps - tty/interactive fields and exec step type (#2602)
* feat(commands): add tty/interactive step schema fields and interrupt suspension
Add Interactive/Tty bools to Task and WorkflowStep with converter mappings.
Add pkg/signals with a nestable interrupt-exit suspension counter, consulted
by the main signal handler so foreground interactive steps own Ctrl-C.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(pty): don't block completion on stdin copier; add DisableStdinForward
The stdin copy goroutine was joined via WaitGroup, but io.Copy from a
terminal only returns on the next read after the PTY closes - so ExecWithPTY
hung until a keypress after the child exited. Detach the stdin copier
(docker-CLI pattern) and drain IO errors non-blockingly.
DisableStdinForward supports docker's -t-without-i semantics: the child gets
a TTY but host input is not forwarded and the host terminal stays cooked.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(process): add RunShellSession for terminal-attached shell steps
Runs a shell command attached to the user's terminal: under a PTY when
supported (masking preserved, raw mode routes Ctrl-C to the child for
interactive sessions), otherwise via direct fd inheritance with a visible
warning that masking is unavailable. Interactive sessions suspend the global
SIGINT-exit handler; child exit codes propagate as ExitCodeError.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(commands): route tty/interactive custom command steps to terminal sessions
Shell steps with tty: true attach the user's terminal via RunShellSession;
interactive: true suspends the Atmos SIGINT-exit handler so the step owns
Ctrl-C. Plain steps keep the existing masked shell-interpreter path.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(workflows): support tty/interactive shell steps
Workflow shell steps with tty: true attach the user's terminal via
RunShellSession (output modes don't apply); interactive: true suspends the
Atmos SIGINT-exit handler so the step owns Ctrl-C.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(runner): support tty/interactive shell tasks in task runner and step handler
Shell tasks with tty: true attach the user's terminal via RunShellSession
(no capturable output; exit code recorded in metadata). Interactive tasks
attach host stdin, force raw output mode (buffered modes would hide prompts),
and suspend the Atmos SIGINT-exit handler while running.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: document tty/interactive steps; update schemas, changelog, roadmap
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs(roadmap): link tty/interactive steps milestone to PR #2602
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(steps): add exec step type that replaces the Atmos process
Steps with type: exec hand the process over entirely (shell exec semantics):
execve of the system shell on Unix (inheriting env, working directory, and
the terminal natively; ATMOS_SHLVL unchanged), spawn-and-propagate-exit-code
emulation on Windows. Exec steps are validated to be the final step and must
not set supervisor-only fields (tty, interactive, retry, timeout, output).
Wired into custom commands, workflows, and the task runner.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor(steps): route interactive steps through RunShellSession; cross-platform test helpers
Interactive (non-tty) steps now use the shell session path so suspension and
platform-aware shell selection live in one place (pkg/process); dry-run is
checked before shell-level validation; the runner env inherits os.Environ.
Tests use the test binary as a cross-platform subprocess helper.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(process): only warn about lost masking when a tty was requested
Interactive (non-tty) sessions always attach the real streams, so missing
masking is inherent there - debug-log it instead of warning on every step.
The visible warning remains for the unexpected case: tty requested but PTY
unavailable on the platform.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor(steps): keep cmd/ and internal/exec to bare call sites
Move shell-family step routing into pkg/process.RunShellStep (terminal steps
to sessions, plain steps via caller fallback) and default masking wiring
inside RunShellSession. Delete the cmd/ step helper file and the internal/exec
helper - both locations now contain only inline switch-case call sites; the
runner and step handler use the same shared routing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(pty): bound session teardown when grandchildren hold the PTY slave
When the session command exits, grandchildren that inherited the PTY slave
(e.g. aws ssm's session-manager-plugin) can keep it open, so the output
copier never gets EIO: atmos hung with the terminal in raw mode (no prompt
until a stray keypress, no echo afterwards). Drain output on a 1s deadline
after child exit, forcing the pending read to return so the terminal is
restored promptly.
Reported-by: live SSM session test on PR #2602
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(tests): suppress terminal queries from PTY test children
The test binary used as a PTY child links TUI libraries that emit OSC/DSR
terminal queries when stdout is a TTY and block ~5s per query waiting for
replies no test PTY sends - hanging three pty tests past their deadlines and
silently adding ~15s to the process suite. TERM=dumb/NO_COLOR in the child
env suppresses the queries (pty suite 25s+fail -> 1.5s; process 16.6s -> 1.6s).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test: update workflow step-type hint expectations for exec
The invalid-step-type hint now lists 'exec' among valid types; update the
test-case pattern and regenerate the golden snapshot (-regenerate-snapshots).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(process): build cmd.exe session commands verbatim with /S /C
Go converts argv to a process command line with C quoting rules, which
cmd.exe does not parse - any quoted session command broke on Windows
('"C:\..." is not recognized'). Build the command line verbatim via
SysProcAttr.CmdLine using cmd.exe /S /C "<command>" so cmd strips exactly
the outer quotes and runs the command literally. Test helper now quotes
Windows args plainly (the child parses standard quoting).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs(schema): list TaskTypeExec in Task.Type field comment
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test: raise patch coverage for terminal step paths
- exec failure paths (LookPath miss, execve ENOEXEC) covered in-process
- attached-session TTY masking warning branch and nil-context default
- pty drain deadline, benign copy errors, isPtyEIO truth table
- workflow exec step dry-run routing and not-last validation via ExecuteWorkflow
- WorkflowStep exec validation rows for tty/interactive/retry (CodeRabbit)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(process): shell-convention exit codes for signal-killed sessions; restore terminal on signal exit
Sessions whose child died from a signal now report 128+signal (e.g. 130)
instead of Go's -1 ('subcommand exited with code -1'). The PTY terminal
restore is also registered as a signal-exit cleanup: os.Exit in the signal
handler skips defers, which could leave the host terminal in raw mode when
atmos was signalled mid-session.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: document the exec step type; extend changelog and roadmap
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(process): exit silently on non-zero terminal-session exit (no post-session hang)
A tty/interactive/exec session that exits non-zero produced a bare
ExitCodeError that Atmos rendered through the themed Glamour formatter. That
render triggers termenv's terminal queries (OSC 11 background color, DSR
cursor) and reads the reply from os.Stdin - but the session's stdin copier
steals it, so termenv blocks for its full ~5s timeout before the process
exits (Matt's '3-5s then code -1'; Erik's hang on a failed-command exit).
Mark session ExitCodeErrors Silent so the code propagates like a shell would,
with no themed error box and no terminal query. Honored in
CheckErrorPrintAndExit (custom commands), main.run (workflows), and the
workflow step-error wrapper. Before: 5.0s on non-zero exit; after: 3ms.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>1 parent 7fc9c3e commit 6c3ef6a
43 files changed
Lines changed: 2674 additions & 45 deletions
File tree
- cmd
- errors
- internal/exec
- pkg
- datafetcher/schema
- atmos/manifest
- config/global
- process
- runner
- step
- schema
- signals
- terminal/pty
- tests
- snapshots
- test-cases
- website
- blog
- docs
- cli/configuration
- workflows
- src/data
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| 34 | + | |
34 | 35 | | |
35 | 36 | | |
36 | 37 | | |
| |||
729 | 730 | | |
730 | 731 | | |
731 | 732 | | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
732 | 740 | | |
733 | 741 | | |
734 | 742 | | |
| |||
892 | 900 | | |
893 | 901 | | |
894 | 902 | | |
| 903 | + | |
| 904 | + | |
895 | 905 | | |
896 | | - | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
| 923 | + | |
897 | 924 | | |
898 | 925 | | |
899 | 926 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
336 | 336 | | |
337 | 337 | | |
338 | 338 | | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
339 | 348 | | |
340 | 349 | | |
341 | 350 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
123 | 123 | | |
124 | 124 | | |
125 | 125 | | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
126 | 152 | | |
127 | 153 | | |
128 | 154 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1223 | 1223 | | |
1224 | 1224 | | |
1225 | 1225 | | |
| 1226 | + | |
| 1227 | + | |
| 1228 | + | |
| 1229 | + | |
| 1230 | + | |
| 1231 | + | |
1226 | 1232 | | |
1227 | 1233 | | |
1228 | 1234 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
| 30 | + | |
30 | 31 | | |
31 | 32 | | |
32 | 33 | | |
| |||
279 | 280 | | |
280 | 281 | | |
281 | 282 | | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
282 | 295 | | |
283 | 296 | | |
284 | 297 | | |
| |||
402 | 415 | | |
403 | 416 | | |
404 | 417 | | |
| 418 | + | |
| 419 | + | |
405 | 420 | | |
406 | 421 | | |
407 | 422 | | |
408 | | - | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
409 | 446 | | |
410 | 447 | | |
411 | 448 | | |
| |||
464 | 501 | | |
465 | 502 | | |
466 | 503 | | |
467 | | - | |
| 504 | + | |
468 | 505 | | |
469 | 506 | | |
470 | 507 | | |
| |||
476 | 513 | | |
477 | 514 | | |
478 | 515 | | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
479 | 523 | | |
480 | 524 | | |
481 | 525 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1694 | 1694 | | |
1695 | 1695 | | |
1696 | 1696 | | |
| 1697 | + | |
| 1698 | + | |
| 1699 | + | |
| 1700 | + | |
| 1701 | + | |
| 1702 | + | |
| 1703 | + | |
| 1704 | + | |
| 1705 | + | |
| 1706 | + | |
| 1707 | + | |
| 1708 | + | |
| 1709 | + | |
| 1710 | + | |
| 1711 | + | |
| 1712 | + | |
| 1713 | + | |
| 1714 | + | |
| 1715 | + | |
| 1716 | + | |
| 1717 | + | |
| 1718 | + | |
| 1719 | + | |
| 1720 | + | |
| 1721 | + | |
| 1722 | + | |
| 1723 | + | |
| 1724 | + | |
| 1725 | + | |
| 1726 | + | |
| 1727 | + | |
| 1728 | + | |
| 1729 | + | |
| 1730 | + | |
| 1731 | + | |
| 1732 | + | |
| 1733 | + | |
| 1734 | + | |
| 1735 | + | |
| 1736 | + | |
| 1737 | + | |
| 1738 | + | |
| 1739 | + | |
| 1740 | + | |
| 1741 | + | |
| 1742 | + | |
| 1743 | + | |
| 1744 | + | |
| 1745 | + | |
| 1746 | + | |
| 1747 | + | |
| 1748 | + | |
| 1749 | + | |
| 1750 | + | |
| 1751 | + | |
| 1752 | + | |
| 1753 | + | |
| 1754 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
| 15 | + | |
14 | 16 | | |
15 | 17 | | |
16 | 18 | | |
17 | 19 | | |
18 | 20 | | |
19 | 21 | | |
20 | 22 | | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
28 | 41 | | |
29 | | - | |
30 | | - | |
31 | 42 | | |
32 | 43 | | |
33 | 44 | | |
| |||
81 | 92 | | |
82 | 93 | | |
83 | 94 | | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
84 | 102 | | |
85 | 103 | | |
86 | 104 | | |
| |||
97 | 115 | | |
98 | 116 | | |
99 | 117 | | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
100 | 137 | | |
101 | 138 | | |
102 | 139 | | |
| |||
0 commit comments