Skip to content

fix(codex): edit Codex config.toml through one parser-checked writer (1/2) - #23930

Open
brennanb2025 wants to merge 28 commits into
mainfrom
brennanb2025/codex-config-checked-writer
Open

brennanb2025 wants to merge 28 commits into
mainfrom
brennanb2025/codex-config-checked-writer

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 16 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1335 $\color{#cf222e}{\Huge{\mathbf{−}}}$​28 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1307
Prod 34 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1756 $\color{#cf222e}{\Huge{\mathbf{−}}}$​459 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1297

ELI5

Orca edits Codex's settings file (~/.codex/config.toml) to mark your folders as trusted and to install its status hook. It did this with text patterns that only recognised one way of writing each setting. Codex writes some of them differently, so Orca sometimes added a second copy of a section. A settings file with the same section twice is invalid, so every codex command stopped working, even outside Orca. Now every Orca edit goes through one checked writer. It reads the file with a real parser, never leaves it invalid, and keeps your comments. It also removes the duplicates older Orca versions already wrote.

What Changed

The problem users see (#22592): after Orca trusts a folder, codex, codex exec and codex login status all fail with Error loading config.toml: duplicate key, including when you run codex outside Orca.

  • Why: Codex's own trust screen writes a project section as ["projects"."/path"], but Orca looked only for [projects."/path"]. Not finding it, Orca appended a second section for the same folder.
  • The same happened for the trust_level key, for Orca's hook-trust sections, and in Orca's own copy of your settings, the "managed Codex home" that Orca-launched Codex uses.

Scope:

  • Affected: anyone using Codex with Orca, on macOS, Linux, Windows, WSL and SSH hosts. It happens when Orca trusts a folder, installs its hook, or copies your settings into its managed Codex home.
  • Not affected: Codex settings Orca never edits.
  • Behaves as on main: a ~/.codex/config.toml you broke yourself (for example a line with no value). Codex shows its own error, and Orca never edits a file it can't read.

Before:

  • About eight separate text matchers, each with its own idea of how a key is written.
  • Nothing checked that an edit left a valid file, and old duplicates stayed broken forever.

After:

  • One checked writer for every Orca edit of a Codex config.toml. It covers:
    • your ~/.codex and Orca's managed Codex homes;
    • copying settings between them;
    • hook trust, and the cleanup of old hook entries;
    • the SSH host (see Notes).
  • Reading: tables and keys are found by their decoded name, however the header is written (quoted, bare, literal or escaped), including CRLF files.
  • Checking: Orca still edits the text itself, so your comments and formatting survive. Then it parses the result, which must be valid, hold the intended value, and change nothing else.
  • Refusing: an edit that would leave the file invalid is refused. It's logged once per file and message, with the file and line, and it never blocks a launch.
  • Repair:
    • The exact duplicates older Orca versions appended are removed, and your first section always wins.
    • Repair never drops a value: it removes only Orca's exact copies, or values your first section already holds, and re-parses to prove it.
    • In ~/.codex, the previous version is kept as config.toml.bak, as for every Orca write there; the next write replaces it. Orca's own Codex home is rebuilt from ~/.codex and keeps no backup, as on main.
  • One home failing doesn't stop the others: if ~/.codex can't be edited, Orca still trusts the folder in its managed Codex home, and the reverse.
  • Smaller behaviour changes:
    • Disabled hook, no enabled line: when Orca carries a disabled hook's state onto a hook-trust section that has no enabled line, it now writes enabled = false. Before, that section stayed enabled.
    • Change made inside Orca while ~/.codex is broken: say you change a setting inside Orca-launched Codex (for example /model), then break ~/.codex by hand before Orca copies the change back. Orca now holds the change and skips copying settings from ~/.codex into its managed home until ~/.codex parses again. It logs this once and then copies the change back, and Orca-launched Codex keeps working meanwhile. Before, Orca wrote into the broken file and copied the broken file into its managed home.
    • Moving a user hook's approval when its position shifts (from fix(codex): opening a terminal no longer strips Codex hooks from the real ~/.codex #23552): this move now goes through the checked writer too.
      • When you change hooks (turning Orca's hooks on or off, or Orca installing its own), the hooks.json change happens. If config.toml can't be read, the approval move is refused and logged once, and Codex lists the moved hook for review. On main the move edited the unreadable file.
      • When Orca cleans up its own retired entries from ~/.codex/hooks.json, it plans the config.toml edit first. If the file can't be read, it leaves both files alone and logs once ("Waiting to remove retired Orca hook entries until config.toml can be read"). The first launch after you fix the file removes the entry and moves your approval cleanly, so Codex doesn't ask you to review your own hook again. Removing the entry anyway would strand your approval at the old position.
    • Hand-written forms Orca won't edit: these are refused and logged rather than edited: a project written as an inline table ("/x" = { ... }), and hook trust written as dotted keys or inline tables. Codex itself always writes table headers.
  • New dependency: smol-toml, pinned to 1.8.0. It was already in the lockfile through another package, so the lockfile change is three lines. It's loaded with a plain require:
    • the packaged app and CLI resolve it from the packaged runtime modules;
    • the SSH relay bundle inlines it, because remote hosts have no node_modules.

Why

  • The bug class is "each matcher guesses how the key is written." A real parser decides once, and checking the result catches whatever the text edit gets wrong, including forms Codex adds later.
  • Why not rewrite the whole file from the parsed data: that loses your comments and formatting.
  • Why not a format-preserving TOML editing library: we tried the two available for JavaScript. One dropped comments and CRLF and deleted a project. The other placed new entries in its own style instead of the [projects."..."] section Codex writes. Both throw on a file with duplicates, so the repair step would still be needed.
  • Why keep trust as a file edit rather than a per-launch -c option: trust must work however Codex is launched (hand-typed, scripts, cmd.exe, company-specific codex wrappers), and the settings file is the one thing every launch reads.
  • This supersedes fix(codex): recognize quoted projects keys in config.toml trust headers #22605, which fixed the header matcher only. It missed the trust_level key, hook trust, the managed home, and already-broken files.

This PR is step 1 of 3. The plan fixes how Orca edits Codex's config, trust and hooks:

Linked Issue

Fixes #22592

Visual Proof

Live on an M4Air Mac, with real Codex (codex login status) and an isolated test home.

  • Before: Orca built from main.
  • After: Orca built from this branch, merged with current main.
  • Scenario 1: Codex had already trusted the folder, using its own quoted spelling. Orca then launches Codex there.

Before: Orca appends a second section and Codex fails with duplicate key.
q1-before

After: one section, the comment kept, and Codex loads ("Not logged in" is expected in the isolated home).
q1-after

Scenario 2 is a file an older Orca already broke. Before: it stays broken.
q2-before

After: the duplicate is repaired, and Codex loads.
q2-after

Scenario 5 launches Codex in a linked worktree that Codex had already trusted. After: one section, and Codex loads.
q5-after

Testing

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

  • Live QA (M4Air, before/after as above):

    • Codex's quoted spelling: fixed.
    • A file an older Orca broke: repaired.
    • CRLF with comments: the file is byte-identical and trusted once.
    • A linked worktree: one table, and Codex loads.
    • A hand-broken file: the launch isn't blocked, Codex shows its own error, and the file is left untouched.
    • Not exercised live: the duplicate path in Orca's managed Codex home, because on that Mac Orca-launched Codex read ~/.codex directly. Unit tests cover it.
  • Live QA (Windows high spec, Codex 0.159.2, an isolated copy of Orca built from this branch; the machine's real ~/.codex was hash-checked and never changed):

    • A folder Codex trusted itself, which it writes in lowercase with literal quotes ([projects.'c:\users\...']), isn't added a second time. Codex opens there with no trust prompt.
    • The [Bug]: Codex config.toml gets a duplicate [projects."…"] table (Orca does not recognize Codex's ["projects"."…"] headers), breaking codex startup #22592 duplicate-key file is repaired both in ~/.codex and in Orca's own Codex home, and Codex loads both. The Mac QA couldn't reach Orca's own home; Windows always uses it.
    • A Notepad-style file (CRLF line endings, comments) keeps its bytes, and the added block uses CRLF.
    • A quoted "enabled" = false hook stays off inside Orca.
    • A hand-broken file: launches aren't blocked, the file is untouched, and the refusal is logged once.
    • A user hook's approval moves once when Orca removes its retired entry ahead of it.
    • With an unreadable config.toml, the retired-entry cleanup waits, and after the file is fixed it moves the approval cleanly. QA found the first version of this wrong; it's fixed here, with tests.
    • Packaging: the main bundle loads smol-toml from the packaged runtime modules, and CI's Windows package check confirms it ships. A full packaged launch on Windows wasn't run.
    • Not run: WSL (this PR has no WSL Codex trust path), Windows low spec (its install fails building an unrelated native module), and a live SSH host (the Linux test host is down).
  • New tests cover:

    • quoted, bare, literal and escaped spellings, dotted keys, and sub-tables;
    • duplicate repair, including arrays of tables and adjacent headers;
    • refusing an invalid result, and logging each refusal once;
    • comments and CRLF kept, and integers larger than 2^53;
    • one Codex home failing without stopping the other, in both directions;
    • a hand-broken ~/.codex mirrored exactly as on main;
    • on the SSH host (relay): a quoted section edited in place, an unreadable remote config never written, the relay bundle loading with no node_modules, and repairing on Node 18 (Node 20-only array methods removed).
  • The key tests fail with their fix removed.

  • A mirror comparison with main over thousands of generated config shapes: the managed Codex home is never written unparseable, and a hand-broken ~/.codex gives the same bytes as on main.

  • Typecheck is clean for the node and CLI projects. oxlint, oxfmt and the changed-code quality gate are clean. The targeted suites pass.

AI Disclosure

Review

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

Ensure no issues in: Security, Cross-platoform support (Linux, Windows, Mac), Remote SSH, Mobile, general backwards compatibility, performance

  • SSH: on main, trust on an SSH host is written by Orca's relay on that host (feat(agents): pre-trust the folder wherever Orca starts an agent #23744). This PR routes that write through the same checked writer, with smol-toml inlined into the relay bundle and no Node 20-only APIs. The remote hook installer, which writes over SFTP, also goes through the checked writer. There's no protocol change, so mixed desktop and relay versions are safe; each desktop deploys its own relay.
  • Windows and WSL: paths are matched after normalisation, including lowercase drive letters and literal-string Windows paths, and CRLF is preserved.
  • Performance (worst case, a 386 KB config with 5,000 projects):
    • a trust edit takes about 20-30 ms, up from about 4-6 ms;
    • copying settings into the managed home at each launch takes about 160 ms, up from about 120 ms.
    • At realistic sizes the difference is small: about 15 ms against 13 ms at 500 projects, and about 2 ms at 30.
  • Symlinks and permissions: writes still go through the existing atomic writer. It follows a dotfiles symlink to its target, keeps the file's permissions, and refuses a dangling link.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

Fixes #22592. After Orca started a Codex agent, every `codex` command
(including the Codex app and Codex outside Orca) failed with
"duplicate key" in ~/.codex/config.toml. Codex had written the project
as `["projects"."<path>"]`; Orca's text matchers only knew the bare
`[projects."<path>"]` spelling, so Orca appended a second table, added a
second `trust_level` beside a quoted `"trust_level"`, and its mirror into
Orca-managed Codex homes kept both spellings (and a second
`[hooks.state]`). TOML forbids all of these.

Now every Orca edit of a Codex config.toml finds tables and keys by their
decoded key path (quoted, bare, literal, spaced, dotted or inline), decides
with a real TOML parse (smol-toml, 64-bit integers included), and keeps its
text-level edit so the user's comments and formatting survive. Each result
is checked before it is written: it must parse, hold the intended value,
and leave every other value unchanged. A file that does not parse is
repaired only where the damage is the exact shape earlier Orca builds wrote
(never a table under an array of tables, and never if a removed value would
be lost); otherwise the edit is refused with the file and line, and the
launch continues. The same check covers the local atomic writer, the
managed-home mirror, settings promotion, the legacy profile cleanup, the
SSH relay trust write and the SFTP hook-trust write.

While ~/.codex does not parse, a managed Codex home whose config parses is
left untouched (logged once and recorded), so state only it holds survives
an invalid save; a fresh or equally unreadable managed home gets an
unchanged copy so Orca-launched Codex shows Codex's own error, like `codex`
typed by hand. Settings are never promoted from, or merged out of, a managed
config that does not parse, and one that is reseeded is kept as `.bak`.

smol-toml is loaded with createRequire (its declarations are ESM-only, and
the CLI builds as CommonJS) and shipped as a packaged runtime dependency so
the packaged app and CLI can find it.
…ever taken for managed state

A ~/.codex broken only by a duplicate project or hook-trust table was
copied verbatim into a fresh managed Codex home, and the mirror's own
dedupe then made that copy look like readable managed state: later
passes kept it, merged its sections and promoted from it. After the user
fixed and trimmed ~/.codex, Orca wrote a deleted marketplace back into
the real ~/.codex, and the managed home kept a deleted MCP server and a
trusted folder.

The copy now ends with a marker comment
(`# orca: verbatim copy of <source>; replaced when the source parses`),
appended so Codex reports the same error lines as in the user's file.
A marked managed config is always reseeded, never kept, merged or
promoted from; the marker disappears with the reseed, so it cannot strand.
…e parsed

markCodexProjectTrusted wrote ~/.codex first; a refused write there (the
file does not parse) threw before the managed-home write ran, so
Orca-launched Codex asked for trust again. Each home is now attempted
independently and the failure(s) surface afterwards.
Trust-write refusals were dropped by empty catch blocks or warned on every
launch. They now go through the once-per-file-and-message reporter; other
failures keep their existing handling, and nothing throws into launch.
…tied

- A marked copy of a broken ~/.codex is replaced with a fresh config when
  the user fixes it by deleting or emptying config.toml (managed, account
  and legacy shared homes).
- A file is the copy only if it ends in the marker and does not parse, so
  a valid user config ending in that text is no longer reseeded.
- A broken managed config is kept as .bak before the copy replaces it,
  and the copy itself is never backed up.
- Drop the refusal map and TTL getter that nothing in production read.
Trust-write, promotion, and mirror reports about one config file shared a
single last-message slot, so they displaced each other and every one was
logged again on every launch. Remember the last message per file and kind;
a mirror pass that succeeds forgets only mirror reports, and a trust write
that succeeds forgets the trust refusal so a later one is reported again.
The mirror parses every table header through the full key-path parser to
decide whether it is a projects or hooks.state table. Reject a header that
contains neither the table names nor a backslash (an escape is the only way
to spell a key without its letters), and read the canonical
[projects."path"] form with one anchored regex. Mirror pass on a
5,000-project config: ~165 ms -> ~116 ms.
…; broken-config handling moves to a follow-up

This PR fixes #22592 (Orca's own duplicate tables). It had also grown a
separate feature for a ~/.codex the user broke by hand: a marked verbatim
copy in the managed home, keeping a working managed copy untouched, a .bak
on reseed, a no-source path in the accounts mirror, and skipping settings
promotion from the copy. That feature moves to a later PR.

For a ~/.codex that does not parse even after Orca's duplicate repair, the
managed-home, legacy shared-home and accounts mirrors now do exactly what
they did before this PR. Kept: the checked writer, the repair applied to
~/.codex and to the managed config before mirroring, and the rule that a
mirror never writes a result Codex cannot parse when every input parses.

Settings promotion still never edits a ~/.codex Codex cannot parse. When
it has nothing to write back, the mirror proceeds as before; when an
in-Codex change is pending, the pass stalls (as for any failed write-back)
so the mirror cannot erase that change, and the refusal is logged once.

codex-managed-config-validity.ts is gone; the two helpers still used moved
beside their callers. A mirror pass now parses whole files 4 times instead
of 10.
…write once

When ~/.codex does not parse, the managed home mirrors it as before this PR,
so the managed config.toml does not parse either. Two hook paths then went
wrong on every Codex launch:

- A hook trust edit with nothing to write (no entries to upsert, or no
  existing hooks.state table to toggle) still ran the checked writer, which
  refuses a file it cannot parse. With status hooks off, the user-hook
  refresh returned 'error', warned on every launch, and skipped the trust
  provenance snapshot and legacy cleanup that follow. Before this PR it was
  a silent no-op. It is again.
- A hook trust write with real entries is correctly refused, but launch prep
  logged that refusal on every launch. It is now logged once per file, like
  a refused workspace trust write, and launch prep does not repeat it. The
  hook status is unchanged ('error' with the same detail).

A trust refusal report now ends only when a trust write actually lands; a
no-op edit proves nothing about the file, and otherwise the no-op above
would re-arm the workspace trust refusal log on every launch.
…write lands

A refused Codex trust write is logged once per config file. The local
writer forgets that report when a later trust write lands, so a new
refusal is logged again; the SSH writer never did, so after one refusal
every later refusal of that remote file stayed silent for the session.
The remote writer now clears it the same way.
…ort promotion stalls

- A project that ~/.codex defines only through a sub-table, such as
  [projects."/a".extra], was treated as defined inline, so the mirror
  dropped the managed home's [projects."/a"] trust on every pass (Codex
  then asked to trust the folder again). Any header under projects."/a"
  now counts as a table definition, as before this PR.
- A settings promotion stall was logged once and never forgotten, so a
  second stall after a successful promotion was silent. A promotion pass
  that does not stall now ends the report.
…rsing

The sync status is derived from source-side checks only, so it can read
as synced while a pass stalls on content (a refused settings promotion or
an unparseable merge result); the comment claimed the two can never
disagree. The line scanner comment still said Orca has no TOML dependency.
…otted key also sets it

A project that ~/.codex defines through a sub-table such as
[projects."/a".extra] and also through dotted keys ([projects] with
"/a".trust_level = ..., or root projects."/a".trust_level = ...) was
counted as table-defined, so the mirror kept the managed home's
[projects."/a"] table, the merged file redefined /a, and every mirror
pass was refused. A project now counts as table-defined only when it has
its own [projects."/a"] header or every key under it comes from a
sub-table header.
…ever clear

The refusal logging grew per-file, per-kind bookkeeping with clear calls in
promotion, the mirror, local and remote trust writes, and a WeakSet of hook
statuses in launch prep; three review-loop bugs came from its clearing
rules. Replace it with one rule: each distinct (config path, message) logs
once per app session, in a bounded set. Launch prep logs a hook status error
through the same call instead of checking a WeakSet; hook status values are
unchanged. Refusals are still contained exactly as before.
Main (#23744, #23937) moved every agent trust write into one dispatcher,
applyWorkspaceTrustOnThisHost, run on the host that starts the agent: main
for local and WSL launches, the SSH relay for remote ones. The desktop SFTP
trust writer, the trust IPC and the per-call-site launch-prep writes are gone.

Re-applied on top:
- markCodexProjectTrusted attempts every config.toml it is given, so a file
  Orca refuses to edit never leaves another Codex home untrusted.
- The dispatcher reports refused Codex config edits once per file and message.
- smol-toml is loaded with a literal require so the relay's esbuild bundle
  inlines it; relay hosts have no node_modules, and createRequire made the
  relay fail to load.
- Remote trust tests ported to the relay writer; hook-status log-once test
  moved out of the test file main deleted.
… every value under it

A deeper header such as [projects."/a".extra.deep] counted `extra` as a
header-defined sub-table even when a dotted key ("/a".extra.q = 1 under
[projects], or root projects."/a".extra.q = 1) created `extra`. Orca then
kept its managed [projects."/a"] table, the merged file redefined /a, and
the mirror was refused on every pass. A project now counts as table-defined
only when every value under it sits under some [projects."/a"...] header,
checked recursively. Also drops a stale "loaded via createRequire" note:
smol-toml is now loaded with a literal require.
The relay runs the checked writer on the remote host, and SSH hosts may run
Node 18, which has no Array.prototype.toReversed. The repair and the hook
enable/disable edit iterated with it, so repairing a config an older Orca
broke threw a TypeError there and left the file broken.
@brennanb2025

brennanb2025 commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor Author

Review status: ready for review

The problem: after Orca trusted a folder, every codex command failed with Error loading config.toml: duplicate key, including outside Orca (#22592). Codex's trust screen writes a folder's section as ["projects"."/path"]. Orca's text matcher looked only for [projects."/path"], so it appended a second section for the same folder. The same happened for the trust_level key, for hook trust, and in Orca's own copy of your settings (the "managed Codex home" that Orca-launched Codex uses).

What changes for users:

  • Orca never again leaves a Codex settings file with a duplicate section.
  • Files an older Orca already broke are repaired on the next write, and your first section always wins.
  • Your comments and CRLF line endings are kept.
  • If an edit would leave the file invalid, Orca skips it and logs this once; it never blocks a launch.
  • A ~/.codex you broke yourself behaves exactly as on main.

What the review changed (6 rounds including narrow re-checks, plus an architecture challenge and a final readiness pass):

  • Split on the owner's decision. A second feature for a hand-broken ~/.codex (a marked word-for-word copy in the managed home) was the least stable part of the PR. It had four of the lifecycle bugs found in review, and it isn't needed to fix [Bug]: Codex config.toml gets a duplicate [projects."…"] table (Orca does not recognize Codex's ["projects"."…"] headers), breaking codex startup #22592. It's preserved on brennanb2025/codex-broken-config-copy as step 3 of the plan, with no PR yet. This PR now behaves like main for a file you broke by hand.
  • Fixed:
    • If ~/.codex couldn't be edited, Orca stopped before trusting the folder in its managed Codex home, so Orca-launched Codex would have asked for trust. Each home is now tried on its own.
    • Trust refusals were swallowed silently or logged on every launch. Each is now logged once per file and message, and the logging code was simplified along the way.
    • A no-op hook-trust edit on an unreadable config reported an error and skipped cleanup.
    • The managed home lost your trust for a project that ~/.codex defined only through a sub-table, and some dotted and sub-table mixes made Orca stop updating its copy of your settings.
    • The settings copy into the managed home was about twice as slow on very large configs. It's now about 160 ms, against about 120 ms on main, at 5,000 projects.
    • Merged current main, including feat(agents): pre-trust the folder wherever Orca starts an agent #23744 and fix(codex): trust the worktree Codex starts in, not a guessed repo root #23937, which now write trust from the SSH host's relay. The TOML parser is now bundled into the relay; without that, relay trust writes would have failed on every SSH host. Repair now also works on Node 18 SSH hosts, where it had thrown toReversed is not a function.
  • Deferred: all hand-written edge cases Codex itself never writes, each tracked:
    • inline-table projects and dotted or inline hook trust are refused rather than edited;
    • a project written as an array of tables stops Orca's copy of your settings from updating;
    • smol-toml's strictness differs from Codex's parser only on out-of-range integers and impossible dates;
    • the Accounts pane shows "synced" while the settings copy into the managed home is paused;
    • the relay bundle test copies its build options by hand;
    • once the hotfix fix(codex): recognise Codex's quoted spellings in config.toml, and repair Orca's duplicates (#22592) #23958 lands, this PR adopts its rule for carrying hook trust into the managed home.

Verified:

  • Live QA on an M4Air Mac against real Codex, before and after, with screenshots in the body:
    • Codex's quoted spelling: fixed.
    • A file an older Orca broke: repaired.
    • CRLF with comments: byte-identical.
    • A linked worktree: one section.
    • A hand-broken file: not blocked, and Codex shows its own error.
  • Targeted unit suites, including the SSH relay bundle and Node 18 array methods removed.
  • A comparison with main over thousands of generated configs.
  • Node and CLI typechecks, oxlint and oxfmt.

Not verified:

  • A real SSH host, a real Node 18 binary (the Node 18 check removes the Node 20 array methods instead), and Windows or WSL hosts.
  • A packaged-app build. Packaging was checked by building the relay with its real build script and confirming how the main process and CLI resolve modules.
  • The managed-home duplicate path live: on that Mac, Orca-launched Codex read ~/.codex directly. Unit tests cover it.

CI: all required checks green on head 60dcc2e0650 (25 passed, 6 skipped).

brennanb2025 added a commit that referenced this pull request Sep 30, 2026
…ership

#23930 merged current main, whose #23744/#23937 moved trust writing into
applyWorkspaceTrustOnThisHost (local) and the SSH relay. Resolved by taking
that design and dropping what it already covers: the per-home trust writes,
the launch-prep trust writes and their shared budget, and the worker-start
trust diagnosis (moved to a follow-up; #23847 is now referenced, not fixed).

Kept on top of it:
- Local Codex trust also reaches the per-account home the launch reads: the
  launch env's CODEX_HOME joins getLocalCodexTrustConfigFiles, as the relay
  already does.
- An OS error that stops a trust write names config.toml, not the atomic
  writer's temp file; config refusals pass through unchanged.
- The WSL hook-trust relocation now logs through warnCodexConfigOnce and
  writes through withConfigPath, the base's single refusal and write rules.
@brennanb2025
brennanb2025 marked this pull request as ready for review September 30, 2026 02:18
@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The changes add TOML parsing, duplicate repair, and checked-edit utilities for Codex configuration. Project and hook trust updates now use checked edits and validated writes. Managed and legacy runtime configuration mirroring includes additional preparation, merge, and validation behavior. Workspace-trust operations continue across configured files and report refusals. Tests cover TOML variants, malformed configurations, mirroring, relay bundling, and warning deduplication.

Priority: ➖ Normal

Severity of issue fixed: Medium

Merge Risk: 🔵 Low · up to 8d896

In uncommon cases, settings promotion can write a TOML date Codex rejects, and a refused mirror can leave settings unapplied while reporting them as synced. These are bounded configuration and sync failures; merge with owner awareness and prioritize the fixes.

Architecture Summary

Architecture risk: 🔵 Low · up to 8d896

The change affects 3 systems.

Changed systems: src, config, package.json

Architecture concerns
No architecture-level concerns identified.

Review details

Systems and components

  • observed — src (service) was modified; 45 changed files map to changed impact.
  • observed — config (service) was modified; 3 changed files map to changed impact.
  • observed — package.json (service) was modified; 1 changed file maps to changed impact.

Before / after behavior

  • observed — Modified behavior in config/packaged-runtime-node-modules.cjs: Adds smol-toml to the packaged runtime package roots; the accompanying comment identifies its use for Codex config reading and validation in the main process and CLI.
  • observed — Modified behavior in config/scripts/relay-codex-config-toml-bundle.test.mjs: The test setup builds agent-workspace-trust-spawn.ts as a bundled CommonJS Node 18 artifact, loads applyRelayAgentWorkspaceTrust from that artifact, and removes the temporary directory after the suite.
  • observed — Modified behavior in config/scripts/relay-codex-config-toml-bundle.test.mjs: Adds a test that applies Codex trust to a workspace with a quoted ["projects"."…"] table and checks that its trust_level changes from untrusted to trusted.
  • observed — Modified behavior in config/scripts/relay-codex-config-toml-bundle.test.mjs: Adds a test that applies trust to a config containing both quoted and legacy project tables while Node 20 array-copy methods are unavailable. It restores those methods in a finally block, then checks the parsed project remains trusted and the config contains one trust_level.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.92% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 126 functions across 47 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed No active directly linked issue remains. Issue #22592 is closed and provides historical context only. Therefore, no linked-issue coding requirements apply. The PR addresses the historical duplicate-ta…
Out of Scope Changes check ✅ Passed The changes remain within the Codex config.toml safety scope. The checked writer, parser and structure helpers, duplicate repair, refusal handling, trust and settings edits, managed-home mirroring, SS…
Title check ✅ Passed The title clearly identifies the main change: routing Codex config.toml edits through a parser-checked writer. The (1/2) suffix is acceptable for a stacked change.
Description check ✅ Passed The description is complete and directly related to the changes. It includes the user impact, implementation details, rationale, linked issue, visual proof, testing, platform considerations, limitatio…
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

[High risk] Refactors Codex config file parsing and writing with new dependency.

The PR does not appear safe to merge while managed project trust can still disappear during mirroring.

Findings

  1. P1 Managed project trust disappears ▶

Summary

This PR routes Codex config.toml edits through parser-checked, format-preserving operations and adds repair for duplicate trust sections previously written by Orca.

  • Covers project and hook trust, settings promotion, managed-home mirroring, and SSH relay writes.
  • Adds tests for duplicate repair, invalid inputs, and managed-home behavior.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Read config.toml] --> B[Parse or repair known duplicates]
  B --> C[Apply text edit]
  C --> D[Parse and check intended values]
  D -->|Valid| E[Write config]
  D -->|Refused| F[Leave file unchanged]
Loading

Reviews (7) · Last reviewed commit: "test(codex): read the swept hooks.json w..."

Comment on lines +30 to +35
).filter(
// Why: ~/.codex defines this project inline or with dotted keys, so a
// runtime `[projects."…"]` table beside it would redefine it.
(section) =>
!isRuntimeProjectTomlSection(section.header) ||
!systemInlineProjects.has(getTomlSectionHeaderKey(section.header))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Managed project trust disappears When ~/.codex defines a project with inline or dotted keys but no trust_level, this filter drops the managed home's trusted project table. For example, a system project containing only "/repo".extra.q = 1 causes an existing managed [projects."/repo"] trust entry to disappear on the next mirror pass. Codex then loses that trust even though the user never revoked it.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — the whole PR: one parser-checked writer now owns every Orca edit of a Codex config.toml, plus a duplicate-repair pass, replacing the previous per-spelling text matchers.

  • New parser/atomic-edit layer — codex-config-toml-document (smol-toml@1.8.0 via literal require, BOM/CRLF aware, integersAsBigInt: 'asNeeded'), codex-config-toml-structure (decoded key paths, table blocks, Node-18-safe), and codex-config-toml-checked-edit (applyCheckedCodexConfigTomlEdit refuses an edit unless the result parses, holds the intended value, and leaves every unowned value unchanged).
  • Repair — codex-config-toml-repair removes only the exact Orca-appended duplicate shapes (keeps the user's first definition, re-parses to prove no removed value was lost) so an already-broken ~/.codex self-heals on the next trust write.
  • Every write routed through it — project trust (config-toml-project-trust matches inline/dotted/sub-table/escaped spellings), hook trust upsert/remove/enabled (config-toml-hook-trust-edit), settings promotion, the managed-home mirror, and the legacy shared home split into codex-config-mirror-{merge,source} / codex-config-legacy-shared-home-mirror.
  • Refusal handling — CodexConfigTomlEditRefusedError (reason/line/configPath), warnCodexConfigOnce bounds the once-per-file+message log at 500 entries; markCodexProjectTrusted now attempts every home and rethrows; reportCodexTrustWriteRefusals logs refusals once and returns other failures.
  • Relay/SSH — the same writer runs on the remote host; relay-codex-config-toml-bundle.test.mjs bundles the real esbuild externals and proves smol-toml is inlined and Node-18 array methods suffice.

The design's safety nets are the strongest part: a wrong merge result degrades to a refusal that keeps the last good copy and logs once, not a corrupt file. I read every TOC region and ran the new/targeted suites locally (checked-edit, mirror-duplicate-repair, syntax, config-toml project trust, stale writes, agent-trust-presets, launch-hook warning, hook-service user-hook mirroring, relay bundle, relay trust spawn) — all pass. The one acknowledged gap (managed-home duplicate path exercised in units only, not live) is disclosed in the PR body.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Adopts #23958's rules for Codex's quoted config.toml spellings and keeps one
implementation of each piece:

- Repair: #23958's Orca-trust duplicate rules (the user's table wins in either
  order) run first inside the checked writer's repair; the checked writer then
  drops only duplicates that add no value. Its own Orca-block and trust-line
  rules, and #23958's separate refusal logger, are removed.
- Trust writes stay on the checked writer; an existing quoted trust_level with
  a different value is rewritten bare, as #23958 does.
- Header matchers, the hooks.state parent check and the section scanner use
  the checked writer's helpers with #23958's rules; #23958's duplicates are
  removed. getProjectTrustLevel uses #23958's trust_level reader.
- Plugin and project hook trust carry is wired into the split mirror files.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — since the prior pullfrog review (60dcc2e), the branch merged origin/main, which brought main's own fix for the same #22592 duplicate-key bug (#23958, same author) and reconciled it with this branch's parser-checked writer. The two implementations are wired coherently: this branch's duplicate repair now delegates to main's, and the targeted suites, both typecheck projects, and the relay bundle test all pass locally.

  • Merged origin/main — imported main's quoted-spelling recognition and Orca-duplicate repair, then reconciled it with this branch's checked writer.
  • Adopted main's repair core — added config-toml-project-duplicate-repair.ts and config-toml-project-trust-level.ts; codex-config-toml-repair.ts now runs repairOrcaDuplicateTrustTables first, then collapses any remaining value-neutral duplicates, with refusal logging left to the checked writer.
  • Carried plain-Codex plugin/project hook trust into managed homes — classifyHookTrustKey / getHookTrustTomlSectionKeys, a sharedHookTrust option on stripRuntimeOwnedTomlSections, and a new systemConfigDir argument on mergeSystemCodexConfigIntoRuntime.
  • Broadened header matching — ensureHooksStateParentTable now treats any hooks.state.* depth as a child, and a quoted trust_level key is rewritten bare in place.
  • Added coverage — hook-trust carry and spellings, project/hook duplicate repair, and the Node-18 relay bundle.

ℹ️ Two implementations for #22592 now coexist

Main's #23958 already fixes the duplicate-key bug this PR targets. The branch keeps that fix and layers its parser-checked writer on top, which is coherent and tested — but the PR description still presents this as the first and only fix and never mentions #23958. A one-line note on how the two are meant to relate (supersede, absorb, or stay layered) would help reviewers judge the intended end state.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Codex can write "trusted_hash" and "enabled" quoted; main's reader only
matched the bare names, so a quoted "enabled" = false read as enabled.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — since the prior pullfrog review (ad682c1), the delta is a single test-only commit.

  • Pinned quoted hook-trust field names — config-toml-hook-trust-read.test.ts asserts readHookTrustContent reads "trusted_hash" / "enabled" when the field names are quoted, both on a file that parses and on a duplicate-key file that falls back to the structural scan. Both cases exercise the production reader end-to-end and read real values (trustedHash: 'sha256:abc', enabled: false), so they would fail against a bare-name-only matcher. The new file passes locally (2/2).

No production code changed in this delta, so no behavioral surface to re-check; the config-toml-hook-trust-read.ts parser refactor the test exercises is pre-ad682c1 branch code, already covered by the prior review.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Brings in #23552 (cfa43e7), which moves a shifted user hook's trust block
to its new key (moveHookTrustContent / moveHookTrustEntries) instead of
rebasing it through a Codex session. Conflicts and resolutions:

- config-toml-hook-trust-edit.ts: ported main's moveHookTrustContent into the
  checked writer. One applyCheckedCodexConfigTomlEdit call now strips the old
  and new keys' blocks (every spelling, matched by decoded key) and appends the
  moved bodies verbatim. Owned paths are the old/new keys plus their spellings;
  each new key must hold the old block's parsed values; an invalid result is
  refused. Main's guards stay: nothing to move or a stored key of unknown shape
  returns the file unchanged without parsing. Dropped main's stale
  repairOrcaDuplicateTrustTables import (#23930 moved repair into
  codex-config-toml-repair). appendTrustBlocks became appendTomlBlock, shared
  by the upsert and the move.
- config-toml-syntax.ts: kept main's exported CODEX_HOOK_TRUST_KEY and
  #23930's decoded-key header parsing.
- config-toml-runtime-owned-sections.ts: #23930's import block plus main's
  CODEX_HOOK_TRUST_KEY; main's local copy of the regex stays removed.
- config-toml-trust.ts: union of imports (move, remove, setEnabled, upsert).
  moveHookTrustEntries keeps main's name and signature but now wraps the edit
  in withConfigPath and writes with writeTomlConfigAtomically, like its
  sibling hook-trust writers.

Outside the conflicts: codex-user-hook-trust-moves.ts reports a refused move
through reportCodexConfigTomlEditRefusal (once per file and message) instead
of console.warn on every hooks write. Added tests: a quoted-spelling stale
table at the new key leaves one parseable table, and a hand-broken config is
left untouched with the refusal logged once.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — since the prior pullfrog review (01030ef0), the only new commit is the merge of origin/main (3ab3c92) into the branch. It adopts main's own user-hook-trust rework (#23552) and re-integrates this branch's parser-checked writer with it. I read the net delta on every PR file that changed since 01030ef0, completed the full-diff TOC read, and ran the touched suites plus both typecheck projects; all pass.

  • Merged origin/main, adopting #23552's user-hook-trust rework — codex-user-hook-trust-rebase{,-client}.ts are gone; codex-user-hook-trust-moves.ts replaces them with a synchronous mutateRealHomeHooksPreservingUserTrust (no runtimeHomePath / restoreHooks). codex-hook-legacy-cleanup.ts, codex-real-home-hook-install.ts, codex-real-home-hook-sweep.ts, and startup/codex-launch-preparation.ts now follow main's newer flow.
  • Routed the shifted-hook trust move through the checked writer — new moveHookTrustContent (config-toml-hook-trust-edit.ts) runs the move under applyCheckedCodexConfigTomlEdit, asserts each moved block still holds the source value at its new key, and refuses (once) a config Codex cannot parse; new moveHookTrustEntries (config-toml-trust.ts) wraps it with the mutation-lane path and atomic write. The move's catch in codex-user-hook-trust-moves.ts reports a refusal once and leaves other failures to a plain warn.
  • Deduplicated CODEX_HOOK_TRUST_KEY into config-toml-syntax.ts (imported by config-toml-runtime-owned-sections and hook-trust-edit), and generalized appendTrustBlocks to appendTomlBlock.
  • Added coverage — codex-user-hook-trust-moves.test.ts now pins that a stale table at the new key is replaced with exact bytes and that an unparseable config.toml is left untouched with the refusal logged once.

The merge leaves the branch's writer layer coherent on top of main's move logic: the moved block is the only thing that changes, its value is verified at the new key, and any result that would not parse is refused rather than written. No prior pullfrog threads were open, and no new issue surfaced.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

…ite is refused

When ~/.codex/config.toml can't be parsed, the managed mirror copies it, so the
managed-home trust write is refused first. Its catch returned before the legacy
sweep, so a retired Orca entry stayed in ~/.codex/hooks.json and the user hook's
trust move was never attempted (found in Windows QA). The sweep now runs on that
error path too; its move is refused and logged once, as on any unreadable file.

The status detail no longer ends "parse.. Run /hooks in Codex to approve." for an
unreadable file, where /hooks can't help.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — since the prior pullfrog review (b6afcb5), the only new commit is 0262518, a Windows-QA follow-up to the refused-trust-write path.

  • Legacy sweep now runs on a refused trust write — installCodexHooksExclusively and refreshCodexRuntimeUserHooksExclusively call cleanupLegacyManagedHookRepresentations() in their catch before returning. Previously the refused managed-home trust write returned early and left a retired Orca entry in ~/.codex/hooks.json, and never attempted the user hook's trust move. The sweep was already on each function's success path; it swallows its own errors and re-enters the system-config lane through the AsyncLocalStorage pass-through.
  • Centralized the hook-trust failure detail — new describeHookTrustWriteFailure(summary, error, approveAdvice) returns ${summary}: ${error.message} without the /hooks advice for a reason === 'input-invalid' refusal (where /hooks cannot help), and otherwise strips trailing periods before appending the advice. Replaces the inline templates in the local install, local maintenance, remote install, and WSL runtime status details.
  • Added coverage — hook-service-refused-trust-legacy-sweep.test.ts (hooks on and off) hand-breaks ~/.codex/config.toml so the mirror copies it and the managed trust write is refused, then asserts the retired entry is removed while the user hook survives, the broken TOML is byte-identical, the detail carries no .. or /hooks, and the trust-move refusal logs once across two launches.

The delta is narrow and coherent: the sweep is idempotent and self-error-swallowing, and the new test targets exactly the pre-fix behavior (without the catch sweep the retired entry would remain and no move refusal would be logged). Verified locally: the new test passes 2/2, the related hook-service-user-hook-mirroring and hook-service-legacy-cleanup suites pass (21), the relay bundle test passes, and pnpm tc:node / pnpm tc:cli are clean. There were no open pullfrog review threads to retire.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Removing a retired Orca entry from ~/.codex/hooks.json shifts the user hooks
after it, so their approvals must move in config.toml in the same step. When
config.toml can't be parsed that move is refused, and sweeping anyway left the
user's approval at the old key and the retired entry's trust at the new one:
after the user fixed the file, Codex asked them to review their own hook again.

The retired-entry sweep now plans the config.toml edit first and, if the file
can't be read, leaves hooks.json untouched and logs once. The next launch
re-derives the sweep from hooks.json and moves the approval cleanly. A refusal
no longer escapes as a stack trace, and the legacy profile cleanup no longer
depends on the sweep succeeding. The real-home lanes are unchanged.
Comment thread src/main/codex/codex-hook-legacy-cleanup.ts

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues — one minor suggestion inline.

Reviewed changes — since the prior pullfrog review (0262518), two commits replace "sweep ~/.codex/hooks.json even when the trust write is refused" with an explicit wait.

  • Waited instead of sweeping while config.toml is unreadable — new planRetiredHookSweepTrust computes the config.toml side (the shifted user-hook trust moves and the retired entries' own trust removal) before hooks.json is touched; an input-invalid refusal now leaves both files byte-identical, logs once, and re-derives the sweep on the next launch.
  • Extracted the planner into codex-retired-hook-sweep-trust.ts, and listed it in the CLI project so codex-hook-legacy-cleanup.ts type-checks under tc:cli.
  • Separated the legacy profile cleanup into its own try/catch so it still runs when the system sweep throws.
  • Rewrote the coverage in hook-service-refused-trust-legacy-sweep.test.ts to prove the wait (both files byte-identical, one log) and the eventual sweep and approval move once the file is fixed.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

collectManagedTrustEntries,
removeSelfComputedMatchingTrustEntries
} from './codex-hook-trust-cleanup'
import { collectManagedTrustEntries } from './codex-hook-trust-cleanup'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removeSelfComputedMatchingTrustEntries lost its only caller in this commit: planRetiredHookSweepTrust inlines the same self-computed-hash match (trust.get(computeTrustKey(entry))?.trustedHash === computeTrustedHash(entry)) instead of reusing it. If step 2 (#23931) does not reintroduce a caller, delete the now-unused export in codex-hook-trust-cleanup.ts (or have the planner reuse it) so the logic does not live in two places.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 1cb9ea59-7ee4-4d02-b3cf-57f84e273a99

📥 Commits

Reviewing files that changed from the base of the PR and between 0262518 and 37a7f5e.

📒 Files selected for processing (4)
  • config/tsconfig.cli.json
  • src/main/codex/codex-hook-legacy-cleanup.ts
  • src/main/codex/codex-retired-hook-sweep-trust.ts
  • src/main/codex/hook-service-refused-trust-legacy-sweep.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 6 remain after this review.

Comment thread src/main/codex/hook-service-refused-trust-legacy-sweep.test.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to GitHub limitations.

⚠️ Outside diff range comments (2)

🟡 Minor · Reject non-Codex TOML values before promotion. · codex-config-toml-document.ts:17-39

src/main/codex/codex-config-toml-document.ts:17-39
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Reject non-Codex TOML values before promotion.

smol-toml 1.8.0 normalizes impossible dates such as 2023-02-30 instead of rejecting them. During settings promotion, raw values from the runtime config pass through upsertPromotedSettingsInContent and applyCheckedCodexConfigTomlEdit. The checked edit validates only with parseCodexConfigToml, then the promotion writes the result. Therefore, a runtime value such as model = 2023-02-30 can replace a valid system value and produce a file that the Codex TOML reader cannot load, while Orca reports a successful write. Use Codex-compatible validation for promoted values before writing.

🟡 Minor · Report a stall after refusing invalid output. · codex-config-mirror.ts:75-79

src/main/codex/codex-config-mirror.ts:75-79
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Report a stall after refusing invalid output.

The new refused-invalid branch returns before it reports a sync outcome. The Accounts/config-sync handler recomputes status from the selected home and can return synced when the source and existing managed config are readable. The mirror can therefore keep the previous settings while the status reports that the settings were applied. Record an explicit stalled status for this branch, using the same status channel as refused-indeterminate.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 76449d0b-0630-4557-8046-c55cbc0165ba

📥 Commits

Reviewing files that changed from the base of the PR and between 37a7f5e and 8d89699.

📒 Files selected for processing (1)
  • src/main/codex/hook-service-refused-trust-legacy-sweep.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 2 remain after this review.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Codex config.toml gets a duplicate [projects."…"] table (Orca does not recognize Codex's ["projects"."…"] headers), breaking codex startup

1 participant