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 +30 -21
- package/bin/cli.js +195 -93
- package/index.js +17 -31
- package/lib/instructions.js +145 -0
- package/lib/layout.js +95 -0
- package/package.json +2 -1
- package/templates/README.md +27 -18
- package/templates/instructions/source/core.md +36 -0
- package/templates/GEMINI.md +0 -142
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` | ✅
|
|
125
|
-
| **Gemini** | `GEMINI.md` | ✅
|
|
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
|
-
**
|
|
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
|
-
├──
|
|
143
|
-
│ ├──
|
|
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
|
-
│ ├──
|
|
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
|
-
├──
|
|
175
|
-
├──
|
|
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 (
|
|
108
|
-
{ name: 'Skills (
|
|
109
|
-
{ name: 'AI Agent instructions (Cursor, Copilot,
|
|
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
|
|
140
|
-
await fs.ensureDir(
|
|
141
|
-
await copyDirectory(sourceDir,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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(' ✓
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
335
|
+
path.join(targetDir, LAYOUT.canonical.skillsDir),
|
|
325
336
|
options.force
|
|
326
337
|
);
|
|
327
338
|
}
|
|
328
339
|
|
|
329
|
-
// Install AI Agent instructions (Cursor, Copilot,
|
|
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
|
-
|
|
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(' ✓
|
|
343
|
-
console.log(chalk.gray(' ✓
|
|
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
|
|
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
|
|
354
|
-
console.log(chalk.white(' 4. Customize
|
|
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 (
|
|
375
|
-
console.log(chalk.yellow('skills') + ' - Agent skills (
|
|
376
|
-
console.log(chalk.yellow('github') + ' - AI Agent instructions (Cursor, Copilot,
|
|
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
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
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(`⚠
|
|
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
|
|
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(`✓
|
|
443
|
+
passed.push(`✓ ${relativeRulesDir}/${file} found`);
|
|
433
444
|
} else {
|
|
434
|
-
warnings.push(`⚠
|
|
445
|
+
warnings.push(`⚠ ${relativeRulesDir}/${file} missing`);
|
|
435
446
|
}
|
|
436
447
|
}
|
|
437
448
|
} else {
|
|
438
|
-
warnings.push(`⚠
|
|
449
|
+
warnings.push(`⚠ ${LAYOUT.canonical.rulesDir} directory missing - run 'agents-templated init --rules'`);
|
|
439
450
|
}
|
|
440
451
|
|
|
441
452
|
// Check skills
|
|
442
|
-
const
|
|
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
|
-
|
|
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(`⚠
|
|
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
|
-
|
|
451
|
-
|
|
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
|
|
590
|
-
await fs.pathExists(path.join(targetDir,
|
|
591
|
-
await fs.pathExists(path.join(targetDir,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
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:
|
|
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:
|
|
696
|
-
{ targetFile:
|
|
697
|
-
{ targetFile:
|
|
698
|
-
{ targetFile:
|
|
699
|
-
{ targetFile:
|
|
700
|
-
{ targetFile:
|
|
701
|
-
{ targetFile: '.
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
67
|
+
path.join(targetDir, LAYOUT.canonical.skillsDir),
|
|
66
68
|
options.force
|
|
67
69
|
);
|
|
68
70
|
}
|
|
69
71
|
|
|
70
|
-
// AI Agent instructions (Cursor, Copilot, Claude
|
|
72
|
+
// AI Agent instructions (Cursor, Copilot, Claude)
|
|
71
73
|
if (installAll || options.github) {
|
|
72
|
-
await fs.ensureDir(path.join(targetDir, '.github'));
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
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.
|
|
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",
|
package/templates/README.md
CHANGED
|
@@ -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` | ✅
|
|
106
|
-
| **Gemini** | `GEMINI.md` | ✅
|
|
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
|
-
**
|
|
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
|
-
├──
|
|
124
|
-
│ ├──
|
|
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
|
-
│ ├──
|
|
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
|
-
├──
|
|
149
|
-
├──
|
|
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
|
+
|
package/templates/GEMINI.md
DELETED
|
@@ -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.
|