From 5a7d56e6c54e7a6d86b58ab10c6610d825e008cd Mon Sep 17 00:00:00 2001 From: CI Date: Tue, 17 Mar 2026 20:24:35 +0800 Subject: [PATCH] fix(codex): include required agent metadata in TOML --- bin/install.js | 12 ++++++++++-- tests/codex-config.test.cjs | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/bin/install.js b/bin/install.js index cff9bb5f8..f7e230b66 100755 --- a/bin/install.js +++ b/bin/install.js @@ -819,14 +819,22 @@ purpose: ${toSingleLine(description)} /** * Generate a per-agent .toml config file for Codex. - * Sets sandbox_mode and developer_instructions from the agent markdown body. + * Sets required agent metadata, sandbox_mode, and developer_instructions + * from the agent markdown content. */ function generateCodexAgentToml(agentName, agentContent) { const sandboxMode = CODEX_AGENT_SANDBOX[agentName] || 'read-only'; - const { body } = extractFrontmatterAndBody(agentContent); + const { frontmatter, body } = extractFrontmatterAndBody(agentContent); + const frontmatterText = frontmatter || ''; + const resolvedName = extractFrontmatterField(frontmatterText, 'name') || agentName; + const resolvedDescription = toSingleLine( + extractFrontmatterField(frontmatterText, 'description') || `GSD agent ${resolvedName}` + ); const instructions = body.trim(); const lines = [ + `name = ${JSON.stringify(resolvedName)}`, + `description = ${JSON.stringify(resolvedDescription)}`, `sandbox_mode = "${sandboxMode}"`, // Agent prompts contain raw backslashes in regexes and shell snippets. // TOML literal multiline strings preserve them without escape parsing. diff --git a/tests/codex-config.test.cjs b/tests/codex-config.test.cjs index 4c2cd0aff..42b3bb850 100644 --- a/tests/codex-config.test.cjs +++ b/tests/codex-config.test.cjs @@ -160,6 +160,19 @@ tools: Read, Grep, Glob assert.ok(result.includes("'''"), 'has closing literal triple quotes'); }); + test('includes required name and description fields', () => { + const result = generateCodexAgentToml('gsd-executor', sampleAgent); + assert.ok(result.includes('name = "gsd-executor"'), 'has name'); + assert.ok(result.includes('description = "Executes plans"'), 'has description'); + }); + + test('falls back to generated description when frontmatter is missing fields', () => { + const minimalAgent = `You are an unknown agent.`; + const result = generateCodexAgentToml('gsd-unknown', minimalAgent); + assert.ok(result.includes('name = "gsd-unknown"'), 'falls back to agent name'); + assert.ok(result.includes('description = "GSD agent gsd-unknown"'), 'falls back to synthetic description'); + }); + test('defaults unknown agents to read-only', () => { const result = generateCodexAgentToml('gsd-unknown', sampleAgent); assert.ok(result.includes('sandbox_mode = "read-only"'), 'defaults to read-only'); @@ -485,10 +498,13 @@ describe('installCodexConfig (integration)', () => { assert.ok(fs.existsSync(path.join(agentsDir, 'gsd-plan-checker.toml')), 'plan-checker .toml exists'); const executorToml = fs.readFileSync(path.join(agentsDir, 'gsd-executor.toml'), 'utf8'); + assert.ok(executorToml.includes('name = "gsd-executor"'), 'executor has name'); + assert.ok(executorToml.includes('description = "Executes GSD plans with atomic commits, deviation handling, checkpoint protocols, and state management. Spawned by execute-phase orchestrator or execute-plan command."'), 'executor has description'); assert.ok(executorToml.includes('sandbox_mode = "workspace-write"'), 'executor is workspace-write'); assert.ok(executorToml.includes('developer_instructions'), 'has developer_instructions'); const checkerToml = fs.readFileSync(path.join(agentsDir, 'gsd-plan-checker.toml'), 'utf8'); + assert.ok(checkerToml.includes('name = "gsd-plan-checker"'), 'plan-checker has name'); assert.ok(checkerToml.includes('sandbox_mode = "read-only"'), 'plan-checker is read-only'); }); });