chore: clean up argument-comment lint and roll out all-target CI on macOS (#16054)

## Why

`argument-comment-lint` was green in CI even though the repo still had
many uncommented literal arguments. The main gap was target coverage:
the repo wrapper did not force Cargo to inspect test-only call sites, so
examples like the `latest_session_lookup_params(true, ...)` tests in
`codex-rs/tui_app_server/src/lib.rs` never entered the blocking CI path.

This change cleans up the existing backlog, makes the default repo lint
path cover all Cargo targets, and starts rolling that stricter CI
enforcement out on the platform where it is currently validated.

## What changed

- mechanically fixed existing `argument-comment-lint` violations across
the `codex-rs` workspace, including tests, examples, and benches
- updated `tools/argument-comment-lint/run-prebuilt-linter.sh` and
`tools/argument-comment-lint/run.sh` so non-`--fix` runs default to
`--all-targets` unless the caller explicitly narrows the target set
- fixed both wrappers so forwarded cargo arguments after `--` are
preserved with a single separator
- documented the new default behavior in
`tools/argument-comment-lint/README.md`
- updated `rust-ci` so the macOS lint lane keeps the plain wrapper
invocation and therefore enforces `--all-targets`, while Linux and
Windows temporarily pass `-- --lib --bins`

That temporary CI split keeps the stricter all-targets check where it is
already cleaned up, while leaving room to finish the remaining Linux-
and Windows-specific target-gated cleanup before enabling
`--all-targets` on those runners. The Linux and Windows failures on the
intermediate revision were caused by the wrapper forwarding bug, not by
additional lint findings in those lanes.

## Validation

- `bash -n tools/argument-comment-lint/run.sh`
- `bash -n tools/argument-comment-lint/run-prebuilt-linter.sh`
- shell-level wrapper forwarding check for `-- --lib --bins`
- shell-level wrapper forwarding check for `-- --tests`
- `just argument-comment-lint`
- `cargo test` in `tools/argument-comment-lint`
- `cargo test -p codex-terminal-detection`

## Follow-up

- Clean up remaining Linux-only target-gated callsites, then switch the
Linux lint lane back to the plain wrapper invocation.
- Clean up remaining Windows-only target-gated callsites, then switch
the Windows lint lane back to the plain wrapper invocation.
This commit is contained in:
Michael Bolin
2026-03-27 19:00:44 -07:00
committed by GitHub
Unverified
parent ed977b42ac
commit 61dfe0b86c
307 changed files with 7724 additions and 4710 deletions
@@ -6,11 +6,13 @@ use pretty_assertions::assert_eq;
fn split_valid_utf8_prefix_respects_max_bytes_for_ascii() {
let mut buf = b"hello word!".to_vec();
let first = split_valid_utf8_prefix_with_max(&mut buf, 5).expect("expected prefix");
let first =
split_valid_utf8_prefix_with_max(&mut buf, /*max_bytes*/ 5).expect("expected prefix");
assert_eq!(first, b"hello".to_vec());
assert_eq!(buf, b" word!".to_vec());
let second = split_valid_utf8_prefix_with_max(&mut buf, 5).expect("expected prefix");
let second =
split_valid_utf8_prefix_with_max(&mut buf, /*max_bytes*/ 5).expect("expected prefix");
assert_eq!(second, b" word".to_vec());
assert_eq!(buf, b"!".to_vec());
}
@@ -20,7 +22,8 @@ fn split_valid_utf8_prefix_avoids_splitting_utf8_codepoints() {
// "é" is 2 bytes in UTF-8. With a max of 3 bytes, we should only emit 1 char (2 bytes).
let mut buf = "ééé".as_bytes().to_vec();
let first = split_valid_utf8_prefix_with_max(&mut buf, 3).expect("expected prefix");
let first =
split_valid_utf8_prefix_with_max(&mut buf, /*max_bytes*/ 3).expect("expected prefix");
assert_eq!(std::str::from_utf8(&first).unwrap(), "é");
assert_eq!(buf, "éé".as_bytes().to_vec());
}
@@ -29,7 +32,8 @@ fn split_valid_utf8_prefix_avoids_splitting_utf8_codepoints() {
fn split_valid_utf8_prefix_makes_progress_on_invalid_utf8() {
let mut buf = vec![0xff, b'a', b'b'];
let first = split_valid_utf8_prefix_with_max(&mut buf, 2).expect("expected prefix");
let first =
split_valid_utf8_prefix_with_max(&mut buf, /*max_bytes*/ 2).expect("expected prefix");
assert_eq!(first, vec![0xff]);
assert_eq!(buf, b"ab".to_vec());
}
@@ -4,7 +4,7 @@ use pretty_assertions::assert_eq;
#[test]
fn keeps_prefix_and_suffix_when_over_budget() {
let mut buf = HeadTailBuffer::new(10);
let mut buf = HeadTailBuffer::new(/*max_bytes*/ 10);
buf.push_chunk(b"0123456789".to_vec());
assert_eq!(buf.omitted_bytes(), 0);
@@ -20,7 +20,7 @@ fn keeps_prefix_and_suffix_when_over_budget() {
#[test]
fn max_bytes_zero_drops_everything() {
let mut buf = HeadTailBuffer::new(0);
let mut buf = HeadTailBuffer::new(/*max_bytes*/ 0);
buf.push_chunk(b"abc".to_vec());
assert_eq!(buf.retained_bytes(), 0);
@@ -31,7 +31,7 @@ fn max_bytes_zero_drops_everything() {
#[test]
fn head_budget_zero_keeps_only_last_byte_in_tail() {
let mut buf = HeadTailBuffer::new(1);
let mut buf = HeadTailBuffer::new(/*max_bytes*/ 1);
buf.push_chunk(b"abc".to_vec());
assert_eq!(buf.retained_bytes(), 1);
@@ -41,7 +41,7 @@ fn head_budget_zero_keeps_only_last_byte_in_tail() {
#[test]
fn draining_resets_state() {
let mut buf = HeadTailBuffer::new(10);
let mut buf = HeadTailBuffer::new(/*max_bytes*/ 10);
buf.push_chunk(b"0123456789".to_vec());
buf.push_chunk(b"ab".to_vec());
@@ -55,7 +55,7 @@ fn draining_resets_state() {
#[test]
fn chunk_larger_than_tail_budget_keeps_only_tail_end() {
let mut buf = HeadTailBuffer::new(10);
let mut buf = HeadTailBuffer::new(/*max_bytes*/ 10);
buf.push_chunk(b"0123456789".to_vec());
// Tail budget is 5 bytes. This chunk should replace the tail and keep only its last 5 bytes.
@@ -69,7 +69,7 @@ fn chunk_larger_than_tail_budget_keeps_only_tail_end() {
#[test]
fn fills_head_then_tail_across_multiple_chunks() {
let mut buf = HeadTailBuffer::new(10);
let mut buf = HeadTailBuffer::new(/*max_bytes*/ 10);
// Fill the 5-byte head budget across multiple chunks.
buf.push_chunk(b"01".to_vec());
+63 -29
View File
@@ -33,7 +33,15 @@ async fn exec_command(
yield_time_ms: u64,
workdir: Option<PathBuf>,
) -> Result<ExecCommandToolOutput, UnifiedExecError> {
exec_command_with_tty(session, turn, cmd, yield_time_ms, workdir, true).await
exec_command_with_tty(
session,
turn,
cmd,
yield_time_ms,
workdir,
/*tty*/ true,
)
.await
}
fn shell_env() -> HashMap<String, String> {
@@ -227,14 +235,17 @@ async fn unified_exec_persists_across_requests() -> anyhow::Result<()> {
let (session, turn) = test_session_and_turn().await;
let open_shell = exec_command(&session, &turn, "bash -i", 2_500, None).await?;
let open_shell = exec_command(
&session, &turn, "bash -i", /*yield_time_ms*/ 2_500, /*workdir*/ None,
)
.await?;
let process_id = open_shell.process_id.expect("expected process_id");
write_stdin(
&session,
process_id,
"export CODEX_INTERACTIVE_SHELL_VAR=codex\n",
2_500,
/*yield_time_ms*/ 2_500,
)
.await?;
@@ -242,7 +253,7 @@ async fn unified_exec_persists_across_requests() -> anyhow::Result<()> {
&session,
process_id,
"echo $CODEX_INTERACTIVE_SHELL_VAR\n",
2_500,
/*yield_time_ms*/ 2_500,
)
.await?;
assert!(
@@ -259,14 +270,17 @@ async fn multi_unified_exec_sessions() -> anyhow::Result<()> {
let (session, turn) = test_session_and_turn().await;
let shell_a = exec_command(&session, &turn, "bash -i", 2_500, None).await?;
let shell_a = exec_command(
&session, &turn, "bash -i", /*yield_time_ms*/ 2_500, /*workdir*/ None,
)
.await?;
let session_a = shell_a.process_id.expect("expected process id");
write_stdin(
&session,
session_a,
"export CODEX_INTERACTIVE_SHELL_VAR=codex\n",
2_500,
/*yield_time_ms*/ 2_500,
)
.await?;
@@ -274,8 +288,8 @@ async fn multi_unified_exec_sessions() -> anyhow::Result<()> {
&session,
&turn,
"echo $CODEX_INTERACTIVE_SHELL_VAR",
2_500,
None,
/*yield_time_ms*/ 2_500,
/*workdir*/ None,
)
.await?;
tokio::time::sleep(Duration::from_secs(2)).await;
@@ -292,7 +306,7 @@ async fn multi_unified_exec_sessions() -> anyhow::Result<()> {
&session,
shell_a.process_id.expect("expected process id"),
"echo $CODEX_INTERACTIVE_SHELL_VAR\n",
2_500,
/*yield_time_ms*/ 2_500,
)
.await?;
assert!(
@@ -311,14 +325,17 @@ async fn unified_exec_timeouts() -> anyhow::Result<()> {
let (session, turn) = test_session_and_turn().await;
let open_shell = exec_command(&session, &turn, "bash -i", 2_500, None).await?;
let open_shell = exec_command(
&session, &turn, "bash -i", /*yield_time_ms*/ 2_500, /*workdir*/ None,
)
.await?;
let process_id = open_shell.process_id.expect("expected process id");
write_stdin(
&session,
process_id,
format!("export CODEX_INTERACTIVE_SHELL_VAR={TEST_VAR_VALUE}\n").as_str(),
2_500,
/*yield_time_ms*/ 2_500,
)
.await?;
@@ -326,7 +343,7 @@ async fn unified_exec_timeouts() -> anyhow::Result<()> {
&session,
process_id,
"sleep 5 && echo $CODEX_INTERACTIVE_SHELL_VAR\n",
10,
/*yield_time_ms*/ 10,
)
.await?;
assert!(
@@ -336,7 +353,7 @@ async fn unified_exec_timeouts() -> anyhow::Result<()> {
tokio::time::sleep(Duration::from_secs(7)).await;
let out_3 = write_stdin(&session, process_id, "", 100).await?;
let out_3 = write_stdin(&session, process_id, "", /*yield_time_ms*/ 100).await?;
assert!(
out_3.truncated_output().contains(TEST_VAR_VALUE),
@@ -351,12 +368,12 @@ async fn unified_exec_pause_blocks_yield_timeout() -> anyhow::Result<()> {
skip_if_sandbox!(Ok(()));
let (session, turn) = test_session_and_turn().await;
session.set_out_of_band_elicitation_pause_state(true);
session.set_out_of_band_elicitation_pause_state(/*paused*/ true);
let paused_session = Arc::clone(&session);
tokio::spawn(async move {
tokio::time::sleep(Duration::from_secs(2)).await;
paused_session.set_out_of_band_elicitation_pause_state(false);
paused_session.set_out_of_band_elicitation_pause_state(/*paused*/ false);
});
let started = tokio::time::Instant::now();
@@ -364,8 +381,8 @@ async fn unified_exec_pause_blocks_yield_timeout() -> anyhow::Result<()> {
&session,
&turn,
"sleep 1 && echo unified-exec-done",
250,
None,
/*yield_time_ms*/ 250,
/*workdir*/ None,
)
.await?;
@@ -390,7 +407,14 @@ async fn unified_exec_pause_blocks_yield_timeout() -> anyhow::Result<()> {
async fn requests_with_large_timeout_are_capped() -> anyhow::Result<()> {
let (session, turn) = test_session_and_turn().await;
let result = exec_command(&session, &turn, "echo codex", 120_000, None).await?;
let result = exec_command(
&session,
&turn,
"echo codex",
/*yield_time_ms*/ 120_000,
/*workdir*/ None,
)
.await?;
assert!(result.process_id.is_some());
assert!(result.truncated_output().contains("codex"));
@@ -402,7 +426,14 @@ async fn requests_with_large_timeout_are_capped() -> anyhow::Result<()> {
#[ignore] // Ignored while we have a better way to test this.
async fn completed_commands_do_not_persist_sessions() -> anyhow::Result<()> {
let (session, turn) = test_session_and_turn().await;
let result = exec_command(&session, &turn, "echo codex", 2_500, None).await?;
let result = exec_command(
&session,
&turn,
"echo codex",
/*yield_time_ms*/ 2_500,
/*workdir*/ None,
)
.await?;
assert!(
result.process_id.is_some(),
@@ -430,14 +461,17 @@ async fn reusing_completed_process_returns_unknown_process() -> anyhow::Result<(
let (session, turn) = test_session_and_turn().await;
let open_shell = exec_command(&session, &turn, "bash -i", 2_500, None).await?;
let open_shell = exec_command(
&session, &turn, "bash -i", /*yield_time_ms*/ 2_500, /*workdir*/ None,
)
.await?;
let process_id = open_shell.process_id.expect("expected process id");
write_stdin(&session, process_id, "exit\n", 2_500).await?;
write_stdin(&session, process_id, "exit\n", /*yield_time_ms*/ 2_500).await?;
tokio::time::sleep(Duration::from_millis(200)).await;
let err = write_stdin(&session, process_id, "", 100)
let err = write_stdin(&session, process_id, "", /*yield_time_ms*/ 100)
.await
.expect_err("expected unknown process error");
@@ -475,9 +509,9 @@ async fn completed_pipe_commands_preserve_exit_code() -> anyhow::Result<()> {
let environment = codex_exec_server::Environment::default();
let process = UnifiedExecProcessManager::default()
.open_session_with_exec_env(
1234,
/*process_id*/ 1234,
&request,
false,
/*tty*/ false,
Box::new(NoopSpawnLifecycle),
&environment,
)
@@ -517,9 +551,9 @@ async fn unified_exec_uses_remote_exec_server_when_configured() -> anyhow::Resul
let manager = UnifiedExecProcessManager::default();
let process = manager
.open_session_with_exec_env(
1234,
/*process_id*/ 1234,
&request,
true,
/*tty*/ true,
Box::new(NoopSpawnLifecycle),
remote_test_env.environment(),
)
@@ -541,7 +575,7 @@ async fn unified_exec_uses_remote_exec_server_when_configured() -> anyhow::Resul
&output_closed,
&output_closed_notify,
&cancellation_token,
None,
/*pause_state*/ None,
Instant::now() + Duration::from_millis(2_500),
)
.await;
@@ -571,9 +605,9 @@ async fn remote_exec_server_rejects_inherited_fd_launches() -> anyhow::Result<()
let manager = UnifiedExecProcessManager::default();
let err = manager
.open_session_with_exec_env(
1234,
/*process_id*/ 1234,
&request,
true,
/*tty*/ true,
Box::new(TestSpawnLifecycle {
inherited_fds: vec![42],
}),
@@ -36,7 +36,7 @@ fn unified_exec_env_overrides_existing_values() {
#[test]
fn exec_server_process_id_matches_unified_exec_process_id() {
assert_eq!(exec_server_process_id(4321), "4321");
assert_eq!(exec_server_process_id(/*process_id*/ 4321), "4321");
}
#[test]