@mark-gozner/aigile-method 1.0.5 → 1.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.
Files changed (2) hide show
  1. package/package.json +6 -4
  2. package/tools/cli.js +447 -91
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mark-gozner/aigile-method",
3
- "version": "1.0.5",
4
- "description": "AIgile Development Method by Mark Gozner - AI-powered development with custom agents, handoffs, and subagent delegation",
3
+ "version": "1.1.0",
4
+ "description": "AIgile Development Method by Mark Gozner - AI-powered development with custom agents (GitHub Copilot & Google Antigravity), handoffs, and delegation",
5
5
  "private": false,
6
6
  "license": "SEE LICENSE",
7
7
  "bin": {
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "type": "module",
12
12
  "engines": {
13
- "node": ">=20.0.0"
13
+ "node": ">=18"
14
14
  },
15
15
  "scripts": {
16
16
  "bundle": "node tools/cli.js bundle",
@@ -30,6 +30,8 @@
30
30
  "aigile:list": "aigile-method list:agents"
31
31
  },
32
32
  "keywords": [
33
+ "antigravity",
34
+ "gemini",
33
35
  "agentic",
34
36
  "agile",
35
37
  "ai",
@@ -69,4 +71,4 @@
69
71
  "README.md",
70
72
  "package.json"
71
73
  ]
72
- }
74
+ }
package/tools/cli.js CHANGED
@@ -307,11 +307,38 @@ async function multiSelectPrompt({ title, options, defaults = [] }) {
307
307
  }
308
308
 
309
309
  async function installInteractive({ autoYes = false }) {
310
- // Default to GitHub Copilot-focused install
311
310
  const dest = process.cwd();
312
311
  printInstallBanner({ showGMSignature: true });
313
312
 
313
+ // ── CLI flag overrides ──
314
+ const forcedCopilot = process.argv.includes('--for-copilot');
315
+ const forcedAntigravity = process.argv.includes('--for-antigravity');
314
316
  const forcedJavaInstructions = process.argv.includes('--with-java-instructions');
317
+
318
+ // ── Platform selector ──
319
+ let platforms = [];
320
+ if (forcedCopilot || forcedAntigravity) {
321
+ // Explicit flags take precedence
322
+ if (forcedCopilot) platforms.push('copilot');
323
+ if (forcedAntigravity) platforms.push('antigravity');
324
+ } else if (autoYes) {
325
+ platforms = ['copilot']; // default for --yes
326
+ } else {
327
+ const platformSelections = await multiSelectPrompt({
328
+ title: 'Select target platforms:',
329
+ options: [
330
+ { label: 'GitHub Copilot (.github/agents/)', value: 'copilot' },
331
+ { label: 'Google Antigravity (.agent/ + GEMINI.md)', value: 'antigravity' },
332
+ ],
333
+ defaults: ['copilot'],
334
+ });
335
+ platforms = platformSelections.length > 0 ? platformSelections : ['copilot'];
336
+ }
337
+
338
+ const installCopilot = platforms.includes('copilot');
339
+ const installAntigravityFlag = platforms.includes('antigravity');
340
+
341
+ // ── Optional components (only shown in interactive mode) ──
315
342
  let addMcpJson = false;
316
343
  let addMcpSettings = false;
317
344
  let addJavaInstructions = forcedJavaInstructions;
@@ -319,13 +346,14 @@ async function installInteractive({ autoYes = false }) {
319
346
  addMcpJson = false;
320
347
  addMcpSettings = false;
321
348
  } else {
349
+ const componentOptions = [
350
+ { label: 'Install MCP servers (.vscode/mcp.json from mcp/servers.json)', value: 'mcpJson' },
351
+ { label: 'Add mock .vscode/settings.json MCP endpoints', value: 'mcpSettings' },
352
+ { label: 'Include Java contributor instructions (.github/instructions/java.instructions.md)', value: 'javaInstructions' },
353
+ ];
322
354
  const selections = await multiSelectPrompt({
323
355
  title: 'Select optional components:',
324
- options: [
325
- { label: 'Install MCP servers (.vscode/mcp.json from mcp/servers.json)', value: 'mcpJson' },
326
- { label: 'Add mock .vscode/settings.json MCP endpoints', value: 'mcpSettings' },
327
- { label: 'Include Java contributor instructions (.github/instructions/java.instructions.md)', value: 'javaInstructions' },
328
- ],
356
+ options: componentOptions,
329
357
  defaults: forcedJavaInstructions ? ['mcpJson', 'javaInstructions'] : ['mcpJson'],
330
358
  });
331
359
  addMcpJson = selections.includes('mcpJson');
@@ -333,26 +361,25 @@ async function installInteractive({ autoYes = false }) {
333
361
  if (!forcedJavaInstructions) addJavaInstructions = selections.includes('javaInstructions');
334
362
  }
335
363
 
336
- installGithubCopilot(dest, { addJavaInstructions });
337
- // After core install, attempt to add consumer convenience scripts (opt-out with AIGILE_ADD_SCRIPTS=0)
364
+ // ── Run platform-specific installers ──
365
+ let antigravityResult = null;
366
+ if (installCopilot) {
367
+ installGithubCopilot(dest, { addJavaInstructions });
368
+ }
369
+ if (installAntigravityFlag) {
370
+ antigravityResult = installAntigravity(dest);
371
+ }
372
+
373
+ // ── Post-install shared steps ──
338
374
  maybeAddConsumerScripts(dest);
339
375
  if (process.argv.includes('--prune-legacy')) pruneLegacy(dest);
340
376
  if (addMcpSettings) writeMockMcp(dest);
341
377
  if (addMcpJson) writeMcpJson(dest);
378
+ if (installCopilot) writeVscodeSettings(dest);
379
+ writeManifest(dest, { addMcpJson, addMcpSettings, addJavaInstructions, forAntigravity: installAntigravityFlag });
342
380
 
343
- // Always write essential VS Code settings for orchestrator functionality
344
- writeVscodeSettings(dest);
345
-
346
- writeManifest(dest, { addMcpJson, addMcpSettings, addJavaInstructions });
347
-
348
- // Print a concise, colorized summary
381
+ // ── Print summary ──
349
382
  try {
350
- // Check for new agents format first, fallback to legacy chatmodes
351
- const agentsDir = path.join(dest, '.github', 'agents');
352
- const chatModesDir = path.join(dest, '.github', 'chatmodes');
353
- const agentCount = fs.existsSync(agentsDir) ? fs.readdirSync(agentsDir).filter(f => f.endsWith('.agent.md')).length : 0;
354
- const modeCount = fs.existsSync(chatModesDir) ? fs.readdirSync(chatModesDir).filter(f => f.endsWith('.chatmode.md')).length : 0;
355
- const totalAgents = agentCount + modeCount;
356
383
  const coreDir = path.join(dest, '.aigile-core');
357
384
  const coreFiles = listFilesRecursive(coreDir).length;
358
385
  const color = (code) => (s) => `\x1b[${code}m${s}\x1b[0m`;
@@ -361,17 +388,32 @@ async function installInteractive({ autoYes = false }) {
361
388
  const yellow = color(33);
362
389
  console.log(`\n${green('Summary:')}`);
363
390
  console.log(` - .aigile-core files: ${cyan(String(coreFiles))}`);
364
- console.log(` - Custom agents created: ${cyan(String(agentCount))}`);
365
- if (modeCount > 0) console.log(` - Legacy chat modes: ${cyan(String(modeCount))} (consider upgrading)`);
391
+
392
+ if (installCopilot) {
393
+ const agentsDir = path.join(dest, '.github', 'agents');
394
+ const agentCount = fs.existsSync(agentsDir) ? fs.readdirSync(agentsDir).filter(f => f.endsWith('.agent.md')).length : 0;
395
+ console.log(` - Copilot custom agents: ${cyan(String(agentCount))}`);
396
+ }
397
+
398
+ if (installAntigravityFlag && antigravityResult) {
399
+ console.log(` - Antigravity rules: ${cyan(String(antigravityResult.rules))}`);
400
+ console.log(` - Antigravity workflows: ${cyan(String(antigravityResult.workflows))}`);
401
+ console.log(` - ${yellow('GEMINI.md')} generated`);
402
+ }
403
+
366
404
  if (addMcpJson) console.log(` - ${yellow('.vscode/mcp.json')} generated (fill API keys)`);
367
405
  if (addMcpSettings) console.log(` - ${yellow('.vscode/settings.json')} updated with mock MCP servers`);
368
406
  if (addJavaInstructions) console.log(` - ${yellow('.github/instructions/java.instructions.md')} copied`);
407
+
369
408
  console.log(`\n${green('Next steps:')}`);
370
409
  let step = 1;
371
- console.log(` ${step++}) Open VS Code in this folder`);
372
- console.log(` ${step++}) Use GitHub Copilot Chat and select an agent from the ${yellow('Agents dropdown')}`);
410
+ if (installCopilot) {
411
+ console.log(` ${step++}) Open VS Code and select an agent from the ${yellow('Agents dropdown')} in Copilot Chat`);
412
+ }
413
+ if (installAntigravityFlag) {
414
+ console.log(` ${step++}) Open Antigravity IDE — agent rules and workflows are ready in ${yellow('.agent/')}`);
415
+ }
373
416
  if (addMcpJson) console.log(` ${step++}) When prompted, provide the required API keys for MCP servers`);
374
- if (addJavaInstructions) console.log(` ${step++}) Review ${yellow('.github/instructions/java.instructions.md')} for team guidelines`);
375
417
  } catch { }
376
418
  }
377
419
 
@@ -585,17 +627,17 @@ function relevantDependencies(agentId) {
585
627
 
586
628
  // Agent-specific data file mappings
587
629
  const dataMappings = {
588
- 'aigile-orchestrator': ['aigile-kb.md'], // Orchestrator has access to knowledge base
589
- 'aigile-master': ['aigile-kb.md', 'brainstorming-techniques.md', 'elicitation-methods.md', 'technical-preferences.md', 'test-levels-framework.md', 'test-priorities-matrix.md'], // Master has access to all data files
590
- analyst: ['brainstorming-techniques.md', 'elicitation-methods.md', 'aigile-kb.md'],
591
- architect: ['technical-preferences.md', 'aigile-kb.md'],
592
- qa: ['test-levels-framework.md', 'test-priorities-matrix.md', 'technical-preferences.md', 'aigile-kb.md'],
593
- dev: ['technical-preferences.md', 'test-levels-framework.md', 'test-priorities-matrix.md', 'aigile-kb.md'],
594
- pm: ['aigile-kb.md'],
595
- po: ['aigile-kb.md'],
596
- sm: ['aigile-kb.md'],
597
- 'ui-expert': ['aigile-kb.md'],
598
- 'ux-expert': ['aigile-kb.md']
630
+ 'aigile-orchestrator': ['aigile-kb.md'], // Orchestrator has access to knowledge base
631
+ 'aigile-master': ['aigile-kb.md', 'brainstorming-techniques.md', 'elicitation-methods.md', 'technical-preferences.md', 'test-levels-framework.md', 'test-priorities-matrix.md'], // Master has access to all data files
632
+ analyst: ['brainstorming-techniques.md', 'elicitation-methods.md', 'aigile-kb.md'],
633
+ architect: ['technical-preferences.md', 'aigile-kb.md'],
634
+ qa: ['test-levels-framework.md', 'test-priorities-matrix.md', 'technical-preferences.md', 'aigile-kb.md'],
635
+ dev: ['technical-preferences.md', 'test-levels-framework.md', 'test-priorities-matrix.md', 'aigile-kb.md'],
636
+ pm: ['aigile-kb.md'],
637
+ po: ['aigile-kb.md'],
638
+ sm: ['aigile-kb.md'],
639
+ 'ui-expert': ['aigile-kb.md'],
640
+ 'ux-expert': ['aigile-kb.md']
599
641
  };
600
642
 
601
643
  // Agent-specific checklist mappings based on role responsibilities
@@ -798,12 +840,12 @@ function mcpToolsForAgent(agentId) {
798
840
  function mcpServersForAgent(agentId) {
799
841
  // Return MCP server list per agent - all non-orchestrator agents get the core 3 MCPs
800
842
  const coreMcpServers = ['github.com', 'sequentialthinking', 'context7'];
801
-
843
+
802
844
  // Orchestrator has NO MCP tools - only runSubagent
803
845
  if (agentId === 'aigile-orchestrator') {
804
846
  return [];
805
847
  }
806
-
848
+
807
849
  return coreMcpServers;
808
850
  }
809
851
 
@@ -1210,7 +1252,7 @@ function generateCustomAgent({ agentId, agentMeta, agentMd, tools, tasks, checkl
1210
1252
  const title = agentMeta.title || toTitleCase(agentId);
1211
1253
  const description = agentMeta.whenToUse || `Use for ${title} responsibilities and workflows.`;
1212
1254
  const metaName = agentMeta.name || title;
1213
-
1255
+
1214
1256
  // Full tool list for all agents (except orchestrator)
1215
1257
  // Uses VS Code prefix/toolName format and MCP wildcards
1216
1258
  const FULL_AGENT_TOOLS = [
@@ -1244,13 +1286,13 @@ function generateCustomAgent({ agentId, agentMeta, agentMd, tools, tasks, checkl
1244
1286
  ];
1245
1287
 
1246
1288
  // Use full tool list for all agents except orchestrator
1247
- const toolList = agentId === 'aigile-orchestrator'
1248
- ? ['read/readFile', 'agent', 'search/codebase', 'search/fileSearch', 'search/textSearch', 'search/listDirectory', 'sequentialthinking/*']
1289
+ const toolList = agentId === 'aigile-orchestrator'
1290
+ ? ['read/readFile', 'agent', 'search/codebase', 'search/fileSearch', 'search/textSearch', 'search/listDirectory', 'sequentialthinking/*']
1249
1291
  : [...new Set([...FULL_AGENT_TOOLS, ...tools])].sort();
1250
-
1292
+
1251
1293
  // Generate handoffs based on agent role
1252
1294
  const handoffs = generateHandoffsFor(agentId);
1253
-
1295
+
1254
1296
  // Build YAML frontmatter in new custom agents format
1255
1297
  const fmLines = [
1256
1298
  '---',
@@ -1264,7 +1306,7 @@ function generateCustomAgent({ agentId, agentMeta, agentMd, tools, tasks, checkl
1264
1306
  }
1265
1307
  fmLines.push('model: Claude Opus 4.6');
1266
1308
  fmLines.push('user-invokable: true');
1267
-
1309
+
1268
1310
  if (handoffs.length > 0) {
1269
1311
  fmLines.push('handoffs:');
1270
1312
  for (const h of handoffs) {
@@ -1276,14 +1318,14 @@ function generateCustomAgent({ agentId, agentMeta, agentMd, tools, tasks, checkl
1276
1318
  }
1277
1319
  fmLines.push('---');
1278
1320
  fmLines.push('');
1279
-
1321
+
1280
1322
  // Build the agent body
1281
1323
  const person = { ...personaFor(agentId), ...(agentMeta.persona || {}) };
1282
1324
  const combinedPrinciples = (agentMeta.corePrinciples && agentMeta.corePrinciples.length)
1283
1325
  ? agentMeta.corePrinciples
1284
1326
  : principlesFor(agentId);
1285
1327
  const deps = relevantDependencies(agentId);
1286
-
1328
+
1287
1329
  const body = [];
1288
1330
  body.push(`# ${title}`);
1289
1331
  body.push('');
@@ -1314,7 +1356,7 @@ function generateCustomAgent({ agentId, agentMeta, agentMd, tools, tasks, checkl
1314
1356
  body.push('| `analyst` | Requirements analysis |');
1315
1357
  body.push('| `pm` | Project planning |');
1316
1358
  body.push('');
1317
-
1359
+
1318
1360
  if (tasks.length > 0) {
1319
1361
  body.push('## Available Tasks');
1320
1362
  body.push('');
@@ -1323,7 +1365,7 @@ function generateCustomAgent({ agentId, agentMeta, agentMd, tools, tasks, checkl
1323
1365
  }
1324
1366
  body.push('');
1325
1367
  }
1326
-
1368
+
1327
1369
  if (deps.templates.length > 0) {
1328
1370
  body.push('## Templates');
1329
1371
  body.push('');
@@ -1334,7 +1376,7 @@ function generateCustomAgent({ agentId, agentMeta, agentMd, tools, tasks, checkl
1334
1376
  }
1335
1377
  body.push('');
1336
1378
  }
1337
-
1379
+
1338
1380
  body.push('## Original Agent Definition');
1339
1381
  body.push('');
1340
1382
  body.push('<details>');
@@ -1343,7 +1385,7 @@ function generateCustomAgent({ agentId, agentMeta, agentMd, tools, tasks, checkl
1343
1385
  body.push(agentMd.trim());
1344
1386
  body.push('');
1345
1387
  body.push('</details>');
1346
-
1388
+
1347
1389
  return fmLines.join('\n') + body.join('\n');
1348
1390
  }
1349
1391
 
@@ -1390,10 +1432,300 @@ function generateHandoffsFor(agentId) {
1390
1432
  { label: '💻 Implement UX', agent: 'Full Stack Developer', prompt: 'Implement the UX recommendations.', send: false },
1391
1433
  ],
1392
1434
  };
1393
-
1435
+
1394
1436
  return handoffMappings[agentId] || [];
1395
1437
  }
1396
1438
 
1439
+ // ---------------------------------------------------------------------------
1440
+ // Antigravity / Gemini CLI generation
1441
+ // ---------------------------------------------------------------------------
1442
+
1443
+ /**
1444
+ * Generate an Antigravity-compatible rules file for an agent.
1445
+ * Antigravity uses plain markdown rules in .agent/rules/ — no YAML frontmatter,
1446
+ * no tools declarations, no handoffs (handled differently in Antigravity).
1447
+ */
1448
+ function generateAntigravityAgent({ agentId, agentMeta, agentMd, tools, tasks, checklists }) {
1449
+ const title = agentMeta.title || toTitleCase(agentId);
1450
+ const description = agentMeta.whenToUse || `Use for ${title} responsibilities and workflows.`;
1451
+ const person = { ...personaFor(agentId), ...(agentMeta.persona || {}) };
1452
+ const combinedPrinciples = (agentMeta.corePrinciples && agentMeta.corePrinciples.length)
1453
+ ? agentMeta.corePrinciples
1454
+ : principlesFor(agentId);
1455
+ const deps = relevantDependencies(agentId);
1456
+
1457
+ const lines = [];
1458
+ lines.push(`# ${title} — AIgile Agent Rule`);
1459
+ lines.push('');
1460
+ lines.push(`> ${description}`);
1461
+ lines.push('');
1462
+ lines.push('## Core Identity');
1463
+ lines.push('');
1464
+ lines.push(`- **Role**: ${person.role}`);
1465
+ lines.push(`- **Style**: ${person.style}`);
1466
+ lines.push(`- **Focus**: ${person.focus}`);
1467
+ lines.push('');
1468
+ lines.push('## Operating Principles');
1469
+ lines.push('');
1470
+ for (const p of combinedPrinciples) {
1471
+ lines.push(`- ${p}`);
1472
+ }
1473
+ lines.push('');
1474
+
1475
+ // Agent coordination guidance (replaces Copilot handoffs/runSubagent)
1476
+ lines.push('## Agent Coordination');
1477
+ lines.push('');
1478
+ lines.push('This agent is part of the AIgile framework. Other specialist agents are available:');
1479
+ lines.push('');
1480
+ lines.push('| Agent | Specialty |');
1481
+ lines.push('|-------|-----------|');
1482
+ lines.push('| `dev` | Code implementation, debugging, TDD |');
1483
+ lines.push('| `architect` | Architecture review, documentation |');
1484
+ lines.push('| `po` | Story creation, backlog management |');
1485
+ lines.push('| `qa` | Testing, quality gates |');
1486
+ lines.push('| `analyst` | Requirements analysis |');
1487
+ lines.push('| `pm` | Project planning |');
1488
+ lines.push('');
1489
+
1490
+ if (tasks.length > 0) {
1491
+ lines.push('## Available Tasks');
1492
+ lines.push('');
1493
+ lines.push('Task files are located in `.aigile-core/tasks/`. Load and follow them exactly when executing a command:');
1494
+ lines.push('');
1495
+ for (const t of tasks) {
1496
+ lines.push(`- \`${t}\``);
1497
+ }
1498
+ lines.push('');
1499
+ }
1500
+
1501
+ if (deps.templates.length > 0) {
1502
+ lines.push('## Templates');
1503
+ lines.push('');
1504
+ lines.push('Reference templates in `.aigile-core/templates/`:');
1505
+ lines.push('');
1506
+ for (const t of deps.templates) {
1507
+ lines.push(`- ${t}`);
1508
+ }
1509
+ lines.push('');
1510
+ }
1511
+
1512
+ if (deps.data.length > 0) {
1513
+ lines.push('## Data References');
1514
+ lines.push('');
1515
+ lines.push('Reference data files in `.aigile-core/data/`:');
1516
+ lines.push('');
1517
+ for (const d of deps.data) {
1518
+ lines.push(`- ${d}`);
1519
+ }
1520
+ lines.push('');
1521
+ }
1522
+
1523
+ lines.push('## Original Agent Definition');
1524
+ lines.push('');
1525
+ lines.push('<details>');
1526
+ lines.push('<summary>Expand for full agent configuration</summary>');
1527
+ lines.push('');
1528
+ lines.push(agentMd.trim());
1529
+ lines.push('');
1530
+ lines.push('</details>');
1531
+
1532
+ return lines.join('\n');
1533
+ }
1534
+
1535
+ /**
1536
+ * Generate Antigravity workflow files from an agent's commands.
1537
+ * Each workflow is a .md file with YAML frontmatter (description) and step instructions.
1538
+ * Returns an array of { filename, content } objects.
1539
+ */
1540
+ function generateAntigravityWorkflows(agentId) {
1541
+ const commands = commandsFor(agentId);
1542
+ const workflows = [];
1543
+
1544
+ for (const cmd of commands) {
1545
+ const key = Object.keys(cmd)[0];
1546
+ const val = cmd[key];
1547
+ // Skip meta commands
1548
+ if (key === 'help' || key === 'exit') continue;
1549
+
1550
+ const slug = `aigile-${agentId}-${key}`.replace(/[^a-zA-Z0-9]+/g, '-').replace(/^-+|-+$/g, '').toLowerCase();
1551
+ const wfLines = [];
1552
+ wfLines.push('---');
1553
+ wfLines.push(`description: ${typeof val === 'string' ? val : `AIgile ${agentId}: ${key}`}`);
1554
+ wfLines.push('---');
1555
+ wfLines.push('');
1556
+ wfLines.push(`# ${toTitleCase(key)}`);
1557
+ wfLines.push('');
1558
+ wfLines.push(`This workflow is part of the **${toTitleCase(agentId)}** agent in the AIgile framework.`);
1559
+ wfLines.push('');
1560
+
1561
+ if (Array.isArray(val)) {
1562
+ wfLines.push('## Steps');
1563
+ wfLines.push('');
1564
+ let step = 1;
1565
+ for (const el of val) {
1566
+ wfLines.push(`${step}. ${el}`);
1567
+ step++;
1568
+ }
1569
+ } else if (typeof val === 'string') {
1570
+ wfLines.push(`**Goal:** ${val}`);
1571
+ } else {
1572
+ wfLines.push(`**Goal:** Execute the ${key} command.`);
1573
+ }
1574
+
1575
+ wfLines.push('');
1576
+ wfLines.push('## Resources');
1577
+ wfLines.push('');
1578
+ wfLines.push('- Agent definition: `.aigile-core/agents/`');
1579
+ wfLines.push('- Task files: `.aigile-core/tasks/`');
1580
+ wfLines.push('- Templates: `.aigile-core/templates/`');
1581
+ wfLines.push('');
1582
+
1583
+ workflows.push({ filename: `${slug}.md`, content: wfLines.join('\n') });
1584
+ }
1585
+
1586
+ return workflows;
1587
+ }
1588
+
1589
+ /**
1590
+ * Generate the GEMINI.md project-level instructions file for Antigravity.
1591
+ */
1592
+ function generateGeminiMd(agentIds) {
1593
+ const lines = [];
1594
+ lines.push('# AIgile Development Method');
1595
+ lines.push('');
1596
+ lines.push('This project uses the **AIgile Development Method** — a pragmatic, agent-driven agile framework.');
1597
+ lines.push('');
1598
+ lines.push('## Agent Rules');
1599
+ lines.push('');
1600
+ lines.push('Specialist agent personas are defined in `.agent/rules/`. Each rule file defines a role with specific');
1601
+ lines.push('expertise, operating principles, and task references. When asked to assume a role, load the corresponding');
1602
+ lines.push('rule file from `.agent/rules/`.');
1603
+ lines.push('');
1604
+ lines.push('### Available Agents');
1605
+ lines.push('');
1606
+ lines.push('| Agent | File | Specialty |');
1607
+ lines.push('|-------|------|-----------|');
1608
+ for (const id of agentIds) {
1609
+ const title = toTitleCase(id);
1610
+ const icon = agentIcon(id);
1611
+ lines.push(`| ${icon} ${title} | \`.agent/rules/${id}.md\` | ${title} responsibilities |`);
1612
+ }
1613
+ lines.push('');
1614
+ lines.push('## Workflows');
1615
+ lines.push('');
1616
+ lines.push('On-demand workflows are available in `.agent/workflows/`. Use them as slash commands');
1617
+ lines.push('to trigger specific development activities (e.g., create stories, run QA gate, brainstorm).');
1618
+ lines.push('');
1619
+ lines.push('## Core Assets');
1620
+ lines.push('');
1621
+ lines.push('The `.aigile-core/` directory contains all framework resources:');
1622
+ lines.push('');
1623
+ lines.push('- **`tasks/`** — Executable task instructions (follow them exactly)');
1624
+ lines.push('- **`templates/`** — Output templates (YAML-based)');
1625
+ lines.push('- **`checklists/`** — Quality and process checklists');
1626
+ lines.push('- **`data/`** — Reference data (brainstorming techniques, test frameworks, etc.)');
1627
+ lines.push('- **`core-config.yaml`** — Project paths and preferences');
1628
+ lines.push('');
1629
+ lines.push('## Key Principles');
1630
+ lines.push('');
1631
+ lines.push('- Tasks are executable instructions; follow them exactly.');
1632
+ lines.push('- Elicitation steps are mandatory; always ask for missing inputs.');
1633
+ lines.push('- Save artifacts under `docs/` for traceability.');
1634
+ lines.push('- Prefer small, safe, testable changes.');
1635
+ lines.push('');
1636
+ return lines.join('\n');
1637
+ }
1638
+
1639
+ /**
1640
+ * Install AIgile for Google Antigravity / Gemini CLI.
1641
+ * Creates .agent/rules/, .agent/workflows/, and GEMINI.md.
1642
+ */
1643
+ function installAntigravity(dest) {
1644
+ // 1) Copy core to .aigile-core (shared with Copilot path)
1645
+ const srcCore = path.join(root, 'core');
1646
+ const dstCore = path.join(dest, '.aigile-core');
1647
+ if (fs.existsSync(srcCore)) {
1648
+ copyDir(srcCore, dstCore);
1649
+ }
1650
+
1651
+ // 2) Generate agent rules in .agent/rules/
1652
+ const agentsDir = path.join(srcCore, 'agents');
1653
+ const rulesDir = path.join(dest, '.agent', 'rules');
1654
+ const workflowsDir = path.join(dest, '.agent', 'workflows');
1655
+ fs.mkdirSync(rulesDir, { recursive: true });
1656
+ fs.mkdirSync(workflowsDir, { recursive: true });
1657
+
1658
+ const generatedRules = [];
1659
+ const allAgentIds = [];
1660
+
1661
+ if (fs.existsSync(agentsDir)) {
1662
+ const files = fs.readdirSync(agentsDir).filter(f => f.endsWith('.md'));
1663
+ const agentMap = new Map(); // id -> filename
1664
+
1665
+ // First pass: identify all agents and prioritize source format (.md) over native (.agent.md)
1666
+ for (const f of files) {
1667
+ const isNativeAgent = f.endsWith('.agent.md');
1668
+ const agentId = isNativeAgent ? f.replace(/\.agent\.md$/, '') : f.replace(/\.[^/.]+$/, '');
1669
+
1670
+ if (!agentMap.has(agentId)) {
1671
+ agentMap.set(agentId, f);
1672
+ } else {
1673
+ // If we already have an entry, override ONLY if current file is source format (and previous was native)
1674
+ const currentIsSource = !isNativeAgent;
1675
+ const existingIsNative = agentMap.get(agentId).endsWith('.agent.md');
1676
+ if (currentIsSource && existingIsNative) {
1677
+ agentMap.set(agentId, f);
1678
+ }
1679
+ }
1680
+ }
1681
+
1682
+ // Sort by agentId for consistent output
1683
+ const sortedIds = Array.from(agentMap.keys()).sort();
1684
+
1685
+ for (const agentId of sortedIds) {
1686
+ const f = agentMap.get(agentId);
1687
+ const agentPath = path.join(agentsDir, f);
1688
+ const agentMd = read(agentPath);
1689
+ const agentMeta = extractAgentMeta(agentMd);
1690
+ const allTasks = listTasksForAgent(agentId);
1691
+
1692
+ allAgentIds.push(agentId);
1693
+
1694
+ // Generate Antigravity rule file
1695
+ const ruleContent = generateAntigravityAgent({
1696
+ agentId,
1697
+ agentMeta,
1698
+ agentMd,
1699
+ tools: [],
1700
+ tasks: allTasks,
1701
+ checklists: [],
1702
+ });
1703
+ write(path.join(rulesDir, `${agentId}.md`), ruleContent);
1704
+ generatedRules.push(agentId);
1705
+
1706
+ // Generate workflows for this agent
1707
+ const workflows = generateAntigravityWorkflows(agentId);
1708
+ for (const wf of workflows) {
1709
+ write(path.join(workflowsDir, wf.filename), wf.content);
1710
+ }
1711
+ }
1712
+ }
1713
+
1714
+ // 3) Generate GEMINI.md at project root
1715
+ const geminiMdContent = generateGeminiMd(allAgentIds);
1716
+ write(path.join(dest, 'GEMINI.md'), geminiMdContent);
1717
+
1718
+ const color = (code) => (s) => `\x1b[${code}m${s}\x1b[0m`;
1719
+ const green = color(32);
1720
+ console.log(`✅ Created ${generatedRules.length} agent rules in .agent/rules/`);
1721
+ const wfCount = fs.readdirSync(workflowsDir).filter(f => f.endsWith('.md')).length;
1722
+ console.log(`✅ Created ${wfCount} workflows in .agent/workflows/`);
1723
+ console.log(green('✅ Generated GEMINI.md'));
1724
+ console.log(green('✅ Installed AIgile for Google Antigravity into'), dest);
1725
+
1726
+ return { rules: generatedRules.length, workflows: wfCount };
1727
+ }
1728
+
1397
1729
  function installGithubCopilot(dest, { addJavaInstructions = false, useLegacyFormat = false } = {}) {
1398
1730
  // 1) Copy core to .aigile-core (clean, IDE-friendly)
1399
1731
  const srcCore = path.join(root, 'core');
@@ -1404,7 +1736,7 @@ function installGithubCopilot(dest, { addJavaInstructions = false, useLegacyForm
1404
1736
  // 2) Generate GitHub Copilot custom agents in .github/agents/ (new format)
1405
1737
  // Or legacy chatmodes in .github/chatmodes/ if explicitly requested
1406
1738
  const agentsDir = path.join(srcCore, 'agents');
1407
- const outputDir = useLegacyFormat
1739
+ const outputDir = useLegacyFormat
1408
1740
  ? path.join(dest, '.github', 'chatmodes')
1409
1741
  : path.join(dest, '.github', 'agents');
1410
1742
  fs.mkdirSync(outputDir, { recursive: true });
@@ -1422,7 +1754,7 @@ function installGithubCopilot(dest, { addJavaInstructions = false, useLegacyForm
1422
1754
  const tools = [];
1423
1755
  const allTasks = listTasksForAgent(agentId);
1424
1756
  const allChecklists = []; // Use only agent-specific checklists from relevantDependencies()
1425
-
1757
+
1426
1758
  // If already in native .agent.md format, copy directly
1427
1759
  if (isNativeAgent && !useLegacyFormat) {
1428
1760
  const outName = f;
@@ -1430,25 +1762,25 @@ function installGithubCopilot(dest, { addJavaInstructions = false, useLegacyForm
1430
1762
  generatedAgents.push({ id: agentId, format: 'native' });
1431
1763
  continue;
1432
1764
  }
1433
-
1765
+
1434
1766
  // Generate structured agent/chatmode file
1435
1767
  const outContent = useLegacyFormat
1436
1768
  ? generateStructuredChatmode({
1437
- agentId,
1438
- agentMeta,
1439
- agentMd,
1440
- tools,
1441
- tasks: allTasks,
1442
- checklists: allChecklists,
1443
- })
1769
+ agentId,
1770
+ agentMeta,
1771
+ agentMd,
1772
+ tools,
1773
+ tasks: allTasks,
1774
+ checklists: allChecklists,
1775
+ })
1444
1776
  : generateCustomAgent({
1445
- agentId,
1446
- agentMeta,
1447
- agentMd,
1448
- tools,
1449
- tasks: allTasks,
1450
- checklists: allChecklists,
1451
- });
1777
+ agentId,
1778
+ agentMeta,
1779
+ agentMd,
1780
+ tools,
1781
+ tasks: allTasks,
1782
+ checklists: allChecklists,
1783
+ });
1452
1784
  const outName = useLegacyFormat
1453
1785
  ? `${kebabCaseName(f)}.chatmode.md`
1454
1786
  : `${kebabCaseName(f)}.agent.md`;
@@ -1509,7 +1841,7 @@ function maybeAddConsumerScripts(dest) {
1509
1841
  } catch { /* ignore */ }
1510
1842
  }
1511
1843
 
1512
- function writeManifest(dest, { addMcpJson = false, addMcpSettings = false, addJavaInstructions = false } = {}) {
1844
+ function writeManifest(dest, { addMcpJson = false, addMcpSettings = false, addJavaInstructions = false, forAntigravity = false } = {}) {
1513
1845
  try {
1514
1846
  const manifest = {
1515
1847
  name: '@mark-gozner/aigile-method',
@@ -1547,6 +1879,16 @@ function writeManifest(dest, { addMcpJson = false, addMcpSettings = false, addJa
1547
1879
  if (fs.existsSync(promptsDir)) {
1548
1880
  manifest.prompts = fs.readdirSync(promptsDir).filter(f => f.endsWith('.md') || f.endsWith('.prompt.md') || f.endsWith('.txt')).length;
1549
1881
  }
1882
+ // Antigravity output tracking
1883
+ if (forAntigravity) {
1884
+ const rulesDir = path.join(dest, '.agent', 'rules');
1885
+ const workflowsDir = path.join(dest, '.agent', 'workflows');
1886
+ manifest.antigravity = {
1887
+ rules: fs.existsSync(rulesDir) ? fs.readdirSync(rulesDir).filter(f => f.endsWith('.md')).length : 0,
1888
+ workflows: fs.existsSync(workflowsDir) ? fs.readdirSync(workflowsDir).filter(f => f.endsWith('.md')).length : 0,
1889
+ geminiMd: fs.existsSync(path.join(dest, 'GEMINI.md'))
1890
+ };
1891
+ }
1550
1892
  write(path.join(dest, '.aigile-manifest.json'), JSON.stringify(manifest, null, 2));
1551
1893
  } catch { /* ignore */ }
1552
1894
  }
@@ -1567,7 +1909,7 @@ function showStatus(cwd) {
1567
1909
  console.log(`Agents: ${data.agents?.length || 0}`);
1568
1910
  console.log(`Custom Agents: ${data.customAgents || 0}`);
1569
1911
  if (data.chatModes > 0) console.log(`Chat Modes: ${data.chatModes} (legacy)`);
1570
- if (typeof data.prompts !== 'undefined') console.log(`Prompts: ${data.prompts}`);
1912
+ if (typeof data.prompts !== 'undefined') console.log(`Prompts: ${data.prompts}`);
1571
1913
  console.log(`MCP Servers: ${data.mcp?.serversJson ? 'yes' : 'no'}`);
1572
1914
  console.log(`MCP Mock Sets: ${data.mcp?.mockSettings ? 'yes' : 'no'}`);
1573
1915
  if (data.instructions) {
@@ -1722,11 +2064,11 @@ function writeVscodeSettings(dest) {
1722
2064
  if (fs.existsSync(vscodeSettingsPath)) {
1723
2065
  try { settings = JSON.parse(read(vscodeSettingsPath)); } catch { }
1724
2066
  }
1725
-
2067
+
1726
2068
  // Enable custom agent as subagent (experimental) - required for orchestrator delegation
1727
2069
  // This allows runSubagent calls to use the target agent's toolset
1728
2070
  settings['chat.customAgentInSubagent.enabled'] = true;
1729
-
2071
+
1730
2072
  write(vscodeSettingsPath, JSON.stringify(settings, null, 2));
1731
2073
  console.log('✅ Configured VS Code settings for orchestrator subagent delegation');
1732
2074
  }
@@ -1739,18 +2081,25 @@ else if (cmd === 'install') {
1739
2081
  const addMcpJsonFlag = flags.has('--with-mcp');
1740
2082
  const addMcpSettingsFlag = flags.has('--with-mcp-settings');
1741
2083
  const addJavaInstructionsFlag = flags.has('--with-java-instructions');
2084
+ const forAntigravityFlag = flags.has('--for-antigravity');
2085
+ const forCopilotFlag = flags.has('--for-copilot');
1742
2086
  // If flags explicitly provided, skip prompts and just do what flags request
1743
- if (addMcpJsonFlag || addMcpSettingsFlag || addJavaInstructionsFlag) {
2087
+ if (addMcpJsonFlag || addMcpSettingsFlag || addJavaInstructionsFlag || forAntigravityFlag || forCopilotFlag) {
1744
2088
  printInstallBanner({ showGMSignature: true });
1745
2089
  const dest = process.cwd();
1746
- installGithubCopilot(dest, { addJavaInstructions: addJavaInstructionsFlag });
2090
+ const doCopilot = forCopilotFlag || !forAntigravityFlag; // default to copilot unless only antigravity is requested
2091
+ if (doCopilot) {
2092
+ installGithubCopilot(dest, { addJavaInstructions: addJavaInstructionsFlag });
2093
+ }
2094
+ if (forAntigravityFlag) {
2095
+ installAntigravity(dest);
2096
+ }
1747
2097
  maybeAddConsumerScripts(dest);
1748
2098
  if (flags.has('--prune-legacy')) pruneLegacy(dest);
1749
2099
  if (addMcpSettingsFlag) writeMockMcp(dest);
1750
2100
  if (addMcpJsonFlag) writeMcpJson(dest);
1751
- // Always write essential VS Code settings for orchestrator functionality
1752
- writeVscodeSettings(dest);
1753
- writeManifest(dest, { addMcpJson: addMcpJsonFlag, addMcpSettings: addMcpSettingsFlag, addJavaInstructions: addJavaInstructionsFlag });
2101
+ if (doCopilot) writeVscodeSettings(dest);
2102
+ writeManifest(dest, { addMcpJson: addMcpJsonFlag, addMcpSettings: addMcpSettingsFlag, addJavaInstructions: addJavaInstructionsFlag, forAntigravity: forAntigravityFlag });
1754
2103
  } else {
1755
2104
  await installInteractive({ autoYes });
1756
2105
  }
@@ -1774,7 +2123,7 @@ else if (cmd === 'init' || !cmd) {
1774
2123
  for (let i = 0; i < argvRest.length; i++) {
1775
2124
  const a = argvRest[i];
1776
2125
  if (a === 'init') continue;
1777
- if (a === '--token' && argvRest[i+1]) { i++; continue; } // skip legacy token flag
2126
+ if (a === '--token' && argvRest[i + 1]) { i++; continue; } // skip legacy token flag
1778
2127
  if (a.startsWith('--token=')) { continue; } // skip legacy token flag
1779
2128
  passThrough.add(a);
1780
2129
  }
@@ -1784,14 +2133,16 @@ else if (cmd === 'init' || !cmd) {
1784
2133
  const addMcpJson = passThrough.has('--with-mcp');
1785
2134
  const addMcpSettings = passThrough.has('--with-mcp-settings');
1786
2135
  const addJavaInstructions = passThrough.has('--with-java-instructions');
1787
- installGithubCopilot(dest, { addJavaInstructions });
2136
+ const forAntigravity = passThrough.has('--for-antigravity');
2137
+ const forCopilot = passThrough.has('--for-copilot') || !forAntigravity;
2138
+ if (forCopilot) installGithubCopilot(dest, { addJavaInstructions });
2139
+ if (forAntigravity) installAntigravity(dest);
1788
2140
  maybeAddConsumerScripts(dest);
1789
2141
  if (passThrough.has('--prune-legacy')) pruneLegacy(dest);
1790
2142
  if (addMcpSettings) writeMockMcp(dest);
1791
2143
  if (addMcpJson) writeMcpJson(dest);
1792
- // Always write essential VS Code settings for orchestrator functionality
1793
- writeVscodeSettings(dest);
1794
- writeManifest(dest, { addMcpJson, addMcpSettings, addJavaInstructions });
2144
+ if (forCopilot) writeVscodeSettings(dest);
2145
+ writeManifest(dest, { addMcpJson, addMcpSettings, addJavaInstructions, forAntigravity });
1795
2146
  console.log('✅ Init complete');
1796
2147
  }
1797
2148
  else if (cmd === 'auth-install') {
@@ -1803,13 +2154,16 @@ else if (cmd === 'auth-install') {
1803
2154
  const addMcpJson = argvRest.includes('--with-mcp');
1804
2155
  const addMcpSettings = argvRest.includes('--with-mcp-settings');
1805
2156
  const addJavaInstructions = argvRest.includes('--with-java-instructions');
1806
- installGithubCopilot(dest, { addJavaInstructions });
2157
+ const forAntigravity = argvRest.includes('--for-antigravity');
2158
+ const forCopilot = argvRest.includes('--for-copilot') || !forAntigravity;
2159
+ if (forCopilot) installGithubCopilot(dest, { addJavaInstructions });
2160
+ if (forAntigravity) installAntigravity(dest);
1807
2161
  maybeAddConsumerScripts(dest);
1808
2162
  if (argvRest.includes('--prune-legacy')) pruneLegacy(dest);
1809
2163
  if (addMcpSettings) writeMockMcp(dest);
1810
2164
  if (addMcpJson) writeMcpJson(dest);
1811
- writeVscodeSettings(dest);
1812
- writeManifest(dest, { addMcpJson, addMcpSettings, addJavaInstructions });
2165
+ if (forCopilot) writeVscodeSettings(dest);
2166
+ writeManifest(dest, { addMcpJson, addMcpSettings, addJavaInstructions, forAntigravity });
1813
2167
  console.log('✅ Install complete');
1814
2168
  }
1815
2169
  else {
@@ -1824,15 +2178,17 @@ else {
1824
2178
  console.log(' --with-mcp Include .vscode/mcp.json');
1825
2179
  console.log(' --with-mcp-settings Include mock .vscode/settings.json MCP endpoints');
1826
2180
  console.log(' --with-java-instructions Copy Java instructions into .github/instructions');
2181
+ console.log(' --for-copilot Install for GitHub Copilot (.github/agents/)');
2182
+ console.log(' --for-antigravity Install for Google Antigravity (.agent/ + GEMINI.md)');
1827
2183
  console.log(' --prune-legacy Remove legacy artifacts (old .aigile, docs skeleton, chatmodes)');
1828
2184
  console.log(' --use-legacy-format Use deprecated .chatmode.md format instead of .agent.md');
1829
2185
  console.log(' --yes Skip interactive component selection for install');
1830
2186
  console.log('\\nExamples:');
1831
- console.log(' npx @mark-gozner/aigile-method # installs agents and core');
2187
+ console.log(' npx @mark-gozner/aigile-method # installs agents and core (Copilot)');
2188
+ console.log(' npx @mark-gozner/aigile-method install --for-antigravity --yes # Antigravity only');
2189
+ console.log(' npx @mark-gozner/aigile-method install --for-copilot --for-antigravity --yes # both platforms');
1832
2190
  console.log(' npx @mark-gozner/aigile-method init --with-mcp');
1833
- console.log(' npx @mark-gozner/aigile-method install --yes');
1834
- console.log('\\nNew Features (v0.3.0):');
1835
- console.log(' - Custom Agents: Uses new .github/agents/*.agent.md format');
1836
- console.log(' - Handoffs: Agents can hand off to other specialists');
1837
- console.log(' - runSubagent: Autonomous task delegation between agents');
2191
+ console.log('\\nFeatures:');
2192
+ console.log(' - GitHub Copilot: Custom agents (.agent.md), handoffs, runSubagent');
2193
+ console.log(' - Google Antigravity: Agent rules, workflows, GEMINI.md');
1838
2194
  }