agents-templated 1.2.10 → 1.2.12

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/README.md CHANGED
@@ -120,11 +120,11 @@ Agents Templated automatically configures 4 major AI coding assistants:
120
120
  | AI Agent | Config File | Auto-Discovery |
121
121
  |----------|-------------|----------------|
122
122
  | **Cursor** | `.cursorrules` | ✅ Auto-loads in Cursor IDE |
123
- | **GitHub Copilot** | `.github/copilot-instructions.md` | ✅ Auto-loads in VS Code |
124
- | **Claude** | `CLAUDE.md` | ✅ Auto-loads in Claude IDE/API |
125
- | **Gemini** | `GEMINI.md` | ✅ Auto-loads in Gemini IDE/API |
123
+ | **GitHub Copilot** | `.github/instructions/copilot-instructions.md` (+ shim `.github/copilot-instructions.md`) | ✅ Auto-loads in VS Code |
124
+ | **Claude** | `.github/instructions/CLAUDE.md` (+ shim `CLAUDE.md`) | ✅ Compatible |
125
+ | **Gemini** | `.github/instructions/GEMINI.md` (+ shim `GEMINI.md`) | ✅ Compatible |
126
126
 
127
- **All agents follow the same standards:** `agents/rules/` contains behavior rules, and `agents/commands/` contains deterministic slash-command contracts.
127
+ **Single source of truth:** `instructions/source/core.md` drives generated tool-compatible instruction files.
128
128
 
129
129
  ---
130
130
 
@@ -134,13 +134,21 @@ When you run `agents-templated init`, you get:
134
134
 
135
135
  ```
136
136
  your-project/
137
+ ├── instructions/
138
+ │ └── source/
139
+ │ └── core.md # Canonical instruction source of truth
140
+
137
141
  ├── agent-docs/ # 📚 Comprehensive documentation
138
- │ ├── AGENTS.MD # AI assistant guide
139
142
  │ ├── ARCHITECTURE.md # Project architecture & tech stack
140
143
  │ └── README.md # Human-readable setup guide
141
144
 
142
- ├── agents/ # 🤖 AI Agent rules and skills
143
- │ ├── rules/
145
+ ├── .github/
146
+ │ ├── instructions/ # Canonical generated instructions
147
+ │ │ ├── AGENTS.md
148
+ │ │ ├── copilot-instructions.md
149
+ │ │ ├── CLAUDE.md
150
+ │ │ ├── GEMINI.md
151
+ │ │ └── rules/
144
152
  │ │ ├── core.mdc # Core development principles
145
153
  │ │ ├── security.mdc # Security patterns (CRITICAL)
146
154
  │ │ ├── testing.mdc # Testing strategy
@@ -151,7 +159,18 @@ your-project/
151
159
  │ │ ├── intent-routing.mdc # Intent-to-command routing policy
152
160
  │ │ ├── system-workflow.mdc # End-to-end delivery lifecycle gates
153
161
  │ │ └── hardening.mdc # Hardening and obfuscation guidance
154
- │ ├── commands/
162
+ │ ├── skills/
163
+ │ │ ├── find-skills/ # Skill discovery helper
164
+ │ │ ├── feature-delivery/ # Scoped feature delivery workflow
165
+ │ │ ├── bug-triage/ # Reproduction-first defect workflow
166
+ │ │ ├── app-hardening/ # Hardening and release-evidence workflow
167
+ │ │ ├── ui-ux-pro-max/ # Advanced UI/UX design implementation skill
168
+ │ │ ├── README.md # Guide for creating custom skills
169
+ │ │ └── [your-custom-skills]/ # Your project-specific skills
170
+ │ └── copilot-instructions.md # Compatibility shim for Copilot
171
+
172
+ ├── agents/ # 🤖 Deterministic command contracts
173
+ │ └── commands/
155
174
  │ │ ├── SCHEMA.md # Global slash-command response schema
156
175
  │ │ ├── plan.md # /plan contract
157
176
  │ │ ├── fix.md # /fix contract
@@ -159,20 +178,10 @@ your-project/
159
178
  │ │ ├── release.md # /release contract
160
179
  │ │ ├── ... # Other command contracts
161
180
  │ │ └── README.md # Commands directory guide
162
- │ └── skills/
163
- │ ├── find-skills/ # Skill discovery helper
164
- │ ├── feature-delivery/ # Scoped feature delivery workflow
165
- │ ├── bug-triage/ # Reproduction-first defect workflow
166
- │ ├── app-hardening/ # Hardening and release-evidence workflow
167
- │ ├── ui-ux-pro-max/ # Advanced UI/UX design implementation skill
168
- │ ├── README.md # Guide for creating custom skills
169
- │ └── [your-custom-skills]/ # Your project-specific skills
170
-
171
- ├── .github/
172
- │ └── copilot-instructions.md # GitHub Copilot config
173
181
 
174
- ├── CLAUDE.md # Claude AI config
175
- ├── GEMINI.md # Gemini AI config
182
+ ├── AGENTS.MD # Compatibility shim for generic agents
183
+ ├── CLAUDE.md # Compatibility shim for Claude tooling
184
+ ├── GEMINI.md # Compatibility shim for Gemini tooling
176
185
  ├── .cursorrules # Cursor IDE config
177
186
  ├── .gitignore # Pre-configured Git ignore
178
187
  └── README.md # Project documentation
package/bin/cli.js CHANGED
@@ -6,6 +6,19 @@ const fs = require('fs-extra');
6
6
  const path = require('path');
7
7
  const chalk = require('chalk');
8
8
  const { version } = require('../package.json');
9
+ const {
10
+ LAYOUT,
11
+ resolveRulesDir,
12
+ resolveSkillsDir,
13
+ hasAnyLayout,
14
+ getLegacyMigrationPlan
15
+ } = require('../lib/layout');
16
+ const {
17
+ CORE_SOURCE_REL_PATH,
18
+ GENERATED_INSTRUCTION_PATHS,
19
+ writeGeneratedInstructions,
20
+ validateInstructionDrift
21
+ } = require('../lib/instructions');
9
22
 
10
23
  // Resolve the templates directory - works in both dev and installed contexts
11
24
  const getTemplatesDir = () => {
@@ -104,9 +117,9 @@ program
104
117
  choices: [
105
118
  { name: 'All components', value: 'all' },
106
119
  { name: 'Documentation files (agent-docs/)', value: 'docs' },
107
- { name: 'Agent rules (agents/rules/*.mdc)', value: 'rules' },
108
- { name: 'Skills (agents/skills/*)', value: 'skills' },
109
- { name: 'AI Agent instructions (Cursor, Copilot, VSCode, Gemini)', value: 'github' }
120
+ { name: 'Agent rules (.github/instructions/rules/*.mdc)', value: 'rules' },
121
+ { name: 'Skills (.github/skills/*)', value: 'skills' },
122
+ { name: 'AI Agent instructions (Cursor, Copilot, Claude, Generic AGENTS)', value: 'github' }
110
123
  ],
111
124
  default: ['all']
112
125
  },
@@ -136,18 +149,19 @@ program
136
149
  if (installAll || choices.includes('docs')) {
137
150
  console.log(chalk.yellow('Installing documentation files...'));
138
151
  const sourceDir = path.join(templateDir, 'agent-docs');
139
- const targetDir = path.join(targetDir, 'agent-docs');
140
- await fs.ensureDir(targetDir);
141
- await copyDirectory(sourceDir, targetDir, options.force);
152
+ const targetDocsDir = path.join(targetDir, 'agent-docs');
153
+ await fs.ensureDir(targetDocsDir);
154
+ await copyDirectory(sourceDir, targetDocsDir, options.force);
155
+ await copyFiles(templateDir, targetDir, [CORE_SOURCE_REL_PATH], options.force);
142
156
  }
143
157
 
144
158
  // Install agent rules
145
159
  if (installAll || choices.includes('rules')) {
146
160
  console.log(chalk.yellow('Installing agent rules...'));
147
- await fs.ensureDir(path.join(targetDir, 'agents', 'rules'));
161
+ await fs.ensureDir(path.join(targetDir, LAYOUT.canonical.rulesDir));
148
162
  await copyDirectory(
149
163
  path.join(templateDir, 'agents', 'rules'),
150
- path.join(targetDir, 'agents', 'rules'),
164
+ path.join(targetDir, LAYOUT.canonical.rulesDir),
151
165
  options.force
152
166
  );
153
167
  }
@@ -155,35 +169,31 @@ program
155
169
  // Install skills
156
170
  if (installAll || choices.includes('skills')) {
157
171
  console.log(chalk.yellow('Installing skills...'));
158
- await fs.ensureDir(path.join(targetDir, 'agents', 'skills'));
172
+ await fs.ensureDir(path.join(targetDir, LAYOUT.canonical.skillsDir));
159
173
  await copyDirectory(
160
174
  path.join(templateDir, 'agents', 'skills'),
161
- path.join(targetDir, 'agents', 'skills'),
175
+ path.join(targetDir, LAYOUT.canonical.skillsDir),
162
176
  options.force
163
177
  );
164
178
  }
165
179
 
166
- // Install AI Agent instructions (Cursor, Copilot, Claude, Gemini)
180
+ // Install AI Agent instructions (Cursor, Copilot, Claude, Generic AGENTS)
167
181
  if (installAll || choices.includes('github')) {
168
182
  console.log(chalk.yellow('Installing AI agent instructions...'));
169
- await fs.ensureDir(path.join(targetDir, '.github'));
170
- await copyFiles(templateDir, targetDir, [
171
- '.cursorrules',
172
- '.github/copilot-instructions.md',
173
- 'CLAUDE.md',
174
- 'GEMINI.md'
175
- ], options.force);
183
+ await fs.ensureDir(path.join(targetDir, '.github', 'instructions'));
184
+ await copyFiles(templateDir, targetDir, ['.cursorrules'], options.force);
185
+ await writeGeneratedInstructions(targetDir, templateDir, options.force);
176
186
  console.log(chalk.gray(' ✓ Cursor (.cursorrules)'));
177
- console.log(chalk.gray(' ✓ GitHub Copilot (.github/copilot-instructions.md)'));
178
- console.log(chalk.gray(' ✓ Claude (CLAUDE.md)'));
179
- console.log(chalk.gray(' ✓ Google Gemini (GEMINI.md)'));
187
+ console.log(chalk.gray(' ✓ GitHub Copilot (.github/copilot-instructions.md shim)'));
188
+ console.log(chalk.gray(' ✓ Claude (.claude/CLAUDE.md shim)'));
189
+ console.log(chalk.gray(' ✓ Generic AGENTS (AGENTS.MD shim + canonical .github/instructions/AGENTS.md)'));
180
190
  }
181
191
 
182
192
  console.log(chalk.green.bold('\nInstallation complete!\n'));
183
193
  console.log(chalk.cyan('Next steps:'));
184
- console.log(chalk.white(' 1. Review AGENTS.MD for generic AI assistant guide'));
194
+ console.log(chalk.white(' 1. Review instructions/source/core.md (canonical AI guide)'));
185
195
  console.log(chalk.white(' 2. Review agent-docs/ARCHITECTURE.md for project guidelines'));
186
- console.log(chalk.white(' 3. Review AGENTS.MD for AI assistant guide'));
196
+ console.log(chalk.white(' 3. Review .github/instructions/ for generated tool-compatible files'));
187
197
  console.log(chalk.white(' 4. Configure your AI assistant (Cursor, Copilot, etc.)'));
188
198
  console.log(chalk.white(' 5. Adapt the rules to your technology stack\n'));
189
199
 
@@ -231,7 +241,7 @@ program
231
241
  { name: 'Documentation (agent-docs/)', value: 'docs' },
232
242
  { name: 'Agent Rules (security, testing, database, etc.)', value: 'rules' },
233
243
  { name: 'Skills (reusable agent capabilities)', value: 'skills' },
234
- { name: 'AI Agent instructions (Cursor, Copilot, VSCode, Gemini)', value: 'github' }
244
+ { name: 'AI Agent instructions (Cursor, Copilot, Claude, Generic AGENTS)', value: 'github' }
235
245
  ],
236
246
  validate: (answer) => {
237
247
  if (answer.length === 0) {
@@ -267,7 +277,7 @@ program
267
277
  { name: 'Documentation (agent-docs/)', value: 'docs', checked: true },
268
278
  { name: 'Agent Rules (security, testing, database, etc.)', value: 'rules', checked: true },
269
279
  { name: 'Skills (reusable agent capabilities)', value: 'skills', checked: true },
270
- { name: 'AI Agent instructions (Cursor, Copilot, VSCode, Gemini)', value: 'github', checked: true }
280
+ { name: 'AI Agent instructions (Cursor, Copilot, Claude, Generic AGENTS)', value: 'github', checked: true }
271
281
  ],
272
282
  validate: (answer) => {
273
283
  if (answer.length === 0) {
@@ -302,15 +312,16 @@ program
302
312
  const targetDocsDir = path.join(targetDir, 'agent-docs');
303
313
  await fs.ensureDir(targetDocsDir);
304
314
  await copyDirectory(sourceDocsDir, targetDocsDir, options.force);
315
+ await copyFiles(templateDir, targetDir, [CORE_SOURCE_REL_PATH], options.force);
305
316
  }
306
317
 
307
318
  // Install agent rules
308
319
  if (options.rules) {
309
320
  console.log(chalk.yellow('Installing agent rules...'));
310
- await fs.ensureDir(path.join(targetDir, 'agents', 'rules'));
321
+ await fs.ensureDir(path.join(targetDir, LAYOUT.canonical.rulesDir));
311
322
  await copyDirectory(
312
323
  path.join(templateDir, 'agents', 'rules'),
313
- path.join(targetDir, 'agents', 'rules'),
324
+ path.join(targetDir, LAYOUT.canonical.rulesDir),
314
325
  options.force
315
326
  );
316
327
  }
@@ -318,40 +329,34 @@ program
318
329
  // Install skills
319
330
  if (options.skills) {
320
331
  console.log(chalk.yellow('Installing skills...'));
321
- await fs.ensureDir(path.join(targetDir, 'agents', 'skills'));
332
+ await fs.ensureDir(path.join(targetDir, LAYOUT.canonical.skillsDir));
322
333
  await copyDirectory(
323
334
  path.join(templateDir, 'agents', 'skills'),
324
- path.join(targetDir, 'agents', 'skills'),
335
+ path.join(targetDir, LAYOUT.canonical.skillsDir),
325
336
  options.force
326
337
  );
327
338
  }
328
339
 
329
- // Install AI Agent instructions (Cursor, Copilot, VSCode, Gemini)
340
+ // Install AI Agent instructions (Cursor, Copilot, Claude, Generic AGENTS)
330
341
  if (options.github) {
331
342
  console.log(chalk.yellow('Installing AI agent instructions...'));
332
- await fs.ensureDir(path.join(targetDir, '.github'));
333
- await copyFiles(templateDir, targetDir, [
334
- '.cursorrules',
335
- '.github/copilot-instructions.md',
336
- 'AGENTS.MD',
337
- 'CLAUDE.md',
338
- 'GEMINI.md'
339
- ], options.force);
343
+ await fs.ensureDir(path.join(targetDir, '.github', 'instructions'));
344
+ await copyFiles(templateDir, targetDir, ['.cursorrules'], options.force);
345
+ await writeGeneratedInstructions(targetDir, templateDir, options.force);
340
346
  console.log(chalk.gray(' ✓ Cursor (.cursorrules)'));
341
- console.log(chalk.gray(' ✓ GitHub Copilot (.github/copilot-instructions.md)'));
342
- console.log(chalk.gray(' ✓ Generic AI (AGENTS.MD)'));
343
- console.log(chalk.gray(' ✓ Claude (CLAUDE.md)'));
344
- console.log(chalk.gray(' ✓ Google Gemini (GEMINI.md)'));
347
+ console.log(chalk.gray(' ✓ GitHub Copilot (.github/copilot-instructions.md shim)'));
348
+ console.log(chalk.gray(' ✓ Claude (.claude/CLAUDE.md shim)'));
349
+ console.log(chalk.gray(' ✓ Generic AGENTS (AGENTS.MD shim + canonical .github/instructions/AGENTS.md)'));
345
350
  }
346
351
 
347
352
  // Show summary and next steps
348
353
  console.log(chalk.green.bold('\n✅ Installation complete!\n'));
349
354
 
350
355
  console.log(chalk.cyan('\n📚 Next Steps:\n'));
351
- console.log(chalk.white(' 1. Review AGENTS.MD for AI assistant guide'));
356
+ console.log(chalk.white(' 1. Review instructions/source/core.md (canonical AI guide)'));
352
357
  console.log(chalk.white(' 2. Review agent-docs/ARCHITECTURE.md for project guidelines'));
353
- console.log(chalk.white(' 3. Review AGENTS.MD for AI assistant guide'));
354
- console.log(chalk.white(' 4. Customize agents/rules/*.mdc for your tech stack'));
358
+ console.log(chalk.white(' 3. Review .github/instructions/ for generated tool-compatible files'));
359
+ console.log(chalk.white(' 4. Customize .github/instructions/rules/*.mdc for your tech stack'));
355
360
 
356
361
  console.log(chalk.cyan('\n🔒 Security Reminder:\n'));
357
362
  console.log(chalk.white(' • Review agents/rules/security.mdc'));
@@ -371,9 +376,9 @@ program
371
376
  .action(() => {
372
377
  console.log(chalk.blue.bold('\nAvailable Components:\n'));
373
378
  console.log(chalk.yellow('docs') + ' - Documentation files (agent-docs/ directory)');
374
- console.log(chalk.yellow('rules') + ' - Agent rules (core, database, frontend, security, testing, style)');
375
- console.log(chalk.yellow('skills') + ' - Agent skills (find-skills, ui-ux-pro-max)');
376
- console.log(chalk.yellow('github') + ' - AI Agent instructions (Cursor, Copilot, VSCode, Gemini)');
379
+ console.log(chalk.yellow('rules') + ' - Agent rules (.github/instructions/rules/*.mdc)');
380
+ console.log(chalk.yellow('skills') + ' - Agent skills (.github/skills/*)');
381
+ console.log(chalk.yellow('github') + ' - AI Agent instructions (Cursor, Copilot, Claude, Generic AGENTS)');
377
382
  console.log(chalk.yellow('all') + ' - All components');
378
383
 
379
384
  console.log(chalk.blue.bold('\n\nAvailable Presets:\n'));
@@ -398,13 +403,12 @@ program
398
403
  let warnings = [];
399
404
  let passed = [];
400
405
 
401
- // Check documentation files
402
- if (await fs.pathExists(path.join(targetDir, 'AGENTS.MD'))) {
403
- passed.push(`✓ AGENTS.MD found`);
404
- } else if (await fs.pathExists(path.join(targetDir, 'AGENTS.md'))) {
405
- passed.push(`✓ AGENTS.md found (legacy filename)`);
406
+ // Check canonical source file
407
+ const coreSourcePath = path.join(targetDir, CORE_SOURCE_REL_PATH);
408
+ if (await fs.pathExists(coreSourcePath)) {
409
+ passed.push(`✓ ${CORE_SOURCE_REL_PATH} found`);
406
410
  } else {
407
- warnings.push(`⚠ AGENTS.MD missing - run 'agents-templated init --docs'`);
411
+ warnings.push(`⚠ ${CORE_SOURCE_REL_PATH} missing - run 'agents-templated init --docs'`);
408
412
  }
409
413
 
410
414
  const docFiles = ['ARCHITECTURE.md'];
@@ -424,32 +428,64 @@ program
424
428
 
425
429
  // Check agent rules
426
430
  const ruleFiles = ['core.mdc', 'security.mdc', 'testing.mdc', 'frontend.mdc', 'database.mdc', 'style.mdc'];
427
- const rulesDir = path.join(targetDir, 'agents', 'rules');
428
-
431
+ const canonicalRulesDir = path.join(targetDir, LAYOUT.canonical.rulesDir);
432
+ const legacyRulesDir = path.join(targetDir, LAYOUT.legacy.rulesDirs[0]);
433
+ const rulesDir = path.join(targetDir, resolveRulesDir(targetDir));
434
+
435
+ if (!(await fs.pathExists(canonicalRulesDir)) && await fs.pathExists(legacyRulesDir)) {
436
+ issues.push(`✗ Legacy rules layout detected at ${LAYOUT.legacy.rulesDirs[0]} - run 'agents-templated update --all' to migrate`);
437
+ }
438
+
429
439
  if (await fs.pathExists(rulesDir)) {
440
+ const relativeRulesDir = path.relative(targetDir, rulesDir) || LAYOUT.canonical.rulesDir;
430
441
  for (const file of ruleFiles) {
431
442
  if (await fs.pathExists(path.join(rulesDir, file))) {
432
- passed.push(`✓ agents/rules/${file} found`);
443
+ passed.push(`✓ ${relativeRulesDir}/${file} found`);
433
444
  } else {
434
- warnings.push(`⚠ agents/rules/${file} missing`);
445
+ warnings.push(`⚠ ${relativeRulesDir}/${file} missing`);
435
446
  }
436
447
  }
437
448
  } else {
438
- warnings.push(`⚠ agents/rules directory missing - run 'agents-templated init --rules'`);
449
+ warnings.push(`⚠ ${LAYOUT.canonical.rulesDir} directory missing - run 'agents-templated init --rules'`);
439
450
  }
440
451
 
441
452
  // Check skills
442
- const skillsDir = path.join(targetDir, 'agents', 'skills');
453
+ const canonicalSkillsDir = path.join(targetDir, LAYOUT.canonical.skillsDir);
454
+ const legacySkillsDir = path.join(targetDir, LAYOUT.legacy.skillsDirs[0]);
455
+ const skillsDir = path.join(targetDir, resolveSkillsDir(targetDir));
456
+
457
+ if (!(await fs.pathExists(canonicalSkillsDir)) && await fs.pathExists(legacySkillsDir)) {
458
+ issues.push(`✗ Legacy skills layout detected at ${LAYOUT.legacy.skillsDirs[0]} - run 'agents-templated update --all' to migrate`);
459
+ }
460
+
443
461
  if (await fs.pathExists(skillsDir)) {
444
462
  const skills = await fs.readdir(skillsDir);
445
- passed.push(`✓ ${skills.length} skills installed`);
463
+ const relativeSkillsDir = path.relative(targetDir, skillsDir) || LAYOUT.canonical.skillsDir;
464
+ passed.push(`✓ ${skills.length} skills installed in ${relativeSkillsDir}`);
446
465
  } else {
447
- warnings.push(`⚠ agents/skills directory missing - run 'agents-templated init --skills'`);
466
+ warnings.push(`⚠ ${LAYOUT.canonical.skillsDir} directory missing - run 'agents-templated init --skills'`);
467
+ }
468
+
469
+ // Check generated instruction files and drift
470
+ const hasInstructionFootprint =
471
+ await fs.pathExists(path.join(targetDir, '.github', 'instructions')) ||
472
+ await fs.pathExists(path.join(targetDir, GENERATED_INSTRUCTION_PATHS.compatibility.claude)) ||
473
+ await fs.pathExists(path.join(targetDir, GENERATED_INSTRUCTION_PATHS.compatibility.copilot)) ||
474
+ await fs.pathExists(path.join(targetDir, GENERATED_INSTRUCTION_PATHS.compatibility.generic));
475
+
476
+ if (hasInstructionFootprint) {
477
+ const instructionDrift = await validateInstructionDrift(targetDir);
478
+ if (instructionDrift.missingCore) {
479
+ issues.push(`✗ Canonical instruction source missing - run 'agents-templated init --docs --github'`);
480
+ } else if (!instructionDrift.ok) {
481
+ issues.push(`✗ Generated instruction files are out of sync: ${instructionDrift.driftFiles.join(', ')}`);
482
+ } else {
483
+ passed.push('✓ Generated instruction files are in sync with canonical source');
484
+ }
448
485
  }
449
486
 
450
- // Check GitHub Copilot config
451
- const copilotFile = path.join(targetDir, '.github', 'copilot-instructions.md');
452
- if (await fs.pathExists(copilotFile)) {
487
+ const compatCopilotFile = path.join(targetDir, GENERATED_INSTRUCTION_PATHS.compatibility.copilot);
488
+ if (await fs.pathExists(compatCopilotFile)) {
453
489
  passed.push(`✓ GitHub Copilot configuration found`);
454
490
  } else {
455
491
  warnings.push(`⚠ GitHub Copilot configuration missing - run 'agents-templated init --github'`);
@@ -586,9 +622,21 @@ async function copyDirectory(sourceDir, targetDir, force = false) {
586
622
  }
587
623
 
588
624
  async function hasInstalledTemplates(targetDir) {
589
- return await fs.pathExists(path.join(targetDir, 'AGENTS.MD')) ||
590
- await fs.pathExists(path.join(targetDir, 'AGENTS.md')) ||
591
- await fs.pathExists(path.join(targetDir, 'agents'));
625
+ return await hasAnyLayout(targetDir) ||
626
+ await fs.pathExists(path.join(targetDir, CORE_SOURCE_REL_PATH)) ||
627
+ await fs.pathExists(path.join(targetDir, GENERATED_INSTRUCTION_PATHS.compatibility.generic));
628
+ }
629
+
630
+ async function cleanupLegacyInstructionFiles(targetDir) {
631
+ const legacyFiles = ['CLAUDE.md', 'GEMINI.md'];
632
+
633
+ for (const file of legacyFiles) {
634
+ const filePath = path.join(targetDir, file);
635
+ if (await fs.pathExists(filePath)) {
636
+ await fs.remove(filePath);
637
+ console.log(chalk.green(` ✓ Removed legacy file: ${file}`));
638
+ }
639
+ }
592
640
  }
593
641
 
594
642
  async function updateSelectedComponents(targetDir, templateDir, selectedComponents, overwrite = true) {
@@ -604,38 +652,60 @@ async function updateSelectedComponents(targetDir, templateDir, selectedComponen
604
652
  path.join(targetDir, 'agent-docs'),
605
653
  overwrite
606
654
  );
655
+ await copyFiles(templateDir, targetDir, [CORE_SOURCE_REL_PATH], overwrite);
607
656
  }
608
657
 
609
658
  if (components.includes('rules')) {
610
659
  console.log(chalk.yellow('Updating agent rules...'));
611
- await fs.ensureDir(path.join(targetDir, 'agents', 'rules'));
660
+ await fs.ensureDir(path.join(targetDir, LAYOUT.canonical.rulesDir));
612
661
  await copyDirectory(
613
662
  path.join(templateDir, 'agents', 'rules'),
614
- path.join(targetDir, 'agents', 'rules'),
663
+ path.join(targetDir, LAYOUT.canonical.rulesDir),
615
664
  overwrite
616
665
  );
617
666
  }
618
667
 
619
668
  if (components.includes('skills')) {
620
669
  console.log(chalk.yellow('Updating skills...'));
621
- await fs.ensureDir(path.join(targetDir, 'agents', 'skills'));
670
+ await fs.ensureDir(path.join(targetDir, LAYOUT.canonical.skillsDir));
622
671
  await copyDirectory(
623
672
  path.join(templateDir, 'agents', 'skills'),
624
- path.join(targetDir, 'agents', 'skills'),
673
+ path.join(targetDir, LAYOUT.canonical.skillsDir),
625
674
  overwrite
626
675
  );
627
676
  }
628
677
 
629
678
  if (components.includes('github')) {
630
679
  console.log(chalk.yellow('Updating AI agent instructions...'));
631
- await fs.ensureDir(path.join(targetDir, '.github'));
632
- await copyFiles(templateDir, targetDir, [
633
- '.cursorrules',
634
- '.github/copilot-instructions.md',
635
- 'AGENTS.MD',
636
- 'CLAUDE.md',
637
- 'GEMINI.md'
638
- ], overwrite);
680
+ await fs.ensureDir(path.join(targetDir, '.github', 'instructions'));
681
+ await copyFiles(templateDir, targetDir, ['.cursorrules'], overwrite);
682
+ await writeGeneratedInstructions(targetDir, templateDir, overwrite);
683
+ await cleanupLegacyInstructionFiles(targetDir);
684
+ }
685
+
686
+ if ((components.includes('docs') || components.includes('github')) && !components.includes('github')) {
687
+ await writeGeneratedInstructions(targetDir, templateDir, overwrite);
688
+ }
689
+ }
690
+
691
+ async function applyLegacyMigrationPlan(targetDir, migrationPlan, overwrite = true) {
692
+ for (const move of migrationPlan) {
693
+ const sourcePath = path.join(targetDir, move.source);
694
+ const targetPath = path.join(targetDir, move.target);
695
+
696
+ if (!(await fs.pathExists(sourcePath))) {
697
+ continue;
698
+ }
699
+
700
+ await fs.ensureDir(path.dirname(targetPath));
701
+
702
+ if (await fs.pathExists(targetPath)) {
703
+ await copyDirectory(sourcePath, targetPath, overwrite);
704
+ await fs.remove(sourcePath);
705
+ continue;
706
+ }
707
+
708
+ await fs.move(sourcePath, targetPath, { overwrite });
639
709
  }
640
710
  }
641
711
 
@@ -665,6 +735,38 @@ program
665
735
  process.exit(0);
666
736
  }
667
737
 
738
+ const migrationPlan = await getLegacyMigrationPlan(targetDir);
739
+ if (migrationPlan.length > 0) {
740
+ console.log(chalk.yellow('Legacy layout detected. Migration to canonical Copilot-style paths is required.\n'));
741
+ migrationPlan.forEach(({ source, target }) => {
742
+ console.log(chalk.white(` ${source} -> ${target}`));
743
+ });
744
+ console.log('');
745
+
746
+ if (options.checkOnly) {
747
+ console.log(chalk.red('Migration required before validation can pass.'));
748
+ console.log(chalk.gray('Run "agents-templated update" and confirm migration.\n'));
749
+ process.exit(1);
750
+ }
751
+
752
+ const migrationAnswer = await inquirer.prompt([
753
+ {
754
+ type: 'confirm',
755
+ name: 'proceed',
756
+ message: 'Migrate legacy directories now?',
757
+ default: true
758
+ }
759
+ ]);
760
+
761
+ if (!migrationAnswer.proceed) {
762
+ console.log(chalk.red('\nMigration skipped. Setup remains non-canonical.\n'));
763
+ process.exit(1);
764
+ }
765
+
766
+ await applyLegacyMigrationPlan(targetDir, migrationPlan, true);
767
+ console.log(chalk.green('✓ Legacy layout migration completed.\n'));
768
+ }
769
+
668
770
  const hasComponentSelection = options.all || options.docs || options.rules || options.skills || options.github;
669
771
 
670
772
  // Component refresh mode: update selected parts directly without stack/wizard prompts
@@ -685,20 +787,16 @@ program
685
787
 
686
788
  // List potential updates
687
789
  const updates = [];
688
- const rootAgentsTargetFile = (await fs.pathExists(path.join(targetDir, 'AGENTS.MD')))
689
- ? 'AGENTS.MD'
690
- : ((await fs.pathExists(path.join(targetDir, 'AGENTS.md'))) ? 'AGENTS.md' : 'AGENTS.MD');
691
-
692
790
  const checkFiles = [
693
- { targetFile: rootAgentsTargetFile, templateFile: 'AGENTS.MD', component: 'root' },
791
+ { targetFile: CORE_SOURCE_REL_PATH, templateFile: CORE_SOURCE_REL_PATH, component: 'root' },
694
792
  { targetFile: 'agent-docs/ARCHITECTURE.md', templateFile: 'agent-docs/ARCHITECTURE.md', component: 'docs' },
695
- { targetFile: 'agents/rules/security.mdc', templateFile: 'agents/rules/security.mdc', component: 'rules' },
696
- { targetFile: 'agents/rules/testing.mdc', templateFile: 'agents/rules/testing.mdc', component: 'rules' },
697
- { targetFile: 'agents/rules/core.mdc', templateFile: 'agents/rules/core.mdc', component: 'rules' },
698
- { targetFile: 'agents/skills/README.md', templateFile: 'agents/skills/README.md', component: 'skills' },
699
- { targetFile: 'agents/skills/find-skills/SKILL.md', templateFile: 'agents/skills/find-skills/SKILL.md', component: 'skills' },
700
- { targetFile: 'agents/skills/ui-ux-pro-max/SKILL.md', templateFile: 'agents/skills/ui-ux-pro-max/SKILL.md', component: 'skills' },
701
- { targetFile: '.github/copilot-instructions.md', templateFile: '.github/copilot-instructions.md', component: 'github' }
793
+ { targetFile: `${LAYOUT.canonical.rulesDir}/security.mdc`, templateFile: 'agents/rules/security.mdc', component: 'rules' },
794
+ { targetFile: `${LAYOUT.canonical.rulesDir}/testing.mdc`, templateFile: 'agents/rules/testing.mdc', component: 'rules' },
795
+ { targetFile: `${LAYOUT.canonical.rulesDir}/core.mdc`, templateFile: 'agents/rules/core.mdc', component: 'rules' },
796
+ { targetFile: `${LAYOUT.canonical.skillsDir}/README.md`, templateFile: 'agents/skills/README.md', component: 'skills' },
797
+ { targetFile: `${LAYOUT.canonical.skillsDir}/find-skills/SKILL.md`, templateFile: 'agents/skills/find-skills/SKILL.md', component: 'skills' },
798
+ { targetFile: `${LAYOUT.canonical.skillsDir}/ui-ux-pro-max/SKILL.md`, templateFile: 'agents/skills/ui-ux-pro-max/SKILL.md', component: 'skills' },
799
+ { targetFile: '.cursorrules', templateFile: '.cursorrules', component: 'github' }
702
800
  ];
703
801
 
704
802
  for (const {targetFile, templateFile, component} of checkFiles) {
@@ -763,6 +861,10 @@ program
763
861
  console.log(chalk.green(` ✓ Updated: ${targetFile}`));
764
862
  }
765
863
 
864
+ await writeGeneratedInstructions(targetDir, templateDir, true);
865
+ console.log(chalk.green(' ✓ Regenerated instruction compatibility files'));
866
+ await cleanupLegacyInstructionFiles(targetDir);
867
+
766
868
  console.log(chalk.green.bold('\n✅ Updates applied successfully!\n'));
767
869
  console.log(chalk.gray('Backup files created with .backup extension\n'));
768
870
 
@@ -850,7 +952,7 @@ program
850
952
  console.log(chalk.blue('\n📚 Quick Tips:\n'));
851
953
  console.log(chalk.white(' • Run "agents-templated validate" to check setup'));
852
954
  console.log(chalk.white(' • Run "agents-templated wizard" for guided setup'));
853
- console.log(chalk.white(' • Review agents/rules/security.mdc for security patterns\n'));
955
+ console.log(chalk.white(' • Review .github/instructions/rules/security.mdc for security patterns\n'));
854
956
 
855
957
  } catch (error) {
856
958
  console.error(chalk.red('Error:'), error.message);
package/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  const fs = require('fs-extra');
2
2
  const path = require('path');
3
+ const { LAYOUT } = require('./lib/layout');
4
+ const { CORE_SOURCE_REL_PATH, writeGeneratedInstructions } = require('./lib/instructions');
3
5
 
4
6
  /**
5
7
  * Programmatic API for agents-templated
@@ -26,9 +28,9 @@ async function install(targetDir, options = {}) {
26
28
  // Documentation files
27
29
  if (installAll || options.docs) {
28
30
  files.push(
29
- 'AGENTS.md',
30
31
  'agent-docs/ARCHITECTURE.md',
31
- 'agent-docs/README.md'
32
+ 'agent-docs/README.md',
33
+ CORE_SOURCE_REL_PATH
32
34
  );
33
35
  }
34
36
 
@@ -49,51 +51,35 @@ async function install(targetDir, options = {}) {
49
51
 
50
52
  // Agent rules
51
53
  if (installAll || options.rules) {
52
- await fs.ensureDir(path.join(targetDir, 'agents', 'rules'));
54
+ await fs.ensureDir(path.join(targetDir, LAYOUT.canonical.rulesDir));
53
55
  await copyDirectory(
54
56
  path.join(templateDir, 'agents', 'rules'),
55
- path.join(targetDir, 'agents', 'rules'),
57
+ path.join(targetDir, LAYOUT.canonical.rulesDir),
56
58
  options.force
57
59
  );
58
60
  }
59
61
 
60
62
  // Skills
61
63
  if (installAll || options.skills) {
62
- await fs.ensureDir(path.join(targetDir, 'agents', 'skills'));
64
+ await fs.ensureDir(path.join(targetDir, LAYOUT.canonical.skillsDir));
63
65
  await copyDirectory(
64
66
  path.join(templateDir, 'agents', 'skills'),
65
- path.join(targetDir, 'agents', 'skills'),
67
+ path.join(targetDir, LAYOUT.canonical.skillsDir),
66
68
  options.force
67
69
  );
68
70
  }
69
71
 
70
- // AI Agent instructions (Cursor, Copilot, Claude, Gemini)
72
+ // AI Agent instructions (Cursor, Copilot, Claude)
71
73
  if (installAll || options.github) {
72
- await fs.ensureDir(path.join(targetDir, '.github'));
73
-
74
- // Copy all AI agent config files
75
- const agentConfigs = [
76
- '.cursorrules',
77
- 'CLAUDE.md',
78
- 'GEMINI.md'
79
- ];
80
-
81
- for (const config of agentConfigs) {
82
- const sourcePath = path.join(templateDir, config);
83
- const targetPath = path.join(targetDir, config);
84
-
85
- if (await fs.pathExists(sourcePath)) {
86
- await fs.copy(sourcePath, targetPath, { overwrite: options.force });
87
- }
88
- }
89
-
90
- // Copy GitHub Copilot instructions
91
- const sourceGithubPath = path.join(templateDir, '.github', 'copilot-instructions.md');
92
- const targetGithubPath = path.join(targetDir, '.github', 'copilot-instructions.md');
93
-
94
- if (await fs.pathExists(sourceGithubPath)) {
95
- await fs.copy(sourceGithubPath, targetGithubPath, { overwrite: options.force });
74
+ await fs.ensureDir(path.join(targetDir, '.github', 'instructions'));
75
+
76
+ const cursorSource = path.join(templateDir, '.cursorrules');
77
+ const cursorTarget = path.join(targetDir, '.cursorrules');
78
+ if (await fs.pathExists(cursorSource)) {
79
+ await fs.copy(cursorSource, cursorTarget, { overwrite: options.force });
96
80
  }
81
+
82
+ await writeGeneratedInstructions(targetDir, templateDir, options.force);
97
83
  }
98
84
  }
99
85
 
@@ -0,0 +1,145 @@
1
+ const path = require('path');
2
+ const fs = require('fs-extra');
3
+
4
+ const CORE_SOURCE_REL_PATH = 'instructions/source/core.md';
5
+
6
+ const GENERATED_INSTRUCTION_PATHS = {
7
+ canonical: {
8
+ generic: '.github/instructions/AGENTS.md'
9
+ },
10
+ compatibility: {
11
+ generic: 'AGENTS.MD',
12
+ copilot: '.github/copilot-instructions.md',
13
+ claude: '.claude/CLAUDE.md'
14
+ }
15
+ };
16
+
17
+ function getLegacyCoreCandidates() {
18
+ return ['AGENTS.MD', 'AGENTS.md'];
19
+ }
20
+
21
+ function buildHeaders(toolName) {
22
+ return [
23
+ '<!-- GENERATED FILE - DO NOT EDIT DIRECTLY -->',
24
+ `<!-- Source of truth: ${CORE_SOURCE_REL_PATH} -->`,
25
+ `<!-- Tool profile: ${toolName} -->`,
26
+ ''
27
+ ].join('\n');
28
+ }
29
+
30
+ function buildCompatInstruction(toolName, corePath) {
31
+ const titles = {
32
+ generic: '# AGENTS Instructions',
33
+ copilot: '# GitHub Copilot Instructions',
34
+ claude: '# Claude Instructions'
35
+ };
36
+
37
+ return [
38
+ `${titles[toolName]}`,
39
+ '',
40
+ `Primary policy source: \`${corePath}\`.`,
41
+ 'Minimal compatibility stub to reduce duplicated prompt tokens.',
42
+ 'Load rules from the canonical source file above.',
43
+ ''
44
+ ].join('\n');
45
+ }
46
+
47
+ function buildGeneratedArtifacts(coreContent) {
48
+ const corePath = CORE_SOURCE_REL_PATH;
49
+ const files = {};
50
+
51
+ files[GENERATED_INSTRUCTION_PATHS.canonical.generic] = `${buildHeaders('generic')}${coreContent.trim()}\n`;
52
+ files[GENERATED_INSTRUCTION_PATHS.compatibility.generic] = `${buildHeaders('generic-compat')}${buildCompatInstruction('generic', corePath)}`;
53
+ files[GENERATED_INSTRUCTION_PATHS.compatibility.copilot] = `${buildHeaders('copilot-compat')}${buildCompatInstruction('copilot', corePath)}`;
54
+ files[GENERATED_INSTRUCTION_PATHS.compatibility.claude] = `${buildHeaders('claude-compat')}${buildCompatInstruction('claude', corePath)}`;
55
+
56
+ return files;
57
+ }
58
+
59
+ async function resolveCoreContent(targetDir, templateDir) {
60
+ const canonicalPath = path.join(targetDir, CORE_SOURCE_REL_PATH);
61
+ if (await fs.pathExists(canonicalPath)) {
62
+ return fs.readFile(canonicalPath, 'utf8');
63
+ }
64
+
65
+ for (const legacyFile of getLegacyCoreCandidates()) {
66
+ const legacyPath = path.join(targetDir, legacyFile);
67
+ if (await fs.pathExists(legacyPath)) {
68
+ return fs.readFile(legacyPath, 'utf8');
69
+ }
70
+ }
71
+
72
+ const templateCorePath = path.join(templateDir, CORE_SOURCE_REL_PATH);
73
+ return fs.readFile(templateCorePath, 'utf8');
74
+ }
75
+
76
+ async function ensureCoreSource(targetDir, templateDir, force = false) {
77
+ const targetCorePath = path.join(targetDir, CORE_SOURCE_REL_PATH);
78
+
79
+ if (await fs.pathExists(targetCorePath) && !force) {
80
+ return;
81
+ }
82
+
83
+ const coreContent = await resolveCoreContent(targetDir, templateDir);
84
+ await fs.ensureDir(path.dirname(targetCorePath));
85
+ await fs.writeFile(targetCorePath, coreContent, 'utf8');
86
+ }
87
+
88
+ async function writeGeneratedInstructions(targetDir, templateDir, force = false) {
89
+ await ensureCoreSource(targetDir, templateDir, force);
90
+ const corePath = path.join(targetDir, CORE_SOURCE_REL_PATH);
91
+ const coreContent = await fs.readFile(corePath, 'utf8');
92
+ const artifacts = buildGeneratedArtifacts(coreContent);
93
+
94
+ for (const [relPath, content] of Object.entries(artifacts)) {
95
+ const targetPath = path.join(targetDir, relPath);
96
+
97
+ if (await fs.pathExists(targetPath) && !force) {
98
+ continue;
99
+ }
100
+
101
+ await fs.ensureDir(path.dirname(targetPath));
102
+ await fs.writeFile(targetPath, content, 'utf8');
103
+ }
104
+ }
105
+
106
+ async function validateInstructionDrift(targetDir) {
107
+ const corePath = path.join(targetDir, CORE_SOURCE_REL_PATH);
108
+ if (!(await fs.pathExists(corePath))) {
109
+ return {
110
+ ok: false,
111
+ missingCore: true,
112
+ driftFiles: []
113
+ };
114
+ }
115
+
116
+ const coreContent = await fs.readFile(corePath, 'utf8');
117
+ const expected = buildGeneratedArtifacts(coreContent);
118
+ const driftFiles = [];
119
+
120
+ for (const [relPath, expectedContent] of Object.entries(expected)) {
121
+ const filePath = path.join(targetDir, relPath);
122
+ if (!(await fs.pathExists(filePath))) {
123
+ driftFiles.push(relPath);
124
+ continue;
125
+ }
126
+
127
+ const actual = await fs.readFile(filePath, 'utf8');
128
+ if (actual !== expectedContent) {
129
+ driftFiles.push(relPath);
130
+ }
131
+ }
132
+
133
+ return {
134
+ ok: driftFiles.length === 0,
135
+ missingCore: false,
136
+ driftFiles
137
+ };
138
+ }
139
+
140
+ module.exports = {
141
+ CORE_SOURCE_REL_PATH,
142
+ GENERATED_INSTRUCTION_PATHS,
143
+ writeGeneratedInstructions,
144
+ validateInstructionDrift
145
+ };
package/lib/layout.js ADDED
@@ -0,0 +1,95 @@
1
+ const path = require('path');
2
+ const fs = require('fs-extra');
3
+
4
+ const LAYOUT = {
5
+ canonical: {
6
+ docsDir: 'agent-docs',
7
+ rulesDir: '.github/instructions/rules',
8
+ skillsDir: '.github/skills'
9
+ },
10
+ legacy: {
11
+ rulesDirs: ['agents/rules'],
12
+ skillsDirs: ['agents/skills']
13
+ },
14
+ compatible: {
15
+ rulesDirs: ['.claude/rules', '.github/instructions'],
16
+ skillsDirs: ['.claude/skills', '.agents/skills']
17
+ }
18
+ };
19
+
20
+ function firstExistingPath(baseDir, relativePaths) {
21
+ return relativePaths.find((relPath) => fs.existsSync(path.join(baseDir, relPath))) || null;
22
+ }
23
+
24
+ function resolveRulesDir(baseDir) {
25
+ const candidates = [
26
+ LAYOUT.canonical.rulesDir,
27
+ ...LAYOUT.compatible.rulesDirs,
28
+ ...LAYOUT.legacy.rulesDirs
29
+ ];
30
+ return firstExistingPath(baseDir, candidates) || LAYOUT.canonical.rulesDir;
31
+ }
32
+
33
+ function resolveSkillsDir(baseDir) {
34
+ const candidates = [
35
+ LAYOUT.canonical.skillsDir,
36
+ ...LAYOUT.compatible.skillsDirs,
37
+ ...LAYOUT.legacy.skillsDirs
38
+ ];
39
+ return firstExistingPath(baseDir, candidates) || LAYOUT.canonical.skillsDir;
40
+ }
41
+
42
+ async function hasAnyLayout(baseDir) {
43
+ const checks = [
44
+ path.join(baseDir, LAYOUT.canonical.rulesDir),
45
+ path.join(baseDir, LAYOUT.canonical.skillsDir),
46
+ ...LAYOUT.compatible.rulesDirs.map((relPath) => path.join(baseDir, relPath)),
47
+ ...LAYOUT.compatible.skillsDirs.map((relPath) => path.join(baseDir, relPath)),
48
+ ...LAYOUT.legacy.rulesDirs.map((relPath) => path.join(baseDir, relPath)),
49
+ ...LAYOUT.legacy.skillsDirs.map((relPath) => path.join(baseDir, relPath))
50
+ ];
51
+
52
+ for (const checkPath of checks) {
53
+ if (await fs.pathExists(checkPath)) {
54
+ return true;
55
+ }
56
+ }
57
+
58
+ return false;
59
+ }
60
+
61
+ async function getLegacyMigrationPlan(baseDir) {
62
+ const plan = [];
63
+
64
+ for (const relPath of LAYOUT.legacy.rulesDirs) {
65
+ const from = path.join(baseDir, relPath);
66
+ if (await fs.pathExists(from)) {
67
+ plan.push({
68
+ type: 'directory',
69
+ source: relPath,
70
+ target: LAYOUT.canonical.rulesDir
71
+ });
72
+ }
73
+ }
74
+
75
+ for (const relPath of LAYOUT.legacy.skillsDirs) {
76
+ const from = path.join(baseDir, relPath);
77
+ if (await fs.pathExists(from)) {
78
+ plan.push({
79
+ type: 'directory',
80
+ source: relPath,
81
+ target: LAYOUT.canonical.skillsDir
82
+ });
83
+ }
84
+ }
85
+
86
+ return plan;
87
+ }
88
+
89
+ module.exports = {
90
+ LAYOUT,
91
+ resolveRulesDir,
92
+ resolveSkillsDir,
93
+ hasAnyLayout,
94
+ getLegacyMigrationPlan
95
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents-templated",
3
- "version": "1.2.10",
3
+ "version": "1.2.12",
4
4
  "description": "Technology-agnostic development template with multi-AI agent support (Cursor, Copilot, VSCode, Gemini), security-first patterns, and comprehensive testing guidelines",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -36,6 +36,7 @@
36
36
  },
37
37
  "files": [
38
38
  "bin",
39
+ "lib",
39
40
  "templates",
40
41
  "templates/presets",
41
42
  "index.js",
@@ -101,11 +101,11 @@ Agents Templated automatically configures 4 major AI coding assistants:
101
101
  | AI Agent | Config File | Auto-Discovery |
102
102
  |----------|-------------|----------------|
103
103
  | **Cursor** | `.cursorrules` | ✅ Auto-loads in Cursor IDE |
104
- | **GitHub Copilot** | `.github/copilot-instructions.md` | ✅ Auto-loads in VS Code |
105
- | **Claude** | `CLAUDE.md` | ✅ Auto-loads in Claude IDE/API |
106
- | **Gemini** | `GEMINI.md` | ✅ Auto-loads in Gemini IDE/API |
104
+ | **GitHub Copilot** | `.github/instructions/copilot-instructions.md` (+ shim `.github/copilot-instructions.md`) | ✅ Auto-loads in VS Code |
105
+ | **Claude** | `.github/instructions/CLAUDE.md` (+ shim `CLAUDE.md`) | ✅ Compatible |
106
+ | **Gemini** | `.github/instructions/GEMINI.md` (+ shim `GEMINI.md`) | ✅ Compatible |
107
107
 
108
- **All agents follow the same standards:** `agents/rules/` contains behavior rules, and `agents/commands/` contains deterministic slash-command contracts.
108
+ **Single source of truth:** `instructions/source/core.md` drives generated tool-compatible instruction files.
109
109
 
110
110
  ---
111
111
 
@@ -115,20 +115,36 @@ When you run `agents-templated init`, you get:
115
115
 
116
116
  ```
117
117
  your-project/
118
+ ├── instructions/
119
+ │ └── source/
120
+ │ └── core.md # Canonical instruction source of truth
121
+
118
122
  ├── agent-docs/ # 📚 Comprehensive documentation
119
- │ ├── AGENTS.MD # AI assistant guide
120
123
  │ ├── ARCHITECTURE.md # Project architecture & tech stack
121
124
  │ └── README.md # Human-readable setup guide
122
125
 
123
- ├── agents/ # 🤖 AI Agent rules and skills
124
- │ ├── rules/
126
+ ├── .github/
127
+ │ ├── instructions/ # Canonical generated instructions
128
+ │ │ ├── AGENTS.md
129
+ │ │ ├── copilot-instructions.md
130
+ │ │ ├── CLAUDE.md
131
+ │ │ ├── GEMINI.md
132
+ │ │ └── rules/
125
133
  │ │ ├── core.mdc # Core development principles
126
134
  │ │ ├── security.mdc # Security patterns (CRITICAL)
127
135
  │ │ ├── testing.mdc # Testing strategy
128
136
  │ │ ├── frontend.mdc # Frontend patterns
129
137
  │ │ ├── database.mdc # Database patterns
130
138
  │ │ └── style.mdc # Code style guidelines
131
- │ ├── commands/
139
+ │ ├── skills/
140
+ │ │ ├── find-skills/ # Skill discovery helper
141
+ │ │ ├── ui-ux-pro-max/ # Advanced UI/UX design implementation skill
142
+ │ │ ├── README.md # Guide for creating custom skills
143
+ │ │ └── [your-custom-skills]/ # Your project-specific skills
144
+ │ └── copilot-instructions.md # Compatibility shim for Copilot
145
+
146
+ ├── agents/ # 🤖 Deterministic command contracts
147
+ │ └── commands/
132
148
  │ │ ├── SCHEMA.md # Global slash-command response schema
133
149
  │ │ ├── plan.md # /plan contract
134
150
  │ │ ├── fix.md # /fix contract
@@ -136,17 +152,10 @@ your-project/
136
152
  │ │ ├── release.md # /release contract
137
153
  │ │ ├── ... # Other command contracts
138
154
  │ │ └── README.md # Commands directory guide
139
- │ └── skills/
140
- │ ├── find-skills/ # Skill discovery helper
141
- │ ├── ui-ux-pro-max/ # Advanced UI/UX design implementation skill
142
- │ ├── README.md # Guide for creating custom skills
143
- │ └── [your-custom-skills]/ # Your project-specific skills
144
-
145
- ├── .github/
146
- │ └── copilot-instructions.md # GitHub Copilot config
147
155
 
148
- ├── CLAUDE.md # Claude AI config
149
- ├── GEMINI.md # Gemini AI config
156
+ ├── AGENTS.MD # Compatibility shim for generic agents
157
+ ├── CLAUDE.md # Compatibility shim for Claude tooling
158
+ ├── GEMINI.md # Compatibility shim for Gemini tooling
150
159
  ├── .cursorrules # Cursor IDE config
151
160
  ├── .gitignore # Pre-configured Git ignore
152
161
  └── README.md # Project documentation
@@ -0,0 +1,36 @@
1
+ # Canonical AI Instructions
2
+
3
+ This file is the single source of truth for project AI guidance.
4
+
5
+ ## Always Apply
6
+
7
+ 1. Security-first implementation:
8
+ - Validate all external inputs at boundaries.
9
+ - Enforce authentication and authorization on protected operations.
10
+ - Rate limit public endpoints.
11
+ - Never expose sensitive values in logs, errors, or responses.
12
+
13
+ 2. Testing discipline:
14
+ - Add tests for changed business logic.
15
+ - Prefer focused unit tests first, then integration tests for boundaries.
16
+ - Keep critical workflows covered before release.
17
+
18
+ 3. Type safety and reliability:
19
+ - Use strong typing where available.
20
+ - Add runtime validation at trust boundaries.
21
+ - Keep changes minimal, deterministic, and scoped to the requested task.
22
+
23
+ ## Project References
24
+
25
+ - `agent-docs/ARCHITECTURE.md`
26
+ - `agents/rules/security.mdc`
27
+ - `agents/rules/testing.mdc`
28
+ - `agents/rules/core.mdc`
29
+
30
+ ## Operational Rules
31
+
32
+ - Prefer smallest safe change set.
33
+ - Preserve existing APIs unless the task requires breaking changes.
34
+ - Do not commit secrets or credentials.
35
+ - Do not disable security controls to make tests pass.
36
+
@@ -1,142 +0,0 @@
1
- # Google Gemini AI Instructions
2
-
3
- This project uses enterprise-grade, technology-agnostic development patterns for all Google Gemini AI assistants, whether used through:
4
- - Google AI Studio (aistudio.google.com)
5
- - Gemini IDE extensions
6
- - Gemini API integration
7
- - Other Gemini-powered tools
8
-
9
- ## Quick Start
10
-
11
- - **AI Guide**: See `AGENTS.MD` for comprehensive instructions
12
- - **Architecture**: See `agent-docs/ARCHITECTURE.md` for project guidelines
13
- - **Custom Skills**: See `agents/skills/` directory for domain-specific extensions
14
- - **Detailed Rules**: See `agents/rules/*.mdc` files
15
- - **Available Skills**: Check `agents/skills/` for project-specific skills
16
-
17
- ## Core Development Patterns
18
-
19
- Follow these enterprise-grade patterns for all development work:
20
-
21
- ### 1. Security-First Approach
22
- - **Validate all inputs**: Use schema validation for all user inputs and API requests
23
- - **Authentication**: Implement secure session management and authentication flows
24
- - **Authorization**: Apply role-based access control with proper middleware
25
- - **Rate limiting**: Protect public endpoints from abuse with appropriate rate limiting
26
- - **Error handling**: Never expose sensitive data in error messages or logs
27
- - **Database safety**: Use ORM/ODM patterns exclusively, avoid raw SQL queries
28
- - Reference: `agents/rules/security.mdc`
29
-
30
- ### 2. Testing Requirements
31
- - **Unit tests**: Target 80% coverage for business logic
32
- - **Integration tests**: 15% coverage for API and database operations
33
- - **E2E tests**: 5% coverage for critical user journeys
34
- - All business logic must have appropriate test cases
35
- - Reference: `agents/rules/testing.mdc`
36
-
37
- ### 3. Type Safety & Validation
38
- - Use strong typing systems available in your language of choice
39
- - Implement runtime validation at all API boundaries
40
- - Apply schema validation to form inputs and API requests
41
- - Reference: `agents/rules/core.mdc`
42
-
43
- ### 4. Code Quality Standards
44
- - **Readability**: Clear variable names, proper documentation, logical organization
45
- - **Type safety**: Strict typing throughout, no loose type usage
46
- - **Performance**: Monitor resource usage, implement caching, optimize queries
47
- - **Maintainability**: Modular design, separation of concerns, SOLID principles
48
- - **Accessibility**: WCAG 2.1 AA compliance for all user-facing interfaces
49
- - Reference: `agents/rules/style.mdc`
50
-
51
- ## Agent-Based Development
52
-
53
- This project follows an agent-based pattern where different roles handle different aspects:
54
-
55
- | Agent | Responsibility | Reference |
56
- |-------|-----------------|-----------|
57
- | **FrontendAgent** | UI/Design, components, accessibility, responsive layouts | `agents/rules/frontend.mdc` |
58
- | **BackendAgent** | API routes, business logic, authentication, services | `agents/rules/security.mdc` |
59
- | **DatabaseAgent** | Schema design, migrations, data access, optimization | `agents/rules/database.mdc` |
60
- | **TestAgent** | Testing strategy, coverage, test organization | `agents/rules/testing.mdc` |
61
- | **SecurityAgent** | Security patterns, validation, rate limiting, access control | `agents/rules/security.mdc` |
62
- | **ReviewerAgent** | Code quality, performance, accessibility, architecture | All rules |
63
-
64
- When implementing features, identify which agent responsibility applies and refer to the appropriate rules file.
65
-
66
- ## Deterministic Slash Commands
67
-
68
- - Slash command protocol is defined in `AGENTS.MD` under `Deterministic Slash Command System Standard`.
69
- - Modular command contracts are stored in `agents/commands/`.
70
- - Command mode is strict: unknown or malformed slash commands must return structured error output and stop.
71
- - No conversational fallback is allowed once slash-command mode is entered.
72
- - Destructive actions require explicit confirmation token format: `CONFIRM-DESTRUCTIVE:<target>`.
73
-
74
- ## Technology Stack Independence
75
-
76
- These patterns apply regardless of your tech stack. Adapt them to your chosen framework:
77
-
78
- ### Frontend Frameworks
79
- - **React/Next.js/Vue/Svelte**: Component-based architecture with state management
80
- - **Angular**: Component + service pattern with TypeScript
81
- - **Traditional/Server-rendered**: Progressive enhancement with server-side rendering
82
-
83
- ### Backend Frameworks
84
- - **Node.js**: Express, Fastify, Koa, or Next.js API routes
85
- - **Python**: Django, FastAPI, Flask with ORM patterns
86
- - **Go**: Gin, Echo, Fiber for high-performance APIs
87
- - **Other languages**: Apply patterns to your chosen framework
88
-
89
- ### Database Technologies
90
- - **SQL**: PostgreSQL, MySQL, SQLite with ORM (Prisma, TypeORM, SQLAlchemy, etc.)
91
- - **NoSQL**: MongoDB, DynamoDB with schema validation
92
- - **Cloud-native**: Supabase, Firebase with built-in security
93
-
94
- ## Critical Rules (Never Skip These)
95
-
96
- 1. **Input Validation**: ALL user inputs must be validated with schema validation libraries
97
- 2. **Authentication**: Implement secure authentication with proper session management
98
- 3. **Rate Limiting**: Public endpoints MUST have rate limiting to prevent abuse
99
- 4. **Authorization**: Role-based access control with verified permissions
100
- 5. **Data Safety**: Never expose sensitive information in error responses
101
- 6. **Database Access**: Use ORM/ODM exclusively, never raw queries for user data
102
- 7. **Test Coverage**: Minimum 80% coverage for business logic
103
- 8. **Accessibility**: WCAG 2.1 AA compliance for all user interfaces
104
- 9. **Documentation**: Keep guides updated; code should be self-documenting
105
- 10. **Performance**: Monitor metrics, implement caching, optimize critical paths
106
-
107
- ## File Reference Guide
108
-
109
- | File | Purpose | When to Use |
110
- |------|---------|------------|
111
- | `AGENTS.MD` | Primary AI assistant guide | Always start here |
112
- | `agent-docs/ARCHITECTURE.md` | Architecture and technology stack decisions | Need architectural guidance |
113
- | `AGENTS.MD` | AI assistant guide and patterns | How to work effectively with AI |
114
- | `agents/commands/` | Deterministic slash command contracts | Slash-command execution |
115
- | `agents/rules/core.mdc` | Core development principles | General development questions |
116
- | `agents/rules/security.mdc` | Security patterns and implementations | Building secure features |
117
- | `agents/rules/testing.mdc` | Testing strategy and best practices | Writing tests or test strategy |
118
- | `agents/rules/frontend.mdc` | Frontend patterns and components | Building UI features |
119
- | `agents/rules/database.mdc` | Database and data access patterns | Working with data layers |
120
- | `agents/rules/style.mdc` | Code style and formatting | Code style questions |
121
- | `agents/skills/` | Domain-specific implementations | Looking for reusable patterns |
122
-
123
- ## Workflow Recommendations
124
-
125
- 1. **Read AGENTS.MD** for comprehensive AI assistance guidance
126
- 2. **Read agent-docs/ARCHITECTURE.md** to understand the overall architecture
127
- 3. **Reference AGENTS.MD** for AI working patterns and guidance
128
- 3. **Reference the appropriate rule file** for implementation patterns
129
- 4. **Look in agents/skills/** for domain-specific guidance
130
- 5. **Follow all critical rules** without exception
131
- 6. **Apply patterns consistently** across the codebase
132
-
133
- ## Additional Context
134
-
135
- - This template is **completely technology-agnostic** and works with any programming language
136
- - All patterns are **framework and language-independent**
137
- - The rules can be adapted to your specific tech stack while maintaining the security and quality principles
138
- - Skills in `agents/skills/` provide specific, actionable implementations
139
-
140
- ---
141
-
142
- For best results with Gemini AI assistance, reference the appropriate context from `AGENTS.MD`, `agent-docs/ARCHITECTURE.md`, and the relevant `agents/rules/*.mdc` files in your prompts.