# `CodexWrapper.ObservedExecution`
[🔗](https://github.com/genagent/codex_wrapper_ex/blob/v0.8.1/lib/codex_wrapper/observed_execution.ex#L1)

Shared opt-in execution for fresh, resumed and forked commands.

Pass `session_observer: {local_pid, reference}` to `Exec.execute/3`,
`ExecResume.execute/3`, `ExecFork.execute/3`, `ExecFork.fork/3` or `Review.execute/3`.
Existing `CodexWrapper.exec/2` and `exec_json/2` accept the same option.
Observed commands force `--json` and require a runner implementing
`c:CodexWrapper.Runner.run_observed/5`; no Port fallback occurs.

Add `execution_observer: {local_pid, reference}` to request a terminal
`CodexWrapper.ExecutionObservation` on success or failure. This requires
`c:CodexWrapper.Runner.run_evidenced/5` and never falls back. Supply both
observer options for early identity followed by terminal evidence. The caller
sends both facts before returning. The evidence path uses finite wall/idle
bounds (300,000 ms by default) and combined output (1 MiB by default),
configurable with `Config.runner_options`. A valid execution target also
receives a terminal fact for capability/option preflight failures; an invalid
execution target cannot be notified. Missing cleanup remains unknown.

Only the first valid stdout `thread.started` with a nonblank `thread_id`
produces a `CodexWrapper.SessionObservation`. Malformed, duplicate and
conflicting later announcements are ignored. Stderr cannot supply identity.
A dead observer is harmless. The execution caller sends the observation
before returning, preserving order with its later reply to that observer.

Results retain every byte in separate stdout and stderr fields. Legacy
`execute/2` keeps its merged output. Exit codes and process success semantics
are unchanged, including a successful process with no thread announcement.
Completion waits for the transport, not a JSON event. The configured
whole-run timeout and runner cleanup apply; no new idle timeout is added.

Identity framing uses at most 1 MiB per line. Oversized lines are ignored
until the next newline without changing final raw output. Observer targets
and runner support are checked before spawning. Invalid options return
`{:error, :invalid_session_observer}`; unsupported runners return
`{:error, {:observation_unsupported, runner}}`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
