agile-context-engineering 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/install.js ADDED
@@ -0,0 +1,462 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const readline = require('readline');
6
+ const os = require('os');
7
+
8
+ const VERSION = '0.1.0';
9
+
10
+ // ANSI color codes
11
+ const colors = {
12
+ reset: '\x1b[0m',
13
+ bright: '\x1b[1m',
14
+ dim: '\x1b[2m',
15
+ cyan: '\x1b[36m',
16
+ green: '\x1b[32m',
17
+ yellow: '\x1b[33m',
18
+ red: '\x1b[31m',
19
+ magenta: '\x1b[35m',
20
+ };
21
+
22
+ // Runtime configurations
23
+ const RUNTIMES = {
24
+ claude: {
25
+ name: 'Claude Code',
26
+ description: "Anthropic's Claude Code CLI",
27
+ globalDir: '.claude',
28
+ commandsDir: 'commands',
29
+ agentsDir: 'agents',
30
+ supportsLocal: true,
31
+ },
32
+ opencode: {
33
+ name: 'OpenCode',
34
+ description: 'OpenCode AI coding assistant',
35
+ globalDir: '.opencode',
36
+ commandsDir: 'commands',
37
+ agentsDir: 'agents',
38
+ supportsLocal: true,
39
+ },
40
+ gemini: {
41
+ name: 'Gemini CLI',
42
+ description: "Google's Gemini CLI",
43
+ globalDir: '.gemini',
44
+ commandsDir: 'commands',
45
+ agentsDir: 'agents',
46
+ supportsLocal: true,
47
+ },
48
+ codex: {
49
+ name: 'Codex CLI',
50
+ description: "OpenAI's Codex CLI",
51
+ globalDir: '.codex',
52
+ skillsDir: 'skills',
53
+ supportsLocal: false, // Codex only supports global installation
54
+ },
55
+ };
56
+
57
+ function log(message, color = '') {
58
+ console.log(`${color}${message}${colors.reset}`);
59
+ }
60
+
61
+ function banner() {
62
+ log(`
63
+ ●●● ●●● ●●●●●
64
+ ● ● ● ●
65
+ ●●●●● ● ●●●●
66
+ ● ● ● ●
67
+ ● ● ●●● ●●●●●
68
+ `, colors.cyan);
69
+ log(` Agile Context Engineering v${VERSION}`, colors.bright);
70
+ log(` Spec-driven development for AI coding assistants\n`, colors.dim);
71
+ }
72
+
73
+ // Parse command line arguments
74
+ function parseArgs() {
75
+ const args = process.argv.slice(2);
76
+ const flags = {
77
+ claude: args.includes('--claude'),
78
+ opencode: args.includes('--opencode'),
79
+ gemini: args.includes('--gemini'),
80
+ codex: args.includes('--codex'),
81
+ all: args.includes('--all'),
82
+ global: args.includes('--global'),
83
+ local: args.includes('--local'),
84
+ help: args.includes('--help') || args.includes('-h'),
85
+ version: args.includes('--version') || args.includes('-v'),
86
+ };
87
+ return flags;
88
+ }
89
+
90
+ function showHelp() {
91
+ log(`
92
+ Usage: npx agile-context-engineering [options]
93
+
94
+ Options:
95
+ --claude Install for Claude Code only
96
+ --opencode Install for OpenCode only
97
+ --gemini Install for Gemini CLI only
98
+ --codex Install for Codex CLI only (global only)
99
+ --all Install for all supported runtimes
100
+ --global Install globally (~/.claude, ~/.gemini, etc.)
101
+ --local Install locally (.claude, .opencode, etc.)
102
+ -h, --help Show this help message
103
+ -v, --version Show version number
104
+
105
+ Examples:
106
+ npx agile-context-engineering # Interactive installation
107
+ npx agile-context-engineering --claude --local # Claude Code, local install
108
+ npx agile-context-engineering --all --global # All runtimes, global install
109
+ npx agile-context-engineering --codex # Codex CLI (always global)
110
+ `);
111
+ }
112
+
113
+ // Create readline interface for interactive prompts
114
+ function createPrompt() {
115
+ return readline.createInterface({
116
+ input: process.stdin,
117
+ output: process.stdout,
118
+ });
119
+ }
120
+
121
+ async function ask(rl, question, options) {
122
+ return new Promise((resolve) => {
123
+ log(question, colors.cyan);
124
+ options.forEach((opt, i) => {
125
+ log(` ${i + 1}. ${opt.label}`, opt.description ? colors.bright : '');
126
+ if (opt.description) {
127
+ log(` ${opt.description}`, colors.dim);
128
+ }
129
+ });
130
+ rl.question(`\n${colors.yellow}Enter choice (1-${options.length}): ${colors.reset}`, (answer) => {
131
+ const index = parseInt(answer) - 1;
132
+ if (index >= 0 && index < options.length) {
133
+ resolve(options[index].value);
134
+ } else {
135
+ log('Invalid choice, using default.', colors.red);
136
+ resolve(options[0].value);
137
+ }
138
+ });
139
+ });
140
+ }
141
+
142
+ async function askMultiple(rl, question, options) {
143
+ return new Promise((resolve) => {
144
+ log(question, colors.cyan);
145
+ options.forEach((opt, i) => {
146
+ log(` ${i + 1}. ${opt.label}`, colors.bright);
147
+ if (opt.description) {
148
+ log(` ${opt.description}`, colors.dim);
149
+ }
150
+ });
151
+ log(`\n Enter numbers separated by commas (e.g., 1,2,3) or 'all'`, colors.dim);
152
+ rl.question(`\n${colors.yellow}Your choice: ${colors.reset}`, (answer) => {
153
+ if (answer.toLowerCase() === 'all') {
154
+ resolve(options.map(o => o.value));
155
+ } else {
156
+ const indices = answer.split(',').map(s => parseInt(s.trim()) - 1);
157
+ const selected = indices
158
+ .filter(i => i >= 0 && i < options.length)
159
+ .map(i => options[i].value);
160
+ if (selected.length === 0) {
161
+ log('Invalid choice, using first option.', colors.red);
162
+ resolve([options[0].value]);
163
+ } else {
164
+ resolve(selected);
165
+ }
166
+ }
167
+ });
168
+ });
169
+ }
170
+
171
+ // Get installation paths based on runtime and scope
172
+ function getBasePath(runtime, scope) {
173
+ const home = os.homedir();
174
+ const cwd = process.cwd();
175
+ const config = RUNTIMES[runtime];
176
+
177
+ if (scope === 'local' && !config.supportsLocal) {
178
+ // Fallback to global for runtimes that don't support local
179
+ return path.join(home, config.globalDir);
180
+ }
181
+
182
+ return scope === 'global'
183
+ ? path.join(home, config.globalDir)
184
+ : path.join(cwd, config.globalDir);
185
+ }
186
+
187
+ // Copy directory recursively
188
+ function copyDir(src, dest) {
189
+ if (!fs.existsSync(dest)) {
190
+ fs.mkdirSync(dest, { recursive: true });
191
+ }
192
+
193
+ const entries = fs.readdirSync(src, { withFileTypes: true });
194
+
195
+ for (const entry of entries) {
196
+ const srcPath = path.join(src, entry.name);
197
+ const destPath = path.join(dest, entry.name);
198
+
199
+ if (entry.isDirectory()) {
200
+ copyDir(srcPath, destPath);
201
+ } else {
202
+ fs.copyFileSync(srcPath, destPath);
203
+ }
204
+ }
205
+ }
206
+
207
+ // Install for Claude Code, OpenCode, or Gemini (similar structure)
208
+ function installStandard(runtime, scope, packageDir) {
209
+ const config = RUNTIMES[runtime];
210
+ const basePath = getBasePath(runtime, scope);
211
+ const commandsPath = path.join(basePath, config.commandsDir);
212
+ const agentsPath = path.join(basePath, config.agentsDir);
213
+
214
+ // Source directories
215
+ const srcCommands = path.join(packageDir, 'commands');
216
+ const srcAgents = path.join(packageDir, 'agents');
217
+
218
+ log(`\nInstalling ACE for ${config.name}...`, colors.cyan);
219
+ log(` Target: ${basePath}`, colors.dim);
220
+
221
+ // Create directories
222
+ fs.mkdirSync(commandsPath, { recursive: true });
223
+ fs.mkdirSync(agentsPath, { recursive: true });
224
+
225
+ // Copy commands
226
+ if (fs.existsSync(srcCommands)) {
227
+ copyDir(srcCommands, commandsPath);
228
+ log(` ✓ Commands installed`, colors.green);
229
+ }
230
+
231
+ // Copy agents
232
+ if (fs.existsSync(srcAgents)) {
233
+ copyDir(srcAgents, agentsPath);
234
+ log(` ✓ Agents installed`, colors.green);
235
+ }
236
+
237
+ return basePath;
238
+ }
239
+
240
+ // Install for Codex CLI (different structure - uses skills with SKILL.md)
241
+ function installCodex(packageDir) {
242
+ const config = RUNTIMES.codex;
243
+ const home = os.homedir();
244
+ const basePath = path.join(home, config.globalDir);
245
+ const skillsPath = path.join(basePath, config.skillsDir, 'ace');
246
+
247
+ // Source directories
248
+ const srcCommands = path.join(packageDir, 'commands');
249
+ const srcAgents = path.join(packageDir, 'agents');
250
+
251
+ log(`\nInstalling ACE for ${config.name}...`, colors.cyan);
252
+ log(` Target: ${skillsPath}`, colors.dim);
253
+
254
+ // Create ace skill directory
255
+ fs.mkdirSync(skillsPath, { recursive: true });
256
+
257
+ // For Codex, we need to create a combined SKILL.md file
258
+ // or individual skill directories for each command
259
+
260
+ // Create main ACE skill file
261
+ const skillContent = generateCodexSkill(srcCommands, srcAgents);
262
+ fs.writeFileSync(path.join(skillsPath, 'SKILL.md'), skillContent);
263
+ log(` ✓ Main skill installed`, colors.green);
264
+
265
+ // Create individual command skills
266
+ if (fs.existsSync(srcCommands)) {
267
+ const commands = fs.readdirSync(srcCommands).filter(f => f.endsWith('.md'));
268
+ for (const cmd of commands) {
269
+ const cmdName = cmd.replace('.md', '').replace('ace-', '');
270
+ const cmdSkillPath = path.join(basePath, config.skillsDir, `ace-${cmdName}`);
271
+ fs.mkdirSync(cmdSkillPath, { recursive: true });
272
+ fs.copyFileSync(
273
+ path.join(srcCommands, cmd),
274
+ path.join(cmdSkillPath, 'SKILL.md')
275
+ );
276
+ }
277
+ log(` ✓ Command skills installed`, colors.green);
278
+ }
279
+
280
+ return basePath;
281
+ }
282
+
283
+ // Generate a combined skill file for Codex
284
+ function generateCodexSkill(srcCommands, srcAgents) {
285
+ let content = `# ACE - Agile Context Engineering
286
+
287
+ A spec-driven development system with Agile workflows.
288
+
289
+ ## Description
290
+
291
+ ACE (Agile Context Engineering) helps you plan and execute projects using Agile methodology with epics, features, stories, and tasks.
292
+
293
+ ## Commands
294
+
295
+ The following ACE commands are available:
296
+
297
+ - \`/ace:init\` - Initialize ACE in your project
298
+ - \`/ace:plan-project\` - Plan your project with epics and features
299
+ - \`/ace:plan-epic\` - Break an epic into features
300
+ - \`/ace:plan-feature\` - Break a feature into stories
301
+ - \`/ace:plan-story\` - Create a new user story
302
+ - \`/ace:refine-story\` - Prepare a story for execution
303
+ - \`/ace:execute-story\` - Execute a story with atomic commits
304
+ - \`/ace:verify-story\` - Verify a completed story
305
+
306
+ ## Workflow
307
+
308
+ \`\`\`
309
+ Epic → Feature → Story → Tasks
310
+ ↓ ↓ ↓ ↓
311
+ Plan → Refine → Execute → Verify
312
+ \`\`\`
313
+
314
+ ## Agile Hierarchy
315
+
316
+ - **Epic**: Large body of work (1-3 months)
317
+ - **Feature**: Deliverable functionality (1-2 sprints)
318
+ - **Story**: User-facing work item (1-3 days)
319
+ - **Task**: Atomic implementation step (30 min - 2 hours)
320
+
321
+ ## Getting Started
322
+
323
+ 1. Run \`/ace:init\` to initialize ACE in your project
324
+ 2. Run \`/ace:plan-project\` to start planning
325
+ 3. Break down work: epic → feature → story
326
+ 4. Execute and verify stories
327
+
328
+ Each command has its own skill file with detailed instructions.
329
+ `;
330
+
331
+ return content;
332
+ }
333
+
334
+ // Install commands and agents for a specific runtime
335
+ function installForRuntime(runtime, scope, packageDir) {
336
+ if (runtime === 'codex') {
337
+ return installCodex(packageDir);
338
+ }
339
+ return installStandard(runtime, scope, packageDir);
340
+ }
341
+
342
+ // Main installation logic
343
+ async function main() {
344
+ const flags = parseArgs();
345
+
346
+ if (flags.version) {
347
+ log(`ACE v${VERSION}`);
348
+ process.exit(0);
349
+ }
350
+
351
+ if (flags.help) {
352
+ banner();
353
+ showHelp();
354
+ process.exit(0);
355
+ }
356
+
357
+ banner();
358
+
359
+ // Determine package directory (where this script is located)
360
+ const packageDir = path.join(__dirname, '..');
361
+
362
+ let runtimes = [];
363
+ let scope = null;
364
+
365
+ // Check if non-interactive mode
366
+ const hasRuntimeFlag = flags.claude || flags.opencode || flags.gemini || flags.codex || flags.all;
367
+ const hasScopeFlag = flags.global || flags.local;
368
+ const isInteractive = !hasRuntimeFlag && !hasScopeFlag;
369
+
370
+ if (isInteractive) {
371
+ const rl = createPrompt();
372
+
373
+ // Ask for runtime selection (multiple choice)
374
+ runtimes = await askMultiple(rl, '\nWhich runtime(s) do you want to install ACE for?', [
375
+ { label: 'Claude Code', value: 'claude', description: "Anthropic's Claude Code CLI" },
376
+ { label: 'OpenCode', value: 'opencode', description: 'OpenCode AI coding assistant' },
377
+ { label: 'Gemini CLI', value: 'gemini', description: "Google's Gemini CLI" },
378
+ { label: 'Codex CLI', value: 'codex', description: "OpenAI's Codex CLI (global only)" },
379
+ ]);
380
+
381
+ // Check if any selected runtime doesn't support local
382
+ const hasGlobalOnly = runtimes.some(r => !RUNTIMES[r].supportsLocal);
383
+
384
+ if (hasGlobalOnly && runtimes.length === 1 && runtimes[0] === 'codex') {
385
+ // Only Codex selected, skip scope question
386
+ scope = 'global';
387
+ log(`\nNote: Codex CLI only supports global installation.`, colors.yellow);
388
+ } else {
389
+ // Ask for scope
390
+ scope = await ask(rl, '\nWhere should ACE be installed?', [
391
+ { label: 'Global', value: 'global', description: 'Install in home directory (~/.claude, ~/.gemini, etc.)' },
392
+ { label: 'Local', value: 'local', description: 'Install in current project (.claude, .opencode, etc.)' },
393
+ ]);
394
+
395
+ if (scope === 'local' && hasGlobalOnly) {
396
+ log(`\nNote: Codex CLI will be installed globally (doesn't support local).`, colors.yellow);
397
+ }
398
+ }
399
+
400
+ rl.close();
401
+ } else {
402
+ // Non-interactive mode
403
+ if (flags.all) {
404
+ runtimes = ['claude', 'opencode', 'gemini', 'codex'];
405
+ } else {
406
+ if (flags.claude) runtimes.push('claude');
407
+ if (flags.opencode) runtimes.push('opencode');
408
+ if (flags.gemini) runtimes.push('gemini');
409
+ if (flags.codex) runtimes.push('codex');
410
+ }
411
+
412
+ if (runtimes.length === 0) {
413
+ log('Error: No runtime specified. Use --claude, --opencode, --gemini, --codex, or --all', colors.red);
414
+ process.exit(1);
415
+ }
416
+
417
+ if (flags.global && flags.local) {
418
+ log('Error: Cannot specify both --global and --local', colors.red);
419
+ process.exit(1);
420
+ }
421
+
422
+ scope = flags.local ? 'local' : 'global';
423
+ }
424
+
425
+ // Perform installation
426
+ const installedPaths = [];
427
+
428
+ for (const runtime of runtimes) {
429
+ const installedPath = installForRuntime(runtime, scope, packageDir);
430
+ installedPaths.push({ runtime, name: RUNTIMES[runtime].name, path: installedPath });
431
+ }
432
+
433
+ // Show success message
434
+ log(`\n${'═'.repeat(50)}`, colors.green);
435
+ log(` ACE installed successfully!`, colors.green + colors.bright);
436
+ log(`${'═'.repeat(50)}`, colors.green);
437
+
438
+ log(`\nInstalled locations:`, colors.cyan);
439
+ for (const { name, path: p } of installedPaths) {
440
+ log(` ${name}: ${p}`, colors.dim);
441
+ }
442
+
443
+ log(`\nAvailable commands:`, colors.cyan);
444
+ log(` /ace:init Initialize ACE in your project`, colors.dim);
445
+ log(` /ace:plan-project Plan your project with epics and features`, colors.dim);
446
+ log(` /ace:plan-epic Plan an epic with features and stories`, colors.dim);
447
+ log(` /ace:plan-feature Plan a feature with stories`, colors.dim);
448
+ log(` /ace:plan-story Plan a story with tasks`, colors.dim);
449
+ log(` /ace:refine-story Refine a story for execution`, colors.dim);
450
+ log(` /ace:execute-story Execute a story`, colors.dim);
451
+ log(` /ace:verify-story Verify a completed story`, colors.dim);
452
+
453
+ log(`\nGet started:`, colors.cyan);
454
+ log(` 1. Navigate to your project directory`, colors.dim);
455
+ log(` 2. Run /ace:init to initialize ACE`, colors.dim);
456
+ log(` 3. Run /ace:plan-project to start planning\n`, colors.dim);
457
+ }
458
+
459
+ main().catch((err) => {
460
+ log(`Error: ${err.message}`, colors.red);
461
+ process.exit(1);
462
+ });
@@ -0,0 +1,114 @@
1
+ # /ace:execute-story - Execute a Story
2
+
3
+ Execute a refined story by completing all tasks with atomic commits.
4
+
5
+ ## Usage
6
+
7
+ ```
8
+ /ace:execute-story <story-id>
9
+ /ace:execute-story E1-F1-S1
10
+ ```
11
+
12
+ ### Arguments
13
+
14
+ - `story-id` - The story identifier to execute
15
+
16
+ ## Behavior
17
+
18
+ This command executes a story by:
19
+ - Working through each task in sequence
20
+ - Making atomic commits per task
21
+ - Updating task status as work progresses
22
+ - Running tests after each significant change
23
+
24
+ ## Instructions for Claude
25
+
26
+ <ace-execute-story>
27
+
28
+ ### Prerequisites
29
+
30
+ 1. Verify ACE is initialized
31
+ 2. Verify story is refined (has tasks)
32
+ 3. Check for blockers
33
+ 4. Ensure clean git state
34
+
35
+ ### Execution Process
36
+
37
+ 1. **Pre-flight Check**
38
+ ```bash
39
+ git status # Ensure clean working tree
40
+ ```
41
+
42
+ 2. **For Each Task:**
43
+
44
+ a. **Read task details**
45
+ - Understand what to do
46
+ - Know the done criteria
47
+
48
+ b. **Implement the task**
49
+ - Make focused changes
50
+ - Follow existing code patterns
51
+ - Write/update tests as needed
52
+
53
+ c. **Verify done criteria**
54
+ - Run relevant tests
55
+ - Check acceptance criteria
56
+
57
+ d. **Commit atomically**
58
+ ```bash
59
+ git add <specific-files>
60
+ git commit -m "feat(E1-F1-S1-T1): <task description>"
61
+ ```
62
+
63
+ e. **Update task status**
64
+ - Mark task as completed in story file
65
+
66
+ 3. **After All Tasks:**
67
+ - Run full test suite
68
+ - Update story status to "Done"
69
+ - Update STATE.md
70
+
71
+ ### Commit Message Format
72
+
73
+ ```
74
+ <type>(<story-task>): <description>
75
+
76
+ [optional body]
77
+
78
+ Co-Authored-By: Claude <noreply@anthropic.com>
79
+ ```
80
+
81
+ Types:
82
+ - `feat` - New feature
83
+ - `fix` - Bug fix
84
+ - `refactor` - Code refactoring
85
+ - `test` - Adding tests
86
+ - `docs` - Documentation
87
+ - `chore` - Maintenance
88
+
89
+ ### Error Handling
90
+
91
+ If a task fails:
92
+ 1. Document the issue
93
+ 2. Ask user for guidance
94
+ 3. Do NOT proceed to next task until resolved
95
+ 4. Consider creating a blocker in STATE.md
96
+
97
+ ### Output
98
+
99
+ ```
100
+ ✓ Story E1-F1-S1 executed!
101
+
102
+ Completed Tasks:
103
+ ✓ T1: <description> (commit abc123)
104
+ ✓ T2: <description> (commit def456)
105
+ ✓ T3: <description> (commit ghi789)
106
+
107
+ Tests: All passing
108
+
109
+ Next steps:
110
+ - Run /ace:verify-story E1-F1-S1
111
+ - Or continue with next story
112
+ ```
113
+
114
+ </ace-execute-story>