Summary
jobs/<id>.json never records what model, reasoning effort, or sandbox a job actually executed with. Background task jobs persist the raw CLI flags, which are null whenever the caller relied on ~/.codex/config.toml defaults; foreground task jobs and all review jobs record nothing at all. External tooling that wants to display "this job ran gpt-5.4 / medium / read-only" has to reverse-engineer it from Codex CLI rollout files.
Evidence (at HEAD db52e28, plugin v1.0.6)
- Base job records carry no model/effort fields:
createCompanionJob (plugins/codex/scripts/codex-companion.mjs:567-578) plus createJobRecord (plugins/codex/scripts/lib/tracked-jobs.mjs:60-68) produce id, kind, kindLabel, title, workspaceRoot, jobClass, summary, write, createdAt, sessionId.
- Background tasks additionally persist the raw request —
enqueueBackgroundTask stores request (codex-companion.mjs:689-698), built from the CLI flags as passed (buildTaskRequest, codex-companion.mjs:604-614). If --model/--effort were omitted, request.model/request.effort are null, while the job really runs with the config.toml defaults resolved by the app-server.
runTrackedJob never adds resolved values to the running or completed record (tracked-jobs.mjs:142-204).
- Review jobs and foreground tasks go through
runForegroundCommand with no request persisted at all (codex-companion.mjs:731-752, 807-822).
- The resolved values are available to the plugin: the
thread/start / thread/resume response already carries model, reasoningEffort, sandbox, and approvalPolicy — the repo's own fake app-server mirrors this shape (tests/fake-codex-fixture.mjs:316).
Repro
node scripts/codex-companion.mjs task --background "any prompt" (no --model, no --effort).
- Inspect
$CLAUDE_PLUGIN_DATA/state/<slug>-<hash>/jobs/<id>.json: request.model and request.effort are null; no other field names the model/effort/sandbox.
- Run
node scripts/codex-companion.mjs review: the stored job has no model/effort trace at all.
- The actual values only exist in the Codex CLI rollout
turn_context entries under $CODEX_HOME/sessions/YYYY/MM/DD/rollout-<ts>-<threadId>.jsonl.
Proposed fix
At thread/turn start, write the resolved model, effort, and sandbox (as reported by the app-server response) into the job record on all paths — background tasks, foreground tasks, and reviews — e.g. alongside threadId/turnId in the running record written by runTrackedJob.
Happy to follow up with a PR if this direction sounds right.
Why it matters
The downstream log watcher @cubicj/codex-watch displays a per-job session-info line. To get it, it joins the job's threadId against rollout filenames and parses turn_context payloads. That workaround is fragile in ways the plugin can't see: rollout date directories use local time while job timestamps are UTC, resumed threads live under the thread's original date directory, and rollouts are pruned independently of job records. One field written at turn start removes the entire join.
Related
Environment
- Plugin
codex@openai-codex v1.0.6 (upstream HEAD db52e28)
- Codex CLI 0.145.0-alpha.2
- Claude Code on WSL2 Ubuntu 26.04, Node v24.18.0
Summary
jobs/<id>.jsonnever records what model, reasoning effort, or sandbox a job actually executed with. Background task jobs persist the raw CLI flags, which arenullwhenever the caller relied on~/.codex/config.tomldefaults; foreground task jobs and all review jobs record nothing at all. External tooling that wants to display "this job ran gpt-5.4 / medium / read-only" has to reverse-engineer it from Codex CLI rollout files.Evidence (at HEAD db52e28, plugin v1.0.6)
createCompanionJob(plugins/codex/scripts/codex-companion.mjs:567-578) pluscreateJobRecord(plugins/codex/scripts/lib/tracked-jobs.mjs:60-68) produceid,kind,kindLabel,title,workspaceRoot,jobClass,summary,write,createdAt,sessionId.enqueueBackgroundTaskstoresrequest(codex-companion.mjs:689-698), built from the CLI flags as passed (buildTaskRequest,codex-companion.mjs:604-614). If--model/--effortwere omitted,request.model/request.effortarenull, while the job really runs with the config.toml defaults resolved by the app-server.runTrackedJobnever adds resolved values to the running or completed record (tracked-jobs.mjs:142-204).runForegroundCommandwith norequestpersisted at all (codex-companion.mjs:731-752,807-822).thread/start/thread/resumeresponse already carriesmodel,reasoningEffort,sandbox, andapprovalPolicy— the repo's own fake app-server mirrors this shape (tests/fake-codex-fixture.mjs:316).Repro
node scripts/codex-companion.mjs task --background "any prompt"(no--model, no--effort).$CLAUDE_PLUGIN_DATA/state/<slug>-<hash>/jobs/<id>.json:request.modelandrequest.effortarenull; no other field names the model/effort/sandbox.node scripts/codex-companion.mjs review: the stored job has no model/effort trace at all.turn_contextentries under$CODEX_HOME/sessions/YYYY/MM/DD/rollout-<ts>-<threadId>.jsonl.Proposed fix
At thread/turn start, write the resolved
model,effort, and sandbox (as reported by the app-server response) into the job record on all paths — background tasks, foreground tasks, and reviews — e.g. alongsidethreadId/turnIdin the running record written byrunTrackedJob.Happy to follow up with a PR if this direction sounds right.
Why it matters
The downstream log watcher @cubicj/codex-watch displays a per-job session-info line. To get it, it joins the job's
threadIdagainst rollout filenames and parsesturn_contextpayloads. That workaround is fragile in ways the plugin can't see: rollout date directories use local time while job timestamps are UTC, resumed threads live under the thread's original date directory, and rollouts are pruned independently of job records. One field written at turn start removes the entire join.Related
--effort; same underlying theme (effort is invisible/unthreaded), different bug./codex:observestructured event stream; complementary observability interest.Environment
codex@openai-codexv1.0.6 (upstream HEAD db52e28)