diff --git a/crates/pi-shell/src/shell.rs b/crates/pi-shell/src/shell.rs index cd559502a..5e1ede5b2 100644 --- a/crates/pi-shell/src/shell.rs +++ b/crates/pi-shell/src/shell.rs @@ -5019,8 +5019,8 @@ fn parse_ps_format( "sid" | "sess" => PsField::Sid, "tpgid" => PsField::Tpgid, "tty" | "tt" | "tname" => PsField::Tty, - "stat" => PsField::State, - "state" | "s" => PsField::StateChar, + "stat" | "state" => PsField::State, + "s" => PsField::StateChar, "start" | "stime" | "bsdstart" => PsField::Start, "lstart" | "start_time" => PsField::LongStart, "etime" | "elapsed" => PsField::Elapsed, @@ -6593,6 +6593,27 @@ mod tests { } } + #[tokio::test(flavor = "multi_thread")] + async fn ps_builtin_accepts_tpgid_alongside_job_control_columns() { + // Exact form from the field report that failed with + // "unknown output format specifier 'tpgid'". + let pid = std::process::id(); + let (result, output) = + execute_captured(format!("ps -o pid,ppid,pgid,tpgid,sess,stat,tty,command -p {pid}")) + .await; + assert_eq!(result.exit_code, Some(0), "{output:?}"); + let header = output.lines().next().unwrap_or_default(); + for label in ["PID", "PPID", "PGID", "TPGID", "SID", "STAT", "TTY", "COMMAND"] { + assert!(header.contains(label), "missing {label} in {header:?}"); + } + assert!(output.lines().skip(1).any(|line| { + line + .split_whitespace() + .next() + .is_some_and(|value| value == pid.to_string()) + })); + } + #[tokio::test(flavor = "multi_thread")] async fn top_builtin_emits_one_finite_snapshot() { #[cfg(target_os = "macos")] diff --git a/packages/natives/CHANGELOG.md b/packages/natives/CHANGELOG.md index af31ff2c7..43617a5ff 100644 --- a/packages/natives/CHANGELOG.md +++ b/packages/natives/CHANGELOG.md @@ -4,7 +4,7 @@ ### Added -- Added the missing procps/BSD output format specifiers to the in-process ps shell builtin: `tpgid`, `pri`, `f`/`flags`, `ruser`/`logname`, `ruid`, `rgroup`, `rgid`, `group`/`egroup`, `gid`/`egid`, `wchan`, `min_flt`/`maj_flt`, `times`/`cputimes`, `sz`, single-character `s`/`state`, and aliases `tgid`/`tid`/`spid`, `euser`, `bsdtime`, and `rsz`. `ps -j` now includes a TPGID column, `ps -l` prints the single-character S column, and STAT gains the `+` foreground flag for processes in their terminal's foreground process group. +- Added the missing procps/BSD output format specifiers to the in-process ps shell builtin: `tpgid`, `pri`, `f`/`flags`, `ruser`/`logname`, `ruid`, `rgroup`, `rgid`, `group`/`egroup`, `gid`/`egid`, `wchan`, `min_flt`/`maj_flt`, `times`/`cputimes`, `sz`, single-character `s`, and aliases `state`, `tgid`/`tid`/`spid`, `euser`, `bsdtime`, and `rsz`. `ps -j` now includes a TPGID column, `ps -l` prints the single-character S column, and STAT gains the `+` foreground flag for processes in their terminal's foreground process group. ## [17.2.6] - 2026-08-03