()
| 84 | stdio: 'pipe', |
| 85 | encoding: 'utf8', |
| 86 | timeout: 20000, |
| 87 | }); |
| 88 | |
| 89 | const report = checkCodexReadiness({ projectRoot: tmp, write: true }); |
| 90 | assert(report.pass, JSON.stringify(report.checks.filter((check) => !check.pass), null, 2)); |
| 91 | assert(fs.existsSync(path.join(tmp, '.planning', 'verification', 'codex-readiness.json'))); |
| 92 | const manifestText = fs.readFileSync(path.join(tmp, '.codex-plugin', 'plugin.json'), 'utf8'); |
| 93 | assert.doesNotThrow(() => JSON.parse(manifestText), 'target-project plugin manifest must be strict JSON'); |
| 94 | assert(manifestText.includes('./.agents/skills/'), 'target-project plugin manifest should point at generated skills'); |
| 95 | const manifest = JSON.parse(manifestText); |
| 96 | assertPluginAssetsExist(tmp, manifest, ['./.agents/assets/terminal-demo.svg']); |
| 97 | const projectedManifest = JSON.parse(fs.readFileSync( |
| 98 | path.join(tmp, '.agents', '.codex-plugin', 'plugin.json'), |
| 99 | 'utf8' |
| 100 | )); |
| 101 | assertPluginAssetsExist(path.join(tmp, '.agents'), projectedManifest, ['./assets/terminal-demo.svg']); |
| 102 | fs.rmSync(path.join(tmp, '.agents', 'assets', 'icon.svg')); |
| 103 | const missingAssetReport = checkCodexReadiness({ projectRoot: tmp }); |
| 104 | assert(!missingAssetReport.pass, 'readiness must fail when a declared plugin asset is missing'); |
| 105 | assert(missingAssetReport.checks.some((check) => check.id.startsWith('plugin-asset:') && !check.pass), |
| 106 | 'readiness must identify the missing plugin asset'); |
| 107 | } finally { |
| 108 | fs.rmSync(tmp, { recursive: true, force: true }); |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | function testPluginMarketplaceSmoke() { |
| 113 | const tmp = tempProject('citadel-plugin-smoke-'); |
| 114 | try { |
| 115 | fs.writeFileSync(path.join(tmp, 'AGENTS.md'), '# Test\n\n## Review guidelines\n\n- Focus on P0/P1 issues.\n', 'utf8'); |
| 116 | execFileSync(process.execPath, [path.join(CITADEL_ROOT, 'scripts', 'codex-compat.js'), tmp], { |
| 117 | cwd: CITADEL_ROOT, |
| 118 | stdio: 'pipe', |
| 119 | encoding: 'utf8', |
| 120 | timeout: 20000, |
| 121 | }); |
| 122 | |
| 123 | const report = createPluginMarketplace({ projectRoot: tmp, write: true }); |
| 124 | assert(report.pass, JSON.stringify(report.checks, null, 2)); |
| 125 | assert(fs.existsSync(path.join(tmp, '.agents', 'plugins', 'marketplace.json'))); |
| 126 | const generatedManifest = JSON.parse(fs.readFileSync(path.join(tmp, '.agents', '.codex-plugin', 'plugin.json'), 'utf8')); |
| 127 | assert.equal(report.marketplace.plugins[0].version, generatedManifest.version); |
| 128 | assert.equal(report.marketplace.plugins[0].description, generatedManifest.description); |
| 129 | assert.equal(report.marketplace.plugins[0].repository, generatedManifest.repository); |
| 130 | assertPluginAssetsExist(path.join(tmp, '.agents'), generatedManifest, ['./assets/terminal-demo.svg']); |
| 131 | assert(report.codexCliCommands.some((command) => command.includes('codex plugin marketplace add'))); |
| 132 | |
| 133 | const smoke = execFileSync(process.execPath, [ |
| 134 | path.join(CITADEL_ROOT, 'scripts', 'codex-plugin-smoke.js'), |
no test coverage detected