Skip to content

Add declared Codex app-server delivery - #241

Closed
myobie wants to merge 23 commits into
mainfrom
agent/native-delivery-review-implementation
Closed

Add declared Codex app-server delivery#241
myobie wants to merge 23 commits into
mainfrom
agent/native-delivery-review-implementation

Conversation

@myobie

@myobie myobie commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Review order

The branch contains the original implementation commits in build order:

  1. delivery selector and Doctor support
  2. controlled app-server launch and thread binding
  3. subscribed turn-state tracking and response-ID correction
  4. idle start / exact active steer delivery plus review and compaction holds
  5. payload-neutral transport assertion
  6. typed delivery receipt, resume reconciliation, and fresh-thread activation
  7. exact Codex 0.146 protocol compatibility and admission guidance
  8. shared authored configuration for app-server and remote TUI
  9. bounded wrapper startup diagnostics
  10. checked child cleanup if diagnostic persistence fails
  11. response-driven resumed-thread binding after the TUI-start gate
  12. typed TUI-loaded inventory gate before control resume
  13. durable tuiThreadLoaded trace acknowledged before control resume
  14. inner TUI-loaded deadline separated from the outer binding deadline
  15. transient exact-hash hook trust for persistent remote resume
  16. root-option authorization boundary for transient trust

This additive branch starts at current main. It restacks the #237 receipt commits on the corrected #236 tree without moving any existing branch.

Relationship to #239

agent/native-delivery-codex-receipt remains frozen at exact 1d06c4b, so #239 keeps its existing base. #239 is not part of this pull request and owns the bounded body renderer layered over this transport.

Provider compatibility

The original live acceptance used Codex CLI 0.145.0. The first Silber scratch precondition then found Codex CLI 0.146.0 and stopped before creating a worktree, build, declaration, or process.

I generated both exact app-server v2 schema sets. The delivery-critical methods remain compatible:

  • turn/steer, thread/status/changed, contextCompacted, and review-start inputs are byte-identical
  • thread start/resume, turn start, lifecycle notifications, and item receipts retain every field and response path consumed here
  • 0.146 adds optional thread/plugin metadata and an unrelated external-import-history method

The version gate now has a hermetic regression that accepts exactly 0.145.0 and 0.146.0 and rejects 0.147.0. The allowlist comment requires the next version to repeat both the critical-path schema comparison and live remote-TUI acceptance; semantic-version proximity is not evidence. The resumed Silber scratch proved real reconcile with no DING sidecar, idle typed wake, and agent-owned archive settlement. A message sent during an observed foreground busy window was replied to after the wait with no visible composer corruption or duplicate turn, but the first evidence packet looked only at the PTY record and did not capture the adapter's hash-keyed control state. Exact same-turn identity remains an evidence gate.

Validation

At exact head b97ea8f:

  • git diff --check origin/main..HEAD
  • rustfmt --edition 2024 --check src/codex_app_server.rs
  • cargo check --locked
  • cargo test --locked --lib --no-fail-fast -- --test-threads=1: 298 passed across workspace libraries
  • cargo test --locked --test codex_app_server --test doctor --test validate --test reconcile --test run --no-fail-fast: 133 passed
  • cargo clippy --locked --all-targets --no-deps: exit 0 with inherited warnings only
  • exact Codex CLI 0.145.0 and 0.146.0 accept the forwarded app-server config grammar
  • the app-server config regression forwards config/feature/strictness inputs, excludes TUI-only args, and rejects ambiguous boundaries
  • the wrapper diagnostic regression proves 0600 permissions, one-run truncation, terminal error retention, and omission of authored values
  • diagnostic-write failures after child spawn retain the normal checked child cleanup path
  • resumed control sends nothing before the TUI-start gate; polls typed thread/loaded/list until it sees the preserved thread; records and acknowledges tuiThreadLoaded before sending control thread/resume; then binds from the exact response, reconciles history before delivery, and leaves a missing-rollout binding on its prior incarnation
  • the 15-second TUI-loaded deadline is strictly earlier than the 30-second outer binding deadline, and an empty typed inventory reports its specific inner error before the outer wait can mask it
  • persistent remote resume with authored hook-trust bypass runs a bounded typed hooks/list preflight, projects only exact untrusted/modified provider key+hash pairs into final app-server session flags, and fails closed on response drift without logging or persisting trust data
  • exact Codex CLI 0.146.0 reports the projected hash as trusted; the probe leaves config.toml without hook trust state

A parallel full-lib run on the prior head exposed one existing owner-lock timing failure; the complete suite passes serially, including that exact test. The prior ef9e2e8 head passed hosted Nix in run 31534396593. The corrected config-forwarding head 65206bc passed hosted Nix in run 31538400622 (9m 34s). The diagnostic head 5f8d601 passed hosted Nix in run 31540650233 (11m 48s). Exact-head d28005f passed hosted Nix in run 31542574907 (12m 05s; job 93948092773, 2026-08-11 22:28:43Z–22:40:48Z). Exact-head 6cd52a0 passed hosted Nix in run 31545093692 (9m 18s; job 93955745681, 2026-08-11 23:05:21Z–23:14:39Z). Exact-head 4c1451b passed hosted Nix in run 31546501495 (11m 42s; job 93960047096, 2026-08-11 23:26:51Z–23:38:33Z). Exact-head 2b06652 passed hosted Nix in run 31548731523 (12m 48s; job 93966600692, 2026-08-12 00:02:18Z–00:15:06Z). The final authorization-safe head b97ea8f passed hosted Nix in run 31549791361 (12m 52s; job 93969808942, 2026-08-12 00:19:34Z–00:32:26Z). The live Codex 0.146 scratch passed reconcile selection, idle wake, behavioral busy-window delivery, agent-owned settlement, and checked teardown; all seven Silber controls and all three independently observed Hetz DING process trees remained unchanged. The exact active turn ID and client receipt were not captured from the adapter state directory, so the stronger same-turn provider condition is still open. The scratch workspace was also untrusted because the wrapper dropped its authored trust override when starting app-server, so Codex disabled project-local hooks. The corrected r2 scratch reproduced the literal declaration and CAS preconditions, then timed out after publishing a new runtime incarnation but before any thread binding. It restored the original declaration, left no process, and preserved every control. The exact 5f8d601 diagnostic trace recorded resumeSelected=true, connected and initialized the control socket, started the TUI, then expired only at waitingForThreadBinding after 30 seconds. That eliminates socket setup and proves the observer waited for a resume notification the provider does not promise. This head sends the control client's exact thread/resume only after the TUI-start gate and binds the new incarnation from its successful response. Production-parity hook loading and exact same-turn/client evidence remain held for a new exact-head scratch. A separate inert closure issue is held: external catalog synchronization rematerialized the scratch agent.kdl after a local move, with no matching process or runnable Silber task. It requires a sync-aware cleanup plan.

R3 proved the response-driven control bind at the preserved thread and new runtime incarnation, with no failure record and correct shared trust configuration. It did not produce READY-BOOT or the SessionStart canary. Exact Codex 0.146 source and the current Codex manual show that resumed TUI startup does consume the authored prompt and emits SessionStart with source resume, so those absences are not intended resume semantics. This head closes the remaining cold-resume race by waiting for the TUI-loaded inventory before the redundant control resume, and makes that ordering live-observable. R4 then exposed an observability defect: the inner loaded-thread wait and outer binding wait both used 30 seconds, so the outer generic error won and the three provider-specific outcomes were practically unreachable. R4 restored the catalog exactly, left zero processes, preserved every binding/control invariant, and its zero-byte app-server log change is explicitly not trust evidence. This head makes the inner deadline 15 seconds and keeps the outer at 30 seconds. R5 proved that correction: it emitted the specific loaded-thread timeout before the outer wait, and a read-only PTY capture showed the owning TUI blocked at Hooks need review. Exact Codex 0.146 source intentionally suppresses the authored bypass for every persistent remote resume; current upstream main retains that behavior. Exact implementation head 2b06652 then passed startup-only R6: preflight projected four hooks, its owned PID and socket were gone before final launch, tuiThreadLoaded, threadBound, READY-BOOT, and the SessionStart canary all appeared, and runtime, binding, and subscribed control state shared one new incarnation on the preserved thread. The global Codex config remained byte-identical with no persisted hook trust; checked teardown and CAS restore were green. The R6 packet's later hold crossed teardown after this pass. A post-release walk had found that the authorization detector also scanned prompt bytes after --; the tested declaration genuinely authored the root flag before its prompt, so both heads take the same true-positive path and the mechanism evidence remains valid. Final head b97ea8f restricts authorization to the parsed root-option prefix and adds a rejecting regression; its exact hosted gate is green. A duplicate live catalog mutation would not exercise changed true-positive behavior, so no repeat was run. C2 and production stay held.

This pull request remains draft for Nathan's review.

@myobie

myobie commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

Closing this in favour of #254, which is the same work plus the Claude half, in one pull request as Nathan asked.

#254's branch already contained every commit on this one. I confirmed that with git merge-base --is-ancestor rather than reading the log: b97ea8ff is an ancestor of b184715. Then I merged current main into it, which was clean, and it is 12 commits fresher than this branch.

Nothing is lost by closing this. The branch stays.

One thing I found while folding, and it applies to this branch too: three tests fail on macOS and they fail here as well, before the merge. CI is ubuntu-latest only, so the green check on this pull request proves Linux and nothing about Darwin. Detail is in #254.

@myobie myobie closed this Aug 13, 2026
@schickling schickling added area:agent-spec Agent Spec format, parsing, and the agent-spec crate · Set: manual area:ding DING delivery: inbox notice into a running agent · Set: manual area:driver Harness drivers: launch, MCP, app-server, native delivery · Set: manual harness:codex Codex-specific behavior · Set: manual origin:agent Filed or primarily produced by an AI agent · Set: manual type:feature New user-visible or system capability · Set: manual labels Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:agent-spec Agent Spec format, parsing, and the agent-spec crate · Set: manual area:ding DING delivery: inbox notice into a running agent · Set: manual area:driver Harness drivers: launch, MCP, app-server, native delivery · Set: manual harness:codex Codex-specific behavior · Set: manual origin:agent Filed or primarily produced by an AI agent · Set: manual type:feature New user-visible or system capability · Set: manual

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants