Skip to content

Preserve session imports and migrate plugin commands#31483

Draft
charlesgong-openai wants to merge 1 commit into
mainfrom
dev/charlesgong/session-import-and-command-migration
Draft

Preserve session imports and migrate plugin commands#31483
charlesgong-openai wants to merge 1 commit into
mainfrom
dev/charlesgong/session-import-and-command-migration

Conversation

@charlesgong-openai

Copy link
Copy Markdown
Contributor

Summary

  • preserve imported session identity, original timestamps, turn durations, recency, and project working directory
  • deduplicate moved or updated source sessions by their stable source session ID, including concurrent imports
  • migrate supported plugin commands into generated skills when plugins are installed or loaded
  • move reusable command-to-skill conversion from external-agent migration into codex-core-plugins

Root cause

Session imports were keyed by source path and content hash, so moving or changing an already imported source could create a duplicate. Imported rollout metadata was also generated at import time, and later rollout reconciliation could overwrite the source chronology even when SQLite had briefly received the correct timestamps.

Command migration only ran through the external-agent migration path. Installed plugins could therefore contain supported commands without exposing the corresponding generated skills.

Impact

Imported sessions remain associated with their original project and sort using their source chronology. Re-imports use the stable source session identity, and concurrent requests reserve that identity before work starts. Supported commands from installed plugins are available through the generated skill root.

Validation

  • just bazel-lock-update
  • just test -p codex-core-plugins load_plugins_includes_migrated_command_skills_with_explicit_skill_paths
  • just test -p codex-app-server external_agent_config_import_creates_session_rollouts
  • just test -p codex-rollout -p codex-thread-store -p codex-external-agent-migration -p codex-external-agent-sessions -p codex-state (369 passed)
  • just fix -p codex-app-server -p codex-core-plugins -p codex-external-agent-migration -p codex-external-agent-sessions -p codex-rollout -p codex-state -p codex-thread-store
  • just fmt

An earlier broad app-server run also exercised the affected paths, but unrelated command-exec and executor tests cannot run under the current macOS sandbox, and one plugin test observed home-level imported skills. The focused regressions and affected non-app-server crate suites above pass.

Change size

The diff exceeds the usual 800-line review guideline. About 287 lines are removed from codex-external-agent-migration and replaced by the reusable 348-line command_migration.rs module in codex-core-plugins; the other coherent workstream is session import fidelity and deduplication. These could be staged as separate PRs, but this draft intentionally keeps all requested workspace changes together.

@charlesgong-openai charlesgong-openai marked this pull request as ready for review July 8, 2026 01:10
@charlesgong-openai charlesgong-openai requested a review from a team as a code owner July 8, 2026 01:10
@charlesgong-openai charlesgong-openai marked this pull request as draft July 8, 2026 01:11

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 861790e1aa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

body
};
format!(
"---\nname: {}\ndescription: {}\n---\n\n# {name}\n\nUse this skill when the user asks to run the migrated source command `{source_name}`.\n\n## Command Template\n\n{template_body}\n",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 Badge Cap migrated command skill bodies

When a plugin command has a large Markdown body, this renders the entire command template into a generated SKILL.md; the skill injection path later reads the full skill file into model context, so installing such a plugin can create a new context item well over the required 1k/10k-token caps. Please bound, truncate, or skip oversized command bodies before writing the generated skill.

AGENTS.md reference: AGENTS.md:L91-L99

Useful? React with 👍 / 👎.

Comment on lines +971 to +973
let migrated_command_skills = migrated_command_skills_root(plugin_root);
if migrated_command_skills.is_dir() {
paths.push(migrated_command_skills);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Migrate cached plugin commands during load

For plugins that were already installed before this change, .codex-plugin/migrated-command-skills will not exist because migration only runs from PluginStore::install; this load path just skips the missing generated root, so supported commands in existing plugin caches remain invisible until the user reinstalls the plugin. Run the command migration before computing skill roots, or add a startup/load-time backfill for cached plugin roots.

Useful? React with 👍 / 👎.

Comment on lines +66 to +67
import_commands(
&plugin_root.join(PLUGIN_COMMANDS_DIR),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor declared plugin command paths

For marketplace-installed plugins that declare command files outside the literal top-level commands/ directory (for example "commands": ["./tools/review.md"] in the manifest fallback), fresh installs still complete but this scans only plugin_root/commands, so those supported commands never get generated as skills. Use the declared command paths, or include them in addition to the conventional directory.

Useful? React with 👍 / 👎.

Comment on lines +87 to +90
let Ok(Some(summary)) = summarize_session(&path) else {
continue;
};
match ledger.refresh_current_source(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don't let duplicate imports exhaust detection

When the 50 newest .jsonl files are moved or modified sessions that were already imported under the same source session ID, they all enter file_candidates before this later identity check drops them, so older unimported sessions are never considered in that detect pass. This regresses discovery for users with many recent already-imported/renamed source sessions; parse or overfetch enough candidates before applying the SESSION_IMPORT_MAX_COUNT cap.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant