openai / openai/codex

The mentions popup mixes scalar counts with terminal-cell rendering

Open
#45,036 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug CLI TUI
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

What version of Codex CLI is running?

codex-cli 0.0.0, built from the audited source revision d43f1e7eb27b204fd0e565891869280df3ba2346. Running codex --version on that isolated source build returned codex-cli 0.0.0. No host-installed Codex binary was used.

What subscription do you have?

Not applicable to this local reproduction. No Codex account was logged in or used.

Which model were you using?

Not applicable. No model request was made.

What platform is your computer?

Linux x86_64. This is the sanitized result of uname -mprs; host-specific kernel fields are omitted from the public draft.

What terminal emulator and version are you using (if applicable)?

The reproducer runs as a non-interactive Bash/Cargo process, with no terminal emulator and no multiplexer. It builds the pinned source into a separate temporary target directory and uses a separate CODEX_HOME.

Codex doctor report

What issue are you seeing?

The unified mentions popup has two Unicode boundary problems in the same
renderer.

First, the primary column width is measured with Rust chars().count() but
the result is rendered in terminal cells. A one-character CJK name uses two
cells, while a one-character ASCII name uses one. With both rows in the result
set, their descriptions start at different columns instead of sharing one
aligned column.

Second, when fuzzy matching is active, mentions_v2::primary_spans creates
one styled span per Rust char. The shared truncator is grapheme-safe only
inside a single span, so a narrow popup can split the ZWJ sequence 👩‍💻 and
render 👩‍….

The deterministic source-level oracle reports:

FAIL secondary-column primary="a" target_start=5 expected_start=6
FAIL matched-truncation name="👩\u200d💻" width=3 target="👩\u200d…" expected="👩\u200d💻…"
checked=8 failures=2
What steps can reproduce the bug?

From this report directory, run:

bash attachments/repro.sh

On its first run, the wrapper builds codex-cli from the pinned source
revision into isolated CARGO_HOME and CARGO_TARGET_DIR directories. It
prints the matching codex --version, then runs the source-level width and
span oracle. The wrapper intentionally exits with status 1 when the current
source violates the invariant.

To exercise the corresponding UI state manually, add local task, skill, or
plugin metadata whose display name contains 👩‍💻, and another candidate named
界 or a\). Type @in the composer to open the mentions popup, then type enough of the name to activate fuzzy matching. Make the terminal narrow enough for the result row to be truncated. The expected observations are a cell-alignment difference for the two primary-name widths and, for the three-cell content budget, a complete 👩‍💻 name being replaced by the partial👩‍…`.

The source-level oracle deliberately avoids a login, provider request, or
account state. It mirrors the target renderer's width and span operations at
the pinned revision, while the wrapper separately verifies the matching
Codex CLI build. The repeated-run output and exact inputs are in
attachments/evidence.log; runtime details are in
attachments/environment.txt.

What is the expected behavior?

Column padding should be based on the same terminal-cell width used to render
the name, so descriptions line up. A matched grapheme should stay together;
for the three-cell content budget, 👩‍💻… fits and 👩‍… is not a valid retained
name.

Additional information

The audited source revision is
d43f1e7eb27b204fd0e565891869280df3ba2346. Public Codex main was checked
at c4017a87aacc7558002b7cb510025e967c1d765e on 2026-09-12; the relevant
renderer blobs were unchanged. The report is pinned to the audited revision.

The popup computes the maximum primary-column width by mapping each row through
primary_text_width, then uses that value to add padding:

render.rs
render.rs

primary_text_width uses chars().count() for both the filename and
fallback display name:

render.rs

In the fuzzy path, primary_spans enumerates display_name.chars() and
pushes a separate styled span for every scalar:

render.rs

The shared truncator walks grapheme clusters within each span, not across
adjacent spans:

line_truncation.rs

That explains both observations: the column calculation undercounts wide
names, while the span construction removes the unit in which the grapheme
boundary check operates.

I searched the existing Codex issues and did not find one covering this newer
mentions_v2 renderer combination. The attached oracle checks both symptoms
independently; its ASCII and wide-name controls remain valid.

The report artifacts are:

attachments.zip

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with codex-rs/tui/src/bottom_pane/mentions_v2/render.rs, especially primary_text_width and primary_spans, then read codex-rs/tui/src/line_truncation.rs. Run attachments/repro.sh to reproduce both oracle failures. Done means terminal-cell alignment is consistent for wide names and the 👩‍💻 grapheme remains intact under truncation.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.