-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Resumed threads keep stale model-visible skills after new skills are added #16607
Description
What variant of Codex are you using?
CLI / TUI (also likely affects other app-server-backed resume paths)
What issue are you seeing?
Resumed threads keep a stale model-visible skills list after new skills are added.
More specifically:
- a newly added skill can show up in the UI skill list
- explicit
$skill-nameinvocation can still work - but after
codex resume <thread-id>, the model-visible## Skillscontext remains stuck on the older snapshot - asking the resumed thread what skills are available omits the newly added skill
- implicit skill triggering does not pick up the new skill either
This makes it look like skill hot reload only updates the display/explicit invocation layer, but not the developer-context skill section that the model actually sees on resumed threads.
What steps can reproduce the bug?
One reliable repro is:
- Start a thread with some initial skill set.
- Add a new skill afterward (either a custom skill or a plugin-provided skill).
- Confirm the new skill is discoverable in a fresh session.
- Resume the old thread with
codex resume <thread-id>. - Ask the resumed thread what skills are available, or rely on implicit skill triggering.
Observed result:
- the resumed thread still reports the old skill set
- the new skill is missing from the model-visible skill inventory
- explicit
$new-skillcan still work - reinstalling/reloading the plugin does not fix the already-existing resumed thread
What is the expected behavior?
When a thread is resumed, the model-visible skill inventory should reflect the current discovered skills, not the stale set from when the thread was originally created.
At minimum, resumed threads should re-inject the ## Skills developer section whenever the available skills have changed.
Additional information
This appears to be a deeper issue than the previously closed skill hot-reload reports.
- Cant hot reload skills, skill change needs restart #12227 says live detection of new/updated skills was implemented
- Added support for live updates to skills #10478 did add watcher-driven skill updates
- however, the current behavior still appears broken specifically for resumed old threads
Relevant code path analysis:
-
Each turn does recompute skills:
core/src/codex.rsplugins_manager.plugins_for_config(&per_turn_config)skills_load_input_from_config(&per_turn_config, effective_skill_roots)skills_manager.skills_for_config(&skills_input)
-
But model-visible skills are rendered only through
build_initial_context():core/src/codex.rsaroundbuild_initial_contextturn_context.turn_skills.outcome.allowed_skills_for_implicit_invocation()render_skills_section(&implicit_skills)
-
In the normal runtime path,
record_context_updates_and_set_reference_context_item()does this:
let should_inject_full_context = reference_context_item.is_none();
let context_items = if should_inject_full_context {
self.build_initial_context(turn_context).await
} else {
self.build_settings_update_items(reference_context_item.as_ref(), turn_context).await
};So if a resumed thread reconstructs a non-None reference_context_item, it skips build_initial_context() and only emits settings diffs.
- Meanwhile
SkillsUpdateAvailablein the TUI appears to refresh the UI-side list only:tui/src/chatwidget.rs- on
EventMsg::SkillsUpdateAvailableit callsAppCommand::list_skills(..., force_reload = true) - explicit
$skillthen works because it goes throughUserInput::Skill
That would explain the observed split:
- UI skill list updates
- explicit
$skillworks - resumed thread's developer
## Skillscontext stays stale - implicit invocation does not see the new skill
This seems related to, but stronger/more specific than, #14785.