(skill: string, testName: string, featureName: string)
| 803 | }); |
| 804 | |
| 805 | async function checkCodexOffering(skill: string, testName: string, featureName: string) { |
| 806 | const result = await runSkillTest({ |
| 807 | prompt: `Read ${skill}/SKILL.md. Search for ALL sections related to "codex", "outside voice", or "second opinion". |
| 808 | |
| 809 | Summarize the Codex/${featureName} integration — answer these specific questions: |
| 810 | 1. How is Codex availability checked? (what exact bash command?) |
| 811 | 2. How is the user prompted? (via AskUserQuestion? what are the options?) |
| 812 | 3. What happens when Codex is NOT available? (fallback to subagent? skip entirely?) |
| 813 | 4. Is this step blocking (gates the workflow) or optional (can be skipped)? |
| 814 | 5. What prompt/context is sent to Codex? |
| 815 | |
| 816 | Write your summary to ${testDir}/${testName}-summary.md`, |
| 817 | workingDirectory: testDir, |
| 818 | maxTurns: 8, |
| 819 | timeout: 120_000, |
| 820 | testName, |
| 821 | runId, |
| 822 | }); |
| 823 | |
| 824 | logCost(`/${skill} codex offering`, result); |
| 825 | recordE2E(evalCollector, `/${testName}`, 'Codex Offering E2E', result); |
| 826 | expect(result.exitReason).toBe('success'); |
| 827 | |
| 828 | const summaryPath = path.join(testDir, `${testName}-summary.md`); |
| 829 | expect(fs.existsSync(summaryPath)).toBe(true); |
| 830 | |
| 831 | const summary = fs.readFileSync(summaryPath, 'utf-8').toLowerCase(); |
| 832 | // All skills should have codex availability check (command -v per #1197) |
| 833 | expect(summary).toMatch(/command -v codex/); |
| 834 | // All skills should have fallback behavior |
| 835 | expect(summary).toMatch(/fallback|subagent|unavailable|not available|skip/); |
| 836 | // All skills should show it's optional/non-blocking |
| 837 | expect(summary).toMatch(/optional|non.?blocking|skip|not.*required/); |
| 838 | |
| 839 | console.log(`${skill}: Codex offering verified`); |
| 840 | } |
| 841 | |
| 842 | testConcurrentIfSelected('codex-offered-office-hours', async () => { |
| 843 | await checkCodexOffering('office-hours', 'codex-offered-office-hours', 'second opinion'); |
no test coverage detected