Skip to content

Retire Codex free-function adapters behind BackendRunner - #1169

Open
Kh1ng wants to merge 1 commit into
mainfrom
codex/backend-runner-codex
Open

Kh1ng wants to merge 1 commit into
mainfrom
codex/backend-runner-codex

Conversation

@Kh1ng

@Kh1ng Kh1ng commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Codex dispatch already used BackendRunner, but its implementation still passed through two public free functions. Move the existing spawn, log, summary, and transcript code into CodexRunner and retire run_codex / run_codex_with_executable, completing the Codex cleanup step in #832. The remaining backend migrations stay on that issue.

CLI arguments, environment handling, process supervision, and result collection are unchanged. The Rust library intentionally drops the two old Codex helper paths; callers use CodexRunner.run(&RunContext) instead. No other backend or review code changes.

Validation: preserve all seven existing Codex process/argv tests through the trait, and strengthen the registry test to check an explicitly selected executable and the full ordered argv. cargo fmt --check and git diff --check pass locally. Rust tests and Clippy run in CI to avoid recreating the Mac build cache.

@Kh1ng

Kh1ng commented Sep 10, 2026

Copy link
Copy Markdown
Owner Author

Review verdict: hold — conflicts with a design decision that landed on main after this branch was cut, and it retires only half the facade.

  1. Conflicts with refactor(dispatch): route backend invocation through BackendRunner::for_kind #1173 (merged 2026-09-10). This branch predates refactor(dispatch): route backend invocation through BackendRunner::for_kind #1173, which reworked run_backend_with_reserved_route into for_kind(backend_kind).run(&RunContext) with a per-kind LaunchShape, and made a deliberate call on the facade: the free functions remain as the pinned public boundary (documented in the Backend abstraction unification, Phase 1: BackendRunner trait for dispatch, migrated one backend at a time #832 close comment). This PR takes the opposite stance for codex only. Both stances are defensible — but retiring codex's free functions while claude/vibe/opencode/openhands/agy keep theirs leaves the facade half-migrated, which is worse than either extreme.

  2. Textual conflicts. src/dispatch/attempts.rs and src/runner/mod.rs moved substantially (LaunchShape, for_kind re-export), and RunResult gained the resources field (feat(telemetry): per-attempt process-tree CPU time and peak RSS with provenance #1172/Capture per-attempt CPU time and peak RSS with provenance #116) that codex's spawn path must now thread.

Suggested path: keep the direction, but make it a complete step — retire ALL backend free functions in one change, move each backend's spawn/log/summary body into its BackendRunner impl, update runner_adapter_facade_preserves_public_call_paths to pin the *Runner types instead, and rebase onto current main (threading resources through codex's path). Happy to take that as one follow-up PR, or re-review a rebased all-backends version.

Kh1ng added a commit that referenced this pull request Sep 10, 2026
…ner (#1182)

Completes the #832/#1169 direction for ALL backends (the #1169 PR did
codex only, which left the facade half-migrated):

- Each backend's spawn/log/summary body moves to a crate-private
  run_with_executable() in its own module; the BackendRunner impl is the
  only caller. The public run_* and run_*_with_executable wrappers are
  deleted, as are their facade re-exports.
- runner_adapter_facade_preserves_public_call_paths now pins the
  BackendRunner abstraction (for_kind + the seven *Runner types) instead
  of the retired free functions.
- Backend golden tests drive their core functions as before; NEW
  contract tests in backend_runner_contract_tests.rs drive all seven
  backends through the production path (for_kind(kind).run(&ctx)) with
  recording binaries, pinning each CLI's argv shape, stream handling,
  and result collection — the layer where runner wiring and CLI
  contracts meet.

Per-backend golden tests below the runner path keep covering deeper
behavior (stall kills, usage extraction, transcript binding, resource
capture).

Co-authored-by: Colton Spurgin <colton@coltonspurgin.tech>
Kh1ng added a commit that referenced this pull request Sep 10, 2026
#1183)

* refactor(runner): retire all backend free functions behind BackendRunner; add runner-path contract tests

Completes the #832/#1169 direction for ALL backends (the #1169 PR did
codex only, which left the facade half-migrated):

- Each backend's spawn/log/summary body moves to a crate-private
  run_with_executable() in its own module; the BackendRunner impl is the
  only caller. The public run_* and run_*_with_executable wrappers are
  deleted, as are their facade re-exports.
- runner_adapter_facade_preserves_public_call_paths now pins the
  BackendRunner abstraction (for_kind + the seven *Runner types) instead
  of the retired free functions.
- Backend golden tests drive their core functions as before; NEW
  contract tests in backend_runner_contract_tests.rs drive all seven
  backends through the production path (for_kind(kind).run(&ctx)) with
  recording binaries, pinning each CLI's argv shape, stream handling,
  and result collection — the layer where runner wiring and CLI
  contracts meet.

Per-backend golden tests below the runner path keep covering deeper
behavior (stall kills, usage extraction, transcript binding, resource
capture).

* feat(ledger): keep external-approval grants within the pending request (#1170 take-over)

Ported from the codex branch (codex/external-approval-state), rebased
onto today's main. External approval grants previously accepted a
missing or broader pending request, reset consumption on replay, and
could clear an unrelated human hold. Now:

- Grants require a pending request; omitted bounds inherit from it.
- Scope expansion (service label, env vars, request/dollar caps,
  expiry) is rejected under the ledger write lock.
- Inspection and credential injection share one replay implementation.
- Sparse lifecycle records retain bounds and purpose; consumption
  preserves granted credentials when configuration changes.

Also splits the pure gate/alias/index analysis out of jsonl.rs into
ledger/gates.rs — fixing the source-size-guard failure that made the
original PR's CI red (jsonl.rs was 1518 lines; now 1290).

Full docs in docs/EXTERNAL_APPROVALS.md (from the same branch).

---------

Co-authored-by: Colton Spurgin <colton@coltonspurgin.tech>
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.

1 participant