4 Commits

  • fix(tui): preserve wrapped prose beside URLs (#21760)
    ## Why
    
    Mixed prose lines that contained URLs started taking the URL-preserving
    wrapping path, but that path could split ordinary words mid-token. A
    follow-up issue remained in scrollback insertion: when already-rendered
    indented rows were wrapped again, continuation rows could lose their
    margin and fall back to terminal hard wrapping. Together those bugs made
    normal Markdown output look broken around links, lists, blockquotes, and
    indented content.
    
    Separately, the local argument-comment lint wrappers failed under
    environments that set `PYTHONSAFEPATH=1`, because Python no longer adds
    the script directory to `sys.path` automatically. That prevented the
    lint from reaching Rust callsites at all.
    
    <img width="1778" height="1558" alt="CleanShot 2026-05-09 at 11 51 38"
    src="https://github.com/user-attachments/assets/9274d150-1757-4f1a-89ac-5bdc9997d8cb"
    />
    
    ## What Changed
    
    - Preserve URL tokens without turning every neighboring prose word into
    a character-level split point.
    - Add a mixed URL/prose wrapper that keeps ordinary words whole,
    preserves leading whitespace, and re-splits long non-URL tokens against
    the actual width available on continuation rows.
    - Reuse a rendered history row's leading whitespace as the continuation
    indent when scrollback insertion has to pre-wrap it again.
    - Add regression coverage for markdown wrapping, history-cell rendering,
    scrollback continuation margins, leading-indent width accounting, and
    continuation-row re-splitting.
    - Make both argument-comment lint entrypoints explicitly add their own
    directory to `sys.path`, so sibling imports still work when
    `PYTHONSAFEPATH=1`.
    
    ## How to Test
    
    1. Start Codex and render a long Markdown response that mixes prose with
    inline links, blockquotes, lists, and indented code-like text.
    2. Confirm that ordinary words next to links stay whole instead of
    breaking mid-word.
    3. Resize or replay the transcript and confirm wrapped continuation rows
    keep their expected left margin for blockquotes, lists, and indented
    content.
    4. Run the source argument-comment lint from a shell with
    `PYTHONSAFEPATH=1` and confirm it starts normally instead of failing to
    import `wrapper_common`.
    
    Targeted tests:
    - `cargo test -p codex-tui mixed_line --lib`
    - `cargo test -p codex-tui preserves_prefix_on_wrapped_rows --lib`
    - `cargo test -p codex-tui
    agent_markdown_cell_does_not_split_words_after_inline_markdown --lib`
    - `cargo test -p codex-tui
    mixed_url_markdown_wraps_prose_without_splitting_words_snapshot --lib`
    - `python3 tools/argument-comment-lint/test_wrapper_common.py`
    - `just argument-comment-lint-from-source -p codex-tui -- --lib`
    
    Notes:
    - `cargo test -p codex-tui` currently reaches the new tests
    successfully, then still aborts in the pre-existing
    `tests::fork_last_filters_latest_session_by_cwd_unless_show_all`
    stack-overflow failure.
  • fix: close Bazel argument-comment-lint CI gaps (#16253)
    ## Why
    
    The Bazel-backed `argument-comment-lint` CI path had two gaps:
    
    - Bazel wildcard target expansion skipped inline unit-test crates from
    `src/` modules because the generated `*-unit-tests-bin` `rust_test`
    targets are tagged `manual`.
    - `argument-comment-mismatch` was still only a warning in the Bazel and
    packaged-wrapper entrypoints, so a typoed `/*param_name*/` comment could
    still pass CI even when the lint detected it.
    
    That left CI blind to real linux-sandbox examples, including the missing
    `/*local_port*/` comment in
    `codex-rs/linux-sandbox/src/proxy_routing.rs` and typoed argument
    comments in `codex-rs/linux-sandbox/src/landlock.rs`.
    
    ## What Changed
    
    - Added `tools/argument-comment-lint/list-bazel-targets.sh` so Bazel
    lint runs cover `//codex-rs/...` plus the manual `rust_test`
    `*-unit-tests-bin` targets.
    - Updated `just argument-comment-lint`, `rust-ci.yml`, and
    `rust-ci-full.yml` to use that helper.
    - Promoted both `argument-comment-mismatch` and
    `uncommented-anonymous-literal-argument` to errors in every strict
    entrypoint:
      - `tools/argument-comment-lint/lint_aspect.bzl`
      - `tools/argument-comment-lint/src/bin/argument-comment-lint.rs`
      - `tools/argument-comment-lint/wrapper_common.py`
    - Added wrapper/bin coverage for the stricter lint flags and documented
    the behavior in `tools/argument-comment-lint/README.md`.
    - Fixed the now-covered callsites in
    `codex-rs/linux-sandbox/src/proxy_routing.rs`,
    `codex-rs/linux-sandbox/src/landlock.rs`, and
    `codex-rs/core/src/shell_snapshot_tests.rs`.
    
    This keeps the Bazel target expansion narrow while making the Bazel and
    prebuilt-linter paths enforce the same strict lint set.
    
    ## Verification
    
    - `python3 -m unittest discover -s tools/argument-comment-lint -p
    'test_*.py'`
    - `cargo +nightly-2025-09-18 test --manifest-path
    tools/argument-comment-lint/Cargo.toml`
    - `just argument-comment-lint`
  • build: migrate argument-comment-lint to a native Bazel aspect (#16106)
    ## Why
    
    `argument-comment-lint` had become a PR bottleneck because the repo-wide
    lane was still effectively running a `cargo dylint`-style flow across
    the workspace instead of reusing Bazel's Rust dependency graph. That
    kept the lint enforced, but it threw away the main benefit of moving
    this job under Bazel in the first place: metadata reuse and cacheable
    per-target analysis in the same shape as Clippy.
    
    This change moves the repo-wide lint onto a native Bazel Rust aspect so
    Linux and macOS can lint `codex-rs` without rebuilding the world
    crate-by-crate through the wrapper path.
    
    ## What Changed
    
    - add a nightly Rust toolchain with `rustc-dev` for Bazel and a
    dedicated crate-universe repo for `tools/argument-comment-lint`
    - add `tools/argument-comment-lint/driver.rs` and
    `tools/argument-comment-lint/lint_aspect.bzl` so Bazel can run the lint
    as a custom `rustc_driver`
    - switch repo-wide `just argument-comment-lint` and the Linux/macOS
    `rust-ci` lanes to `bazel build --config=argument-comment-lint
    //codex-rs/...`
    - keep the Python/DotSlash wrappers as the package-scoped fallback path
    and as the current Windows CI path
    - gate the Dylint entrypoint behind a `bazel_native` feature so the
    Bazel-native library avoids the `dylint_*` packaging stack
    - update the aspect runtime environment so the driver can locate
    `rustc_driver` correctly under remote execution
    - keep the dedicated `tools/argument-comment-lint` package tests and
    wrapper unit tests in CI so the source and packaged entrypoints remain
    covered
    
    ## Verification
    
    - `python3 -m unittest discover -s tools/argument-comment-lint -p
    'test_*.py'`
    - `cargo test` in `tools/argument-comment-lint`
    - `bazel build
    //tools/argument-comment-lint:argument-comment-lint-driver
    --@rules_rust//rust/toolchain/channel=nightly`
    - `bazel build --config=argument-comment-lint
    //codex-rs/utils/path-utils:all`
    - `bazel build --config=argument-comment-lint
    //codex-rs/rollout:rollout`
    
    
    
    
    
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/16106).
    * #16120
    * __->__ #16106
  • refactor: rewrite argument-comment lint wrappers in Python (#16063)
    ## Why
    
    The `argument-comment-lint` entrypoints had grown into two shell
    wrappers with duplicated parsing, environment setup, and Cargo
    forwarding logic. The recent `--` separator regression was a good
    example of the problem: the behavior was subtle, easy to break, and hard
    to verify.
    
    This change rewrites those wrappers in Python so the control flow is
    easier to follow, the shared behavior lives in one place, and the tricky
    argument/defaulting paths have direct test coverage.
    
    ## What changed
    
    - replaced `tools/argument-comment-lint/run.sh` and
    `tools/argument-comment-lint/run-prebuilt-linter.sh` with Python
    entrypoints: `run.py` and `run-prebuilt-linter.py`
    - moved shared wrapper behavior into
    `tools/argument-comment-lint/wrapper_common.py`, including:
      - splitting lint args from forwarded Cargo args after `--`
    - defaulting repo runs to `--manifest-path codex-rs/Cargo.toml
    --workspace --no-deps`
    - defaulting non-`--fix` runs to `--all-targets` unless the caller
    explicitly narrows the target set
      - setting repo defaults for `DYLINT_RUSTFLAGS` and `CARGO_INCREMENTAL`
    - kept the prebuilt wrapper thin: it still just resolves the packaged
    DotSlash entrypoint, keeps `rustup` shims first on `PATH`, infers
    `RUSTUP_HOME` when needed, and then launches the packaged `cargo-dylint`
    path
    - updated `justfile`, `rust-ci.yml`, and
    `tools/argument-comment-lint/README.md` to use the Python entrypoints
    - updated `rust-ci` so the package job runs Python syntax checks plus
    the new wrapper unit tests, and the OS-specific lint jobs invoke the
    wrappers through an explicit Python interpreter
    
    This is a follow-up to #16054: it keeps the current lint semantics while
    making the wrapper logic maintainable enough to iterate on safely.
    
    ## Validation
    
    - `python3 -m py_compile tools/argument-comment-lint/wrapper_common.py
    tools/argument-comment-lint/run.py
    tools/argument-comment-lint/run-prebuilt-linter.py
    tools/argument-comment-lint/test_wrapper_common.py`
    - `python3 -m unittest discover -s tools/argument-comment-lint -p
    'test_*.py'`
    - `python3 ./tools/argument-comment-lint/run-prebuilt-linter.py -p
    codex-terminal-detection -- --lib`
    - `python3 ./tools/argument-comment-lint/run.py -p
    codex-terminal-detection -- --lib`