Explicit-only skill activation is lost after compaction in long-running tasks
What version of Codex CLI is running?
codex-cli 0.144.0
Also visible from the current skills extension and compaction/context reconstruction paths on main.
What subscription do you have?
Not subscription-specific. Observed on Pro 20x.
Which model were you using?
Observed with GPT-5.5 and GPT-5.6-style model configurations.
This appears to be host/runtime state handling rather than model-specific behavior.
What platform is your computer?
Linux 6.17.0-35-generic x86_64
What terminal emulator and version are you using (if applicable)?
Ghostty (TERM=xterm-ghostty), no tmux/zellij.
Codex doctor report
Not applicable. The problem is visible in the skill activation/context reconstruction lifecycle.
What issue are you seeing?
An explicitly selected skill is injected for the current turn, but its activation is not durable across compaction/context reconstruction in a long-running task.
This is most visible for explicit-only skills whose agents/openai.yaml contains:
policy:
allow_implicit_invocation: false
The user explicitly selects the skill through $<skill-name> and Codex initially reads and follows its SKILL.md. As the task runs through multiple compaction/context-reconstruction rounds, the selected workflow is reduced to whatever the compaction summaries happen to preserve instead of being rehydrated as active host-owned state.
Compaction can preserve a short instruction verbatim, so the failure is not reliably demonstrated by a one-line marker. It becomes reproducible with a substantive multi-step workflow whose skill promotes the main agent into a supervisor/validator role:
- initially, the parent sequences phases, delegates bounded implementation, and validates child work;
- after later compactions, the promotion/role contract disappears;
- the parent silently becomes the executor and performs implementation itself;
- it may say it no longer has an explicit delegation instruction or that the explicit-only skill is unavailable/not installed.
Because explicit-only skills are intentionally omitted from the implicit Available skills catalog, the model cannot recover the selected workflow through implicit routing.
The installed/configured state and the selected/active state are being conflated. A skill can remain installed and resolvable by the host while its explicit activation receipt disappears from model context.
This is especially disruptive for skills that promote the main session into a durable workflow role, such as a supervisor, reviewer, audit loop, or other multi-turn process. Repeating the skill token manually after every compaction is not reliable for autonomous or long-running work.
What steps can reproduce the bug?
- Create an explicit-only supervisor skill:
``yaml``
# agents/openai.yaml
policy:
allow_implicit_invocation: false
- Give its
SKILL.mda substantive workflow rather than a short marker. For example:
```markdown
# Supervisor workflow
The main agent is promoted to supervisor and validator for the duration of
the selected task.
- Read the complete referenced plan before starting.
- Preserve its phase order and completion gates.
- Do not implement production changes in the parent.
- Delegate each bounded implementation phase to a coder with a disjoint
write scope.
- Validate each coder's diff and tests before advancing.
- Use separate reviewers for cross-phase and final validation.
- Keep this supervisor role until every phase and final gate is complete.
```
- Create a realistic plan document with at least four implementation phases, for example (pseudo-plan):
```markdown
# Plan
- Refactor the data model and migration.
- Update service/business logic.
- Update API contracts and clients.
- Add integration tests and compatibility coverage.
- Run a separate final review and fix validated findings.
```
Each phase should contain enough concrete work, validation, and tool output to make the session cross several automatic compaction boundaries.
- Start the task by explicitly selecting the skill:
``text``
$supervisor-test execute docs/plan.md through completion
- Confirm the initial behavior:
- Codex reads the complete
SKILL.mdand plan; - the parent announces/uses the supervisor role;
- implementation is delegated;
- the parent validates child work rather than editing production code itself.
- Allow the workflow to continue through several phases and multiple automatic compactions/context reconstructions.
- Observe behavior after a later compaction:
- the parent starts implementing the next phase directly;
- it no longer applies the skill's delegation and validation gates;
- it does not reread the selected
SKILL.md; - when challenged, it may say there is no current explicit instruction to remain a supervisor/use subagents, or may assume the explicit-only skill is unavailable.
- Repeat
$supervisor-test. - Observe that Codex reloads the still-installed skill, recognizes the lost promotion, and resumes the supervisor workflow.
The important signal is the role transition from supervisor/validator to executor after context reconstruction, not whether a short phrase survives in a summary.
What is the expected behavior?
Explicit skill selection should create a host-owned activation receipt that survives context reconstruction for the scope of the active task.
At minimum:
- compaction during the same logical task must not remove a selected skill;
- the complete selected
SKILL.mdmust be rehydrated after compaction before work continues; - a supervisor/reviewer/other promoted role must remain active until its defined scope ends;
- explicit-only skills must not be treated as missing merely because they are absent from the implicit catalog;
- activation should be removed only at a defined scope boundary or by an explicit deactivate action.
A useful scope model would be:
- normal implicit routing: turn-scoped, as today;
- explicit
$skillselection: active-task or session-scoped; - skill selected by an active
/goal: goal-scoped; - explicit
/skill drop <name>or equivalent: deactivate it.
The exact UX can vary, but compaction should not be an accidental skill deactivation or role-demotion boundary. Summary quality should not determine whether an explicit workflow remains active.
Additional information
Current source shape:
codex-rs/ext/skills/src/extension.rsTurnInputContributor::contributecallscollect_explicit_skill_mentions(&input.user_input, &catalog);- the selected skill body is injected into that turn;
- selection is written to
SkillsTurnState. codex-rs/ext/skills/src/state.rsSkillsThreadStatestores configuration and catalog caches;- it does not store active explicit skill selections.
codex-rs/core-skills/src/render.rs- the model-visible instructions currently say:
Do not carry skills across turns unless re-mentioned. - compaction/context reconstruction reinjects general initial context, but there is no durable selected-skill state to rehydrate.
The model instruction is reasonable for implicit routing. It is too broad for an explicit user selection attached to a long-running task, and it makes host state loss look like intended behavior.
Related but distinct issues:
- #32170:
/goalrecognizes$skilltokens but persists them as inert objective text. - #23454: explicit
$skillinvocation can fail immediately when an explicit-only skill is absent from the implicit list. - #19695: confirms
$<skill-name>is the intended reliable explicit invocation contract. - #22644: active
/goalcontract can be lost after compaction. - #31659: general
/goaldrift after auto-compaction. - #29356: generic operational continuity loss after compaction; this report is specifically about host-known explicit skill activation.
- #30578: proposes persistent installed capability state, but not persistent selected/active skill state.
This report is narrower than generic compaction summary loss: the host already knows which structured skill was selected and can preserve that fact independently of model summarization.
Short implementation plan
- Add an active-skill set to thread/task state with at least:
``text``
name
authority/source
package/path
content/config fingerprint
activation scope
activation source
- Record explicit structured or
$skillselections in that state after successful resolution. - Re-read/reinject active skill instructions when a new context epoch is created by compaction or resume.
- Keep implicit matches turn-scoped; do not make every automatically matched skill durable.
- Invalidate/re-resolve an active entry when its source/config fingerprint changes, and emit a visible warning if it can no longer be loaded.
- Add deterministic prompt-assembly regression coverage:
- select an explicit-only supervisor skill with a multi-step workflow;
- retain its activation in thread/task state;
- force multiple context replacement/compaction epochs;
- assert that each rebuilt context contains a fresh
SkillInstructionsfragment for the selected skill; - assert that the implicit inventory still excludes the explicit-only skill;
- assert that deactivation/scope completion removes it deterministically.
The regression test should verify host-owned activation and reinjection directly. It should not depend on whether a compaction model happens to preserve a short instruction in generated summary text.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗