Summary
scripts/lib/resident-ensure.mjs unconditionally installs each resident role charter as a standing thread goal (thread/goal/set) in both startRoleThread and resumeRoleThread. Under codex CLI >= 0.146 (where the app-server auto-starts goal turns from standing objectives), this causes resident role threads to run turns nobody assigned:
- A role charter is a non-terminating objective — it can never be satisfied — so the runtime re-arms a new goal turn within milliseconds of each completion (we observed 2–9 ms).
- Unassigned resident threads (e.g. a reviewer/researcher role that has received no work) self-run autonomous turns indefinitely. In our deployment, idle role threads self-ran for ~2.5 weeks; rollout files grew to ~1.4 MB per thread with zero assignments.
- Worse, a goal turn can start concurrently with an actual assigned task turn on the implementer thread, producing a two-writer hazard inside a single working directory (we observed duplicated edits from overlapping turns in one repo checkout).
- Broker/thread status reports
idle / activeTurnId: null while these goal turns are executing, so the behavior is invisible to normal supervision.
Note the goal-set signature predates 0.146 in our logs — 0.146's auto-start changed the severity, not the mechanism.
Asks
- Make standing-goal installation opt-in (config/env flag), or stop installing role charters as goals entirely — a charter is descriptive context, not a completable objective. We have locally gated both
thread/goal/set calls behind an env flag (default off) as a containment patch.
- Expose a
thread/goal/clear API. Today there appears to be no way to remove a standing goal from a thread; that blocks the cleaner end-state of setting a per-task terminal goal at dispatch time and clearing it on completion.
Environment
- codex-cli 0.146.0 (model gpt-5.6-sol), plugin codex@openai-codex v1.0.6, resident triad via the broker daemon
- macOS (Darwin 25.5), Claude Code 2.1.220 host
Repro sketch
- Bootstrap the resident triad (three role threads) with the stock
resident-ensure.mjs.
- Assign no work to reviewer/researcher threads.
- Observe rollouts: goal turns start unprompted and re-arm continuously; thread status remains
idle throughout.
Summary
scripts/lib/resident-ensure.mjsunconditionally installs each resident role charter as a standing thread goal (thread/goal/set) in bothstartRoleThreadandresumeRoleThread. Under codex CLI >= 0.146 (where the app-server auto-starts goal turns from standing objectives), this causes resident role threads to run turns nobody assigned:idle/activeTurnId: nullwhile these goal turns are executing, so the behavior is invisible to normal supervision.Note the goal-set signature predates 0.146 in our logs — 0.146's auto-start changed the severity, not the mechanism.
Asks
thread/goal/setcalls behind an env flag (default off) as a containment patch.thread/goal/clearAPI. Today there appears to be no way to remove a standing goal from a thread; that blocks the cleaner end-state of setting a per-task terminal goal at dispatch time and clearing it on completion.Environment
Repro sketch
resident-ensure.mjs.idlethroughout.