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:
@@ -12,6 +12,10 @@ const os = require('node:os');
|
||||
const { spawnSync } = require('node:child_process');
|
||||
const assert = require('node:assert/strict');
|
||||
|
||||
const {
|
||||
resolveRuntimeArtifactLayout,
|
||||
} = require('../../gsd-core/bin/lib/runtime-artifact-layout.cjs');
|
||||
|
||||
const INSTALL_SCRIPT = path.join(__dirname, '..', '..', 'bin', 'install.js');
|
||||
const MANIFEST_NAME = 'gsd-file-manifest.json';
|
||||
|
||||
@@ -177,9 +181,27 @@ function manifestAgentCount(manifest) {
|
||||
return Object.keys(manifest.files).filter((k) => k.startsWith('agents/')).length;
|
||||
}
|
||||
|
||||
function collectSkillBasenamesOnDisk(configDir) {
|
||||
/**
|
||||
* Collect gsd-* skill/command basenames actually present on disk under configDir.
|
||||
*
|
||||
* @param {string} configDir
|
||||
* @param {string} [runtime] - when provided, the skills-kind destination is
|
||||
* resolved via resolveRuntimeArtifactLayout so a skills-kind `home` override
|
||||
* (Codex only, ADR-1239 upgrade 3 / #2088: skills -> $HOME/.agents/skills
|
||||
* instead of configDir/skills) is honored. Omitted callers keep the prior
|
||||
* configDir/skills default.
|
||||
* @param {string} [scope='global']
|
||||
*/
|
||||
function collectSkillBasenamesOnDisk(configDir, runtime, scope = 'global') {
|
||||
const out = new Set();
|
||||
const skillsDir = path.join(configDir, 'skills');
|
||||
let skillsDir = path.join(configDir, 'skills');
|
||||
if (runtime) {
|
||||
try {
|
||||
const layout = resolveRuntimeArtifactLayout(runtime, configDir, scope);
|
||||
const skillsKind = layout.kinds.find((k) => k.kind === 'skills');
|
||||
if (skillsKind) skillsDir = path.join(skillsKind.home || configDir, skillsKind.destSubpath);
|
||||
} catch { /* fall back to configDir/skills */ }
|
||||
}
|
||||
if (fs.existsSync(skillsDir)) {
|
||||
for (const entry of fs.readdirSync(skillsDir, { withFileTypes: true })) {
|
||||
if (entry.isDirectory() && entry.name.startsWith('gsd-')) {
|
||||
|
||||
Reference in New Issue
Block a user