Skip to content

fix(trust): detect the Codex 0.156+ Folder access dialog and send its keystrokes - #67

Merged
Juliusolsson05 merged 6 commits into
integration/batch-2026-09-27-cxh-vfrom
fix/trust-dialog-0157
Sep 27, 2026
Merged

Juliusolsson05 merged 6 commits into
integration/batch-2026-09-27-cxh-vfrom
fix/trust-dialog-0157

Conversation

@Juliusolsson05

@Juliusolsson05 Juliusolsson05 commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

Fixes #65. Refs agent-code#234 (Codex 0.157.1 acceptance).

The bug

Codex 0.156+ repainted the trust dialog. detectCodexTrustDialog returns {visible:false} for the live, blocking dialog, so:

  • no codex.trust-dialog condition is raised;
  • readiness waits on a screen nobody is told about.

Recorded from codex-cli 0.157.1, with no key sent:

  Folder access
  /private/tmp/…/untrusted-ABCD        (hard-wrapped over 2 rows)

  Trust this folder? Codex can read, edit, and run files here, …
› 1. Trust and continue
  2. Back to Agent Command Center

  enter continue · esc back

Upstream also changed the keys. In trust_directory.rs at rust-v0.157.1:

  • 1/y now only moves the highlight ("trust always requires an explicit Enter confirmation");
  • Enter confirms the highlighted row;
  • 2, n, q, Esc, Ctrl+C and Ctrl+D still act at once.

So the old accept bytes ('1') would leave the dialog up.

Change

  • Both layouts are read bottom-up. The dialog is Codex's onboarding screen, so its key hint is the last painted row. A copied frame inside a transcript always has the live composer below it and never matches (review a/b P1). This applies to the legacy layout too: its Press enter to continue hint is last in rust-v0.149.1 (review c F1). The new layout needs:

    • the key hint enter continue · esc quit|back as the last row (one wrap allowed, for the Windows hint below 46 columns), with quit/back agreeing with option 2;
    • the nearest adjacent 1./2. pair above it, with labels upstream can paint;
    • the nearest whole-line Folder access above that.

    Prose that quotes the rows still cannot match.

  • Fields read from the screen:

    • option labels: "Trust and continue", "Open restricted" or "Open existing task"; and "Quit" or "Back to Agent Command Center";
    • the folder, with the hard wrap joined;
    • in a Git subdirectory, the repository root that trust applies to (trustTarget).
  • Keystrokes per layout, carried on the state. Legacy accept is '1'. 0.156+ accept is '1\r': 1 pins the highlight, so the Enter can only confirm option 1. Decline is '2' in both.

  • The condition's actions use the state's keys and on-screen labels. Ids are unchanged. The legacy trust_dialog event no longer sends '2\r'.

  • Shared detector. ScreenParser's streaming-text suppression uses it. Before, it matched on substrings, so quoted prose blanked the stream.

  • Composer surface. In Codex01491ComposerSurface, a bottom-row TRUST_HINT_FOOTER check marks the dialog a modal. Its hint row has the idle-footer shape, so without this check the dialog read as a composer drafting 1. Trust and continue (found by review c F2's test). The hunk is byte-identical to feat(prompt-input): issue the input profile for recorded Codex 0.157.1 #69's.

  • Docs and exports. API.md is rewritten for both layouts. The new constants and CodexTrustDialogLayout are exported.

Evidence and tests (fail-first: 5 of the new tests are red on main)

  • testing/fixtures/trust-dialog-0157/folder-access-back.json: a raw PTY recording of codex-cli 0.157.1 at 80×24.
    • It is replayed through the real HeadlessTerminal and checked with the parser, the condition actions and the streaming-text extractor.
    • Decoded end to end. Redacted at equal length: the account name, a session uuid and a directory suffix inside the scratch path.
  • upstream-snapshots-0157.1.json: upstream's 9 TrustDirectoryWidget insta snapshots, verbatim (Apache-2.0, attributed). They cover:
    • a Git subdirectory, including with only the repository root visible;
    • saved-untrusted and existing-task;
    • the trust-write error;
    • 40-column wraps and truncation.
  • Negatives:
    • prose quoting every row;
    • a verbatim copied frame above the live composer, for BOTH layouts;
    • options above the anchor, or not adjacent;
    • no hint;
    • an unknown option-1 or option-2 label, including the esc back case where only the whitelist rejects;
    • a hint that contradicts option 2.
  • Positives for a one-row wrap of the Windows hint, in both layouts.
  • CodexHeadless.trustDialog.test.ts drives the public class with the recording and asserts the trust_dialog callbacks write '1\r' and '2'.
  • Codex01491ComposerSurface.test.ts pins that the dialog is a modal, unwrapped and wrapped.
  • Live keystroke check. The feat(prompt-input): issue the input profile for recorded Codex 0.157.1 #69 recorder answered this dialog in an isolated CODEX_HOME on codex-cli 0.157.1. After 1 alone the dialog was still up, and the following Enter reached the composer.
  • Legacy tests unchanged and green. tsc --noEmit clean. CI green at d9a1305.
  • Locally, the full suite fails only RolloutOwnership.recorded modern-0149-large-bootstrap-first, on its 5 s timeout under load (bug(testing): RolloutOwnership.recorded 'modern-0149-large-bootstrap-first' exceeds 5 s under load #60, untouched here).

Not verified / residuals

Plan: docs/plans/2026-09-27-trust-dialog-0157.md.

🤖 Generated with Claude Code

Juliusolsson05 and others added 2 commits September 26, 2026 23:06
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…strokes

Codex 0.157.1 rewrote the trust dialog: no '> You are in', no 'Do you
trust the contents', options 'Trust and continue' / 'Quit' or 'Back to
Agent Command Center' (or 'Open restricted' / 'Open existing task').
detectCodexTrustDialog returned not-visible for the live, blocking
dialog. It now recognises both layouts structurally (whole-line anchor,
adjacent option pair, key hint that must agree with option 2) and reads
labels, folder and Git trust target from the screen.

Upstream also changed the keys (trust_directory.rs at rust-v0.157.1): 1
only moves the highlight, Enter confirms. The state now carries per-layout
keystrokes (legacy '1'; 0.156+ '1\r'), the condition labels its actions
from the screen, and CodexHeadless's legacy trust_dialog event stops
sending '2\r'. ScreenParser and the 0.149.1 composer surface share the
detector / add the new hint anchor.

Fail-first: a recorded 0.157.1 PTY replay (no key sent) and upstream's
insta snapshots, red on main.

Fixes #65

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Juliusolsson05 Juliusolsson05 added bug Something isn't working upstream-update Upstream CLI moved; needs a compatibility pass provider:codex Affects Codex integration labels Sep 27, 2026
Juliusolsson05 and others added 3 commits September 26, 2026 23:39
…ept a wrapped hint

Review of #67 (a, b): a transcript quoting the dialog verbatim was read
as a live, answerable trust dialog. The dialog is Codex's onboarding
screen, so its key hint is the last painted row; a quoted copy always has
the live composer below it. Detection now reads bottom-up: hint last (one
wrap allowed, for the Windows sandbox hint below 46 columns), nearest
adjacent option pair above, nearest Folder access above that.

Adds tests for the copied frame, the wrapped hint, an unknown option-1
label, option adjacency, both option-2 condition labels, legacy
streaming suppression, and the CodexHeadless trust_dialog callbacks
driven through the public class with the 0.157.1 recording.

Refs #65

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…0.156+ hint row as a modal

Review c of #67:
- F1: the legacy layout accepted a verbatim quoted dialog above the live
  composer, the same phantom fixed for 0.156+. Its 'Press enter to
  continue' hint is the last painted row as well (rust-v0.149.1 and the
  recorded 0.149.1 frame), so it is read bottom-up the same way.
- F2: pinning the composer-surface anchor exposed that the unwrapped
  0.156+ hint has the idle-footer shape, so the dialog read as a composer
  drafting '1. Trust and continue'. It is now a bottom-row structural
  check (identical to #63's branch); the window-based anchor is removed.
- F3: API.md rewritten for both layouts; new constants and the layout
  type exported.

Refs #65

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eject it

Verification a of #67: with 'esc quit' the hint/label agreement already
rejects an unknown option 2, so the whitelist mutation survived. The
restricted-folder frame ('esc back') makes the whitelist the only guard.

Refs #65

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Juliusolsson05

Copy link
Copy Markdown
Owner Author

Disposition (W1). Three reviews at 86e03d0 (codex a, codex b, pi c), then a verification pass by the same three. The final head is d9a1305.

Finding Source Disposition
A verbatim copied 0.156+ dialog in a transcript raised a live, answerable phantom a P1, b P1 Fixed (7f60d86). Bottom-up match: the hint is the last painted row.
A narrow Windows hint wrap made a live dialog invisible a P2, b P2 Fixed (7f60d86). One wrap is accepted.
Callbacks, labels, adjacency and legacy suppression were not covered by tests b P2 Fixed (7f60d86): CodexHeadless.trustDialog.test.ts plus parser tests.
The legacy layout had the same copied-frame phantom (pre-existing) c F1 Fixed (99a7a7b). The legacy hint is anchored at the bottom too.
The composer-surface anchor was untested c F2 Fixed (99a7a7b). The new test exposed that the unwrapped hint read as a composer; that is now a bottom-row modal check.
API.md was stale c F3 Fixed (99a7a7b). Rewritten, plus exports.
An unknown option-2 label mutation survived verify a Fixed (295412e). An esc back negative now kills it.
Trailing whitespace in the plan verify b Fixed (d9a1305).
A quote that is itself the last thing on screen is indistinguishable from a live dialog verify c Residual by construction. Stated in the body.

Verification a (after 295412e), b and c: MERGE-READY. CI is green at d9a1305, and the body is updated. The accept keystrokes (1 then Enter) are also live-verified, via #69's recorder in an isolated CODEX_HOME.

@Juliusolsson05
Juliusolsson05 changed the base branch from main to integration/batch-2026-09-27-cxh-v September 27, 2026 23:40
@Juliusolsson05
Juliusolsson05 merged commit ccb6080 into integration/batch-2026-09-27-cxh-v Sep 27, 2026
6 checks passed
Juliusolsson05 added a commit that referenced this pull request Sep 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working provider:codex Affects Codex integration upstream-update Upstream CLI moved; needs a compatibility pass

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(trust): Codex 0.156 reworded the trust dialog to "Trust this folder?"; every trust detector misses it

1 participant