diff --git a/commands/egc-plan.toml b/commands/egc-plan.toml index 641f0a5..6ee880e 100644 --- a/commands/egc-plan.toml +++ b/commands/egc-plan.toml @@ -2,7 +2,9 @@ description = "Restate requirements, assess risks, and create step-by-step imple prompt = ''' # Plan Command -This command invokes the **planner** agent to create a comprehensive implementation plan before writing any code. +This command creates a comprehensive implementation plan before writing any code. + +Run inline by default. Do not delegate to the `@planner` subagent (or any other) by default. This keeps `/egc-plan` usable when the runtime ships commands without the matching agent files. ## What This Command Does @@ -22,7 +24,7 @@ Use `/egc-plan` when: ## How It Works -The planner agent will: +The assistant will: 1. **Analyze the request** and restate requirements in clear terms 2. **Break down into phases** with specific, actionable steps @@ -36,7 +38,7 @@ The planner agent will: ``` User: /egc-plan I need to add real-time notifications when markets resolve -Agent (planner): +Assistant: # Implementation Plan: Real-Time Market Resolution Notifications ## Requirements Restatement @@ -91,7 +93,7 @@ Agent (planner): ## Important Notes -**CRITICAL**: The planner agent will **NOT** write any code until you explicitly confirm the plan with "yes" or "proceed" or similar affirmative response. +**CRITICAL**: This command will **NOT** write any code until you explicitly confirm the plan with "yes" or "proceed" or similar affirmative response. If you want changes, respond with: - "modify: [your changes]" @@ -105,7 +107,9 @@ After planning: - Use `/build-and-fix` if build errors occur - Use `/egc-code-review` to review completed implementation -## Related Agents +## Optional Planner Agent + +EGC ships a `planner` agent (`agents/planner.md`) that can produce richer plans for larger features. Use it only when the local runtime already exposes that subagent and the user explicitly asks you to delegate planning — invoke as `@planner`. -This command invokes the `@planner` agent. +If the `@planner` subagent is unavailable (e.g. agents were not installed, or the runtime cannot resolve the name), continue planning inline instead of surfacing an "Agent type 'planner' not found" error. ''' diff --git a/tests/commands/plan-command.test.js b/tests/commands/plan-command.test.js new file mode 100644 index 0000000..902e5e6 --- /dev/null +++ b/tests/commands/plan-command.test.js @@ -0,0 +1,95 @@ +/** + * Tests for commands/egc-plan.toml prompt contract. + * + * Adapted from ECC's tests/commands/plan-command.test.js (commit 17aafc4). + * Verifies that /egc-plan runs inline by default and does not require + * the planner agent to be installed. + */ + +'use strict'; + +const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); + +const repoRoot = path.resolve(__dirname, '..', '..'); +const planCommandPath = path.join(repoRoot, 'commands', 'egc-plan.toml'); + +let passed = 0; +let failed = 0; + +function test(name, fn) { + try { + fn(); + console.log(` ✓ ${name}`); + passed += 1; + } catch (err) { + console.log(` ✗ ${name}`); + console.log(` Error: ${err.message}`); + failed += 1; + } +} + +function readPlanCommand() { + return fs.readFileSync(planCommandPath, 'utf8'); +} + +console.log('\n=== Testing /egc-plan command prompt ===\n'); + +test('/egc-plan runs inline by default without requiring planner agent', () => { + const source = readPlanCommand(); + + assert.ok( + source.includes('Do not delegate to the `@planner` subagent'), + 'Expected /egc-plan to avoid default subagent delegation', + ); + assert.ok( + source.includes('If the `@planner` subagent is unavailable'), + 'Expected /egc-plan to define a planner-unavailable fallback', + ); + assert.ok( + !source.includes('This command invokes the **planner** agent'), + 'Expected /egc-plan not to claim unconditional planner invocation', + ); + assert.ok( + !source.includes('The planner agent will:'), + 'Expected /egc-plan to describe inline behavior, not mandatory agent behavior', + ); + assert.ok( + !source.includes('Agent (planner):'), + 'Expected /egc-plan examples not to imply the planner agent is required', + ); +}); + +test('/egc-plan still documents the optional planner agent for manual use', () => { + const source = readPlanCommand(); + + assert.ok( + source.includes('Optional Planner Agent'), + 'Expected /egc-plan to mention the optional planner agent section', + ); + assert.ok( + source.includes('agents/planner.md'), + 'Expected /egc-plan to reference the planner agent source file', + ); +}); + +test('/egc-plan preserves the WAIT-for-CONFIRM contract', () => { + const source = readPlanCommand(); + + assert.ok( + /\*\*CRITICAL\*\*:.*\*\*NOT\*\* write any code until you explicitly confirm/.test(source), + 'Expected /egc-plan to retain the explicit-confirm guard', + ); + assert.ok( + source.includes('WAITING FOR CONFIRMATION'), + 'Expected /egc-plan to retain the WAITING FOR CONFIRMATION marker', + ); +}); + +console.log('\n=== Test Results ==='); +console.log(`Passed: ${passed}`); +console.log(`Failed: ${failed}`); +console.log(`Total: ${passed + failed}\n`); + +process.exit(failed === 0 ? 0 : 1); diff --git a/tests/run-all.js b/tests/run-all.js index c904229..ebb5c84 100644 --- a/tests/run-all.js +++ b/tests/run-all.js @@ -21,6 +21,7 @@ const testFiles = [ 'lib/upstream-drift.test.js', 'hooks/hooks.test.js', 'hooks/block-no-verify.test.js', + 'commands/plan-command.test.js', 'ci/validate-workflow-security.test.js', 'ci/validate-upstream-sync.test.js', 'lint/validators.test.js'