feat(#2088): migrate Codex onto the Embeddable Orchestration System (ADR-1239)

Drive Codex install/uninstall through the descriptor-driven Host-Integration
Interface (declarative embedding adapter → engine surface dispatch) and fold
every positive `runtime === 'codex'` / `isCodex` projection into descriptor-driven
`runtime.hostBehaviors`. Install/uninstall output stays byte-parity-gated
(tests/fixtures/golden-install-parity/codex.json); no other runtime changes.

Three Context7-verified upgrades, each with a test on the user-reachable surface:
- Skill root → canonical $HOME/.agents/skills via a skills-kind `home` override,
  with pre-move migration cleanup (stale ~/.codex/skills/gsd-* removed on install
  and uninstall; user content preserved). Fixes getGlobalSkillsBase, writeManifest,
  and the skill-manifest inventory to honor the override so --skills-root /
  sync-skills / the manifest report the real location.
- Six new hooks.json lifecycle events (PreToolUse, PermissionRequest, PreCompact,
  PostCompact, SubagentStop, UserPromptSubmit) shared by install + uninstall;
  extendedHookEvents reconciled [] -> the schema-valid wired subset.
- Explicit `[agents] max_depth = 1` in the managed config.toml block, pinning the
  negotiated dispatch.maxDepth:1 axis. validateCodexConfigSchema now permits a
  known-scalar-only bare `[agents]` AgentsToml table (still rejects [[agents]] and
  unknown-key break-forms, #2760); mergeCodexConfig preserves the user's own
  AgentsToml scalars (max_threads etc.) instead of dropping them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-07-08 21:42:11 -04:00
parent e5a1d7f5c4
commit 6e773d97df
24 changed files with 1252 additions and 211 deletions

View File

@@ -9957,7 +9957,9 @@ function readWorkflow() {
describe('install.js --skills-root', () => {
const CASES = [
{ runtime: 'claude', expected: path.join(os.homedir(), '.claude', 'skills') },
{ runtime: 'codex', expected: path.join(os.homedir(), '.codex', 'skills') },
// #2088 (ADR-1239 upgrade 3): Codex skills resolve to the canonical
// $HOME/.agents/skills root (skills-kind home override), not $CODEX_HOME/skills.
{ runtime: 'codex', expected: path.join(os.homedir(), '.agents', 'skills') },
{ runtime: 'copilot', expected: path.join(os.homedir(), '.copilot', 'skills') },
{ runtime: 'cursor', expected: path.join(os.homedir(), '.cursor', 'skills') },
{ runtime: 'trae', expected: path.join(os.homedir(), '.trae', 'skills') },
@@ -10182,10 +10184,15 @@ const INSTALL = path.join(__dirname, '..', 'bin', 'install.js');
*/
function installAndRead(runtime) {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), `gsd-inst-${runtime}-`));
// Sandbox HOME/USERPROFILE to `dir`: Codex's skills-kind `home: ".agents"`
// override (ADR-1239 upgrade 3, #2088) resolves via os.homedir(), so an
// unsandboxed real install here would write a full (non-minimal) gsd-* skill
// set into the developer/CI machine's real $HOME/.agents/skills. Harmless
// no-op for cursor/claude, which have no skills-kind home override.
const res = spawnSync(
process.execPath,
[INSTALL, `--${runtime}`, '--global', '--config-dir', dir],
{ encoding: 'utf8', timeout: 120000 },
{ encoding: 'utf8', timeout: 120000, env: { ...process.env, HOME: dir, USERPROFILE: dir } },
);
assert.strictEqual(res.status, 0, `install --${runtime} failed: ${res.stderr || res.stdout}`);
const wf = path.join(dir, 'gsd-core', 'workflows', 'execute-phase.md');