/**
 * install/transforms/codex.mjs — Codex transform.
 *
 * Codex quirks:
 *   - frontmatter is whitelisted to `KEEP = {name, description}` (Codex
 *     validates strictly against its `allowed_properties` set and rejects
 *     unknown keys; the whitelist is drift-proof against new framework
 *     frontmatter keys).
 *   - body is wrapped in <codex_agent_role>…</codex_agent_role>.
 *   - slash-command refs `/apt:foo` rewritten to `/apt-foo` (Codex command
 *     names disallow `:`).
 *   - output: skills/<folder>/SKILL.md (the documented Codex discovery
 *     surface per https://developers.openai.com/codex/skills — resolved
 *     against installRoot `.agents` to land at `.agents/skills/<folder>/SKILL.md`).
 *     Markdown agents are NOT a Codex surface (custom-agents are TOML
 *     under `.codex/agents/`); only skills are emitted.
 *   - agent inlining: Codex has no markdown agent-spawn surface, so a skill
 *     declaring `spawns_agent: true` + `agent_name: X` would, on Claude, spawn
 *     the X agent (whose prompt lives in agents/X.md). On Codex that file is
 *     never installed and the spawn directive is stripped by the whitelist —
 *     leaving the skill referencing a non-existent agent. To keep Codex at
 *     parity, the referenced agent's body is appended inline to the skill body
 *     so the model has the full methodology even without a spawn primitive.
 */
import { basename, dirname } from 'node:path';
import { parseFrontmatter, rewriteCommandRefs, serializeFrontmatter, substituteVersion, } from './_shared.mjs';
// Codex's `allowed_properties` set (see
// ~/.codex/skills/.system/skill-creator/scripts/quick_validate.py:40):
// {"name", "description", "license", "allowed-tools", "metadata"}.
// We use the minimum viable whitelist {name, description} so adding new
// framework frontmatter keys (a routine occurrence) doesn't break Codex
// validation — only the 2 keys Codex actually consumes are emitted.
const KEEP = ['name', 'description'];
/**
 * @param {import('../pipeline.mjs').TransformInput} input
 * @returns {import('../pipeline.mjs').TransformOutput[]}
 */
export function transform({ canonicalContent, canonicalRelPath, version, fileType, agentContentByName = {}, }) {
    const subbed = substituteVersion(canonicalContent, version);
    const parsed = parseFrontmatter(subbed);
    let payload;
    if (parsed.hasFrontmatter && parsed.fm) {
        // Read the spawn directive BEFORE the whitelist strips it. On Codex
        // there's no agent-spawn surface, so we inline the agent body instead.
        const spawnsAgent = parsed.fm.spawns_agent === true;
        const agentName = typeof parsed.fm.agent_name === 'string' && parsed.fm.agent_name.length > 0
            ? parsed.fm.agent_name
            : null;
        // Whitelist filter: drop every frontmatter key NOT in KEEP.
        for (const k of Object.keys(parsed.fm)) {
            if (!KEEP.includes(k))
                delete parsed.fm[k];
        }
        let body = parsed.body;
        if (spawnsAgent && agentName && agentContentByName[agentName]) {
            body = `${body}\n\n${inlineAgentSection(agentName, agentContentByName[agentName], version)}`;
        }
        const wrappedBody = `<codex_agent_role>\n${body}\n</codex_agent_role>\n`;
        payload = serializeFrontmatter({ ...parsed, body: wrappedBody });
    }
    else {
        payload = `<codex_agent_role>\n${subbed}\n</codex_agent_role>\n`;
    }
    payload = rewriteCommandRefs(payload, '/apt:', '/apt-');
    if (fileType === 'skill') {
        const folder = basename(dirname(canonicalRelPath));
        // Codex's documented skill discovery surface is `.agents/skills/<folder>/SKILL.md`
        // (one folder per skill, canonical SKILL.md filename).
        return [{ outputPath: `skills/${folder}/SKILL.md`, content: payload }];
    }
    // Markdown agents are not a Codex surface. Codex custom-agents are TOML
    // under `.codex/agents/`; emitting markdown there would just create
    // another dead surface. Drop the agent branch entirely.
    return [];
}
/**
 * Build the inlined-agent section appended to a Codex skill body. Strips the
 * agent file's own frontmatter (Codex skills carry a single frontmatter block)
 * and version-substitutes the body. The fenced header makes it unambiguous to
 * the model that this is the methodology it should execute directly — there is
 * no separate agent to spawn on Codex.
 *
 * @param {string} agentName
 * @param {string} agentContent  raw canonical agent file (with frontmatter + {{APT_VERSION}})
 * @param {string} version
 * @returns {string}
 */
function inlineAgentSection(agentName, agentContent, version) {
    const agentBody = parseFrontmatter(substituteVersion(agentContent, version)).body.trim();
    return [
        `## Inlined agent: ${agentName}`,
        '',
        `Codex has no separate agent-spawn surface. Where this skill says to spawn`,
        `the \`${agentName}\` agent, execute the methodology below directly — you ARE`,
        `that agent for this task.`,
        '',
        agentBody,
    ].join('\n');
}
//# sourceMappingURL=codex.mjs.map