@grvmithas/create-aies-kit 1.0.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -25
- package/bin/create-aies-kit.js +119 -41
- package/lib/kit-core/embedded-corpus.js +138 -0
- package/lib/kit-core/generate.js +794 -0
- package/lib/kit-core/install-api.js +173 -0
- package/lib/kit-core/mcp-catalog.js +170 -0
- package/lib/{options.js → kit-core/options.js} +25 -10
- package/package.json +10 -4
- package/lib/scaffold.js +0 -352
package/README.md
CHANGED
|
@@ -1,44 +1,55 @@
|
|
|
1
1
|
# @grvmithas/create-aies-kit
|
|
2
2
|
|
|
3
|
-
Scaffold
|
|
3
|
+
Scaffold a **complete AIES harness** into your repo using **IDE-native paths** (no `.aies/` folder).
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
npx @grvmithas/create-aies-kit
|
|
6
|
+
npx @grvmithas/create-aies-kit@latest \
|
|
7
|
+
--stack nextjs --ide cursor --role fullstack \
|
|
8
|
+
--maturity intermediate --goal new-product \
|
|
9
|
+
--model claude --data-class internal --yes
|
|
7
10
|
```
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
Then enhance for *this* repository:
|
|
10
13
|
|
|
11
14
|
```bash
|
|
12
|
-
npx @grvmithas/create-aies-kit
|
|
15
|
+
npx @grvmithas/create-aies-kit@latest enhance
|
|
13
16
|
```
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
Then open `*/prompts/enhance-repo.prompt.md` in your IDE agent so it adapts artifacts to your conventions.
|
|
19
|
+
|
|
20
|
+
## Layout contract
|
|
21
|
+
|
|
22
|
+
| Location | Contents |
|
|
23
|
+
|----------|----------|
|
|
24
|
+
| IDE folder (`.cursor` / `.github` / `.claude` / …) | **prompts**, **skills**, **agents** only (+ IDE rules / MCP config) |
|
|
25
|
+
| Repo root | `cookbook/{stack}/`, `guides/`, `mcps/`, `templates/`, `MODEL_POLICY.md`, root instruction files |
|
|
26
|
+
|
|
27
|
+
**Anti-pattern:** Nesting cookbook (or guides/MCP specs) under `.github/`. That folder is for Copilot discovery and GitHub metadata only.
|
|
28
|
+
|
|
29
|
+
## What you get
|
|
16
30
|
|
|
17
31
|
| Path | Purpose |
|
|
18
32
|
|------|---------|
|
|
19
|
-
|
|
|
20
|
-
|
|
|
33
|
+
| `AIES.md` | Operator guide — plans, prompts, skills, MCP, enhance |
|
|
34
|
+
| `implementation_plan.md` | Plan of record |
|
|
35
|
+
| `AGENTS.md` | Multi-agent / IDE agent contract |
|
|
36
|
+
| `CLAUDE.md` | Root Claude / multi-IDE contract |
|
|
37
|
+
| `copilot-instructions.md` | Root Copilot instructions |
|
|
38
|
+
| `.github/copilot-instructions.md` | Copilot discovery copy |
|
|
39
|
+
| IDE `prompts/` `skills/` `agents/` | Lifecycle + create/enhance artifacts |
|
|
40
|
+
| `cookbook/{stack}/` | Full stack cookbook at **repo root** |
|
|
21
41
|
|
|
22
|
-
|
|
42
|
+
Maturity only changes the **reading path** in `AIES.md`.
|
|
23
43
|
|
|
24
|
-
|
|
25
|
-
|------|--------|
|
|
26
|
-
| `--stack` | `react`, `nextjs`, `react-native`, `nodejs`, `nestjs`, `python`, `fastapi`, `java`, `dotnet` |
|
|
27
|
-
| `--ide` | `cursor`, `copilot`, `claude-code`, `vscode`, `windsurf`, `continue` |
|
|
28
|
-
| `--role` | `product-manager`, `architect`, `frontend`, `backend`, `fullstack`, `qa`, `devops`, `engineering-manager`, `ai-engineer` |
|
|
29
|
-
| `--maturity` | `beginner`, `intermediate`, `advanced`, `enterprise` |
|
|
30
|
-
| `--goal` | `new-product`, `existing-codebase`, `legacy-modernize`, `learn`, `browse-standards`, `explore-examples` |
|
|
31
|
-
| `--force` | Overwrite existing files |
|
|
32
|
-
| `--dry-run` | Print paths without writing |
|
|
33
|
-
| `--yes` / `-y` | Skip confirmations when all flags are set |
|
|
44
|
+
## MCP
|
|
34
45
|
|
|
35
|
-
|
|
46
|
+
`mcpServers` starts empty. `_aiesRecommended` holds enable-ready stubs (stack + enhance scan). Copy after human approval; never commit secrets.
|
|
36
47
|
|
|
37
|
-
|
|
38
|
-
2. Attach it in IDE chat before coding
|
|
39
|
-
3. Continue: https://open-ai-engineering-standards.vercel.app/workflows
|
|
48
|
+
Docs: https://www.ai-standards.dev/quickstart
|
|
40
49
|
|
|
41
|
-
##
|
|
50
|
+
## Changelog
|
|
42
51
|
|
|
43
|
-
-
|
|
44
|
-
-
|
|
52
|
+
- **1.3.0** — Ephemeral `plans/{STORY_ID}-plan.md` + `reviews/{STORY_ID}-code-review.md`; agent hooks shipped; enhance-repo v2 with IDE chat invoke + deep guardrail scan (lint/style FE+BE).
|
|
53
|
+
- **1.2.0** — Layout fix: cookbook/guides/mcps/templates at repo root for all IDEs; `.github` holds prompts/skills/agents (+ copilot-instructions) only.
|
|
54
|
+
- **1.1.0** — Self-contained package (embedded corpus + generator).
|
|
55
|
+
- **1.0.0** — Initial publish (incomplete; do not use).
|
package/bin/create-aies-kit.js
CHANGED
|
@@ -1,19 +1,38 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { mkdir, writeFile, access } from 'node:fs/promises';
|
|
3
|
+
import { mkdir, writeFile, access, readFile } from 'node:fs/promises';
|
|
4
4
|
import { dirname, join, resolve } from 'node:path';
|
|
5
5
|
import { constants } from 'node:fs';
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import {
|
|
7
|
+
GOALS,
|
|
8
|
+
ROLES,
|
|
9
|
+
MATURITIES,
|
|
10
|
+
IDES,
|
|
11
|
+
MODELS,
|
|
12
|
+
DATA_CLASSES,
|
|
13
|
+
STACKS,
|
|
14
|
+
STACK_LABELS,
|
|
15
|
+
idsOf,
|
|
16
|
+
} from '../lib/kit-core/options.js';
|
|
17
|
+
import { enhanceStarterKit, generateStarterKit, layoutFor } from '../lib/kit-core/generate.js';
|
|
8
18
|
import { choose, confirm } from '../lib/prompts.js';
|
|
9
19
|
|
|
10
20
|
function printHelp() {
|
|
11
21
|
console.log(`
|
|
12
|
-
create-aies-kit —
|
|
22
|
+
create-aies-kit — complete AIES harness in IDE-native paths (no .aies/)
|
|
13
23
|
|
|
14
24
|
Usage:
|
|
15
25
|
npx @grvmithas/create-aies-kit
|
|
16
|
-
npx @grvmithas/create-aies-kit --stack nextjs --ide cursor --role fullstack --maturity intermediate --goal new-product --yes
|
|
26
|
+
npx @grvmithas/create-aies-kit --stack nextjs --ide cursor --role fullstack --maturity intermediate --goal new-product --model claude --data-class internal --yes
|
|
27
|
+
npx @grvmithas/create-aies-kit enhance
|
|
28
|
+
|
|
29
|
+
Install writes: AIES.md, implementation_plan.md, CLAUDE.md, AGENTS.md,
|
|
30
|
+
IDE prompts/skills/agents under .cursor | .github | .claude | …
|
|
31
|
+
plus repo-root cookbook/, guides/, mcps/, templates/ (never under .github/cookbook).
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
After install, run enhance (no --yes needed) to scan the repo and refresh MCP recommendations, then
|
|
35
|
+
run the enhance-repo prompt in your IDE.
|
|
17
36
|
|
|
18
37
|
Flags:
|
|
19
38
|
--stack ${idsOf(STACKS).join(' | ')}
|
|
@@ -21,28 +40,32 @@ Flags:
|
|
|
21
40
|
--role ${idsOf(ROLES).join(' | ')}
|
|
22
41
|
--maturity ${idsOf(MATURITIES).join(' | ')}
|
|
23
42
|
--goal ${idsOf(GOALS).join(' | ')}
|
|
43
|
+
--model ${idsOf(MODELS).join(' | ')}
|
|
44
|
+
--data-class ${idsOf(DATA_CLASSES).join(' | ')}
|
|
24
45
|
--force Overwrite existing files
|
|
25
46
|
--dry-run Print files without writing
|
|
26
|
-
--yes, -y Non-interactive when
|
|
47
|
+
--yes, -y Non-interactive when profile flags are set
|
|
27
48
|
--help, -h Show help
|
|
28
49
|
`);
|
|
29
50
|
}
|
|
30
51
|
|
|
31
52
|
function parseArgs(argv) {
|
|
32
53
|
/** @type {Record<string, string | boolean>} */
|
|
33
|
-
const out = {};
|
|
54
|
+
const out = { _: [] };
|
|
34
55
|
for (let i = 0; i < argv.length; i += 1) {
|
|
35
56
|
const arg = argv[i];
|
|
36
57
|
if (arg === '--help' || arg === '-h') out.help = true;
|
|
37
58
|
else if (arg === '--force') out.force = true;
|
|
38
59
|
else if (arg === '--dry-run') out.dryRun = true;
|
|
39
60
|
else if (arg === '--yes' || arg === '-y') out.yes = true;
|
|
40
|
-
else if (arg.startsWith('--') &&
|
|
41
|
-
out[arg.slice(2)] = argv[i + 1];
|
|
42
|
-
i += 1;
|
|
43
|
-
} else if (arg.startsWith('--') && arg.includes('=')) {
|
|
61
|
+
else if (arg.startsWith('--') && arg.includes('=')) {
|
|
44
62
|
const [k, v] = arg.slice(2).split('=');
|
|
45
63
|
out[k] = v;
|
|
64
|
+
} else if (arg.startsWith('--') && argv[i + 1] && !argv[i + 1].startsWith('--')) {
|
|
65
|
+
out[arg.slice(2)] = argv[i + 1];
|
|
66
|
+
i += 1;
|
|
67
|
+
} else if (!arg.startsWith('--')) {
|
|
68
|
+
out._.push(arg);
|
|
46
69
|
}
|
|
47
70
|
}
|
|
48
71
|
return out;
|
|
@@ -67,7 +90,6 @@ async function pathExists(path) {
|
|
|
67
90
|
async function writeBundle(cwd, files, { force, dryRun }) {
|
|
68
91
|
const written = [];
|
|
69
92
|
const skipped = [];
|
|
70
|
-
|
|
71
93
|
for (const [relPath, content] of Object.entries(files)) {
|
|
72
94
|
const abs = join(cwd, relPath);
|
|
73
95
|
const exists = await pathExists(abs);
|
|
@@ -83,49 +105,96 @@ async function writeBundle(cwd, files, { force, dryRun }) {
|
|
|
83
105
|
await writeFile(abs, content, 'utf8');
|
|
84
106
|
written.push(relPath);
|
|
85
107
|
}
|
|
86
|
-
|
|
87
108
|
return { written, skipped };
|
|
88
109
|
}
|
|
89
110
|
|
|
111
|
+
function stackIdFromLabel(label) {
|
|
112
|
+
const entry = Object.entries(STACK_LABELS).find(([, v]) => v === label);
|
|
113
|
+
return entry?.[0];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async function recoverProfile(cwd, args) {
|
|
117
|
+
const dataClass = args['data-class'] || args.dataClass;
|
|
118
|
+
let profile = {
|
|
119
|
+
goal: args.goal,
|
|
120
|
+
role: args.role,
|
|
121
|
+
maturity: args.maturity,
|
|
122
|
+
ide: args.ide,
|
|
123
|
+
model: args.model,
|
|
124
|
+
dataClass,
|
|
125
|
+
stack: args.stack,
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
if (Object.values(profile).every(Boolean)) return profile;
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const aies = await readFile(join(cwd, 'AIES.md'), 'utf8');
|
|
132
|
+
const m = aies.match(
|
|
133
|
+
/\*\*Profile:\*\*\s*(\S+)\s*·\s*(\S+)\s*·\s*(\S+)\s*·\s*([^*·]+?)\s*·\s*model\s*\*\*([^*]+)\*\*\s*·\s*data\s*\*\*([^*]+)\*\*/,
|
|
134
|
+
);
|
|
135
|
+
if (m) {
|
|
136
|
+
const label = m[4].trim();
|
|
137
|
+
profile = {
|
|
138
|
+
goal: profile.goal || 'existing-codebase',
|
|
139
|
+
role: profile.role || m[1],
|
|
140
|
+
ide: profile.ide || m[2],
|
|
141
|
+
maturity: profile.maturity || m[3],
|
|
142
|
+
stack: profile.stack || stackIdFromLabel(label) || 'nextjs',
|
|
143
|
+
model: profile.model || m[5].trim(),
|
|
144
|
+
dataClass: profile.dataClass || m[6].trim(),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
} catch {
|
|
148
|
+
// no AIES.md yet
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return profile;
|
|
152
|
+
}
|
|
153
|
+
|
|
90
154
|
async function main() {
|
|
91
|
-
const
|
|
155
|
+
const rawArgv = process.argv.slice(2);
|
|
156
|
+
const isEnhance = rawArgv[0] === 'enhance';
|
|
157
|
+
const args = parseArgs(isEnhance ? rawArgv.slice(1) : rawArgv);
|
|
158
|
+
|
|
92
159
|
if (args.help) {
|
|
93
160
|
printHelp();
|
|
94
161
|
return;
|
|
95
162
|
}
|
|
96
163
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
assertChoice('role', args.role, idsOf(ROLES));
|
|
100
|
-
assertChoice('maturity', args.maturity, idsOf(MATURITIES));
|
|
101
|
-
assertChoice('goal', args.goal, idsOf(GOALS));
|
|
164
|
+
const cwd = resolve(process.cwd());
|
|
165
|
+
let profile = await recoverProfile(cwd, args);
|
|
102
166
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
167
|
+
assertChoice('stack', profile.stack, idsOf(STACKS));
|
|
168
|
+
assertChoice('ide', profile.ide, idsOf(IDES));
|
|
169
|
+
assertChoice('role', profile.role, idsOf(ROLES));
|
|
170
|
+
assertChoice('maturity', profile.maturity, idsOf(MATURITIES));
|
|
171
|
+
assertChoice('goal', profile.goal, idsOf(GOALS));
|
|
172
|
+
assertChoice('model', profile.model, idsOf(MODELS));
|
|
173
|
+
assertChoice('data-class', profile.dataClass, idsOf(DATA_CLASSES));
|
|
110
174
|
|
|
111
175
|
const missing = Object.entries(profile).filter(([, v]) => !v).map(([k]) => k);
|
|
112
176
|
if (missing.length > 0) {
|
|
113
177
|
if (args.yes) {
|
|
114
|
-
throw new Error(
|
|
178
|
+
throw new Error(
|
|
179
|
+
`Missing required profile fields: ${missing.join(', ')}. Pass flags or run install first so AIES.md exists.`,
|
|
180
|
+
);
|
|
115
181
|
}
|
|
116
182
|
console.log('AIES starter kit — answer a few questions (or pass flags for CI).');
|
|
117
183
|
if (!profile.goal) profile.goal = await choose('What is your goal?', GOALS, 'new-product');
|
|
118
184
|
if (!profile.role) profile.role = await choose('What is your role?', ROLES, 'fullstack');
|
|
119
185
|
if (!profile.maturity) profile.maturity = await choose('AI experience?', MATURITIES, 'intermediate');
|
|
120
186
|
if (!profile.ide) profile.ide = await choose('Which IDE?', IDES, 'cursor');
|
|
187
|
+
if (!profile.model) profile.model = await choose('Primary model / provider?', MODELS, 'claude');
|
|
188
|
+
if (!profile.dataClass) profile.dataClass = await choose('Data class for this project?', DATA_CLASSES, 'internal');
|
|
121
189
|
if (!profile.stack) profile.stack = await choose('Technology stack?', STACKS, 'nextjs');
|
|
122
190
|
}
|
|
123
191
|
|
|
124
|
-
const cwd = resolve(process.cwd());
|
|
125
192
|
console.log(`\nTarget directory: ${cwd}`);
|
|
126
|
-
console.log(
|
|
193
|
+
console.log(
|
|
194
|
+
`Mode: ${isEnhance ? 'enhance' : 'install'} · ${profile.stack} · ${profile.ide} · ${profile.role} · ${profile.maturity} · ${profile.model} · ${profile.dataClass}`,
|
|
195
|
+
);
|
|
127
196
|
|
|
128
|
-
if (!args.yes && !args.dryRun) {
|
|
197
|
+
if (!args.yes && !args.dryRun && !isEnhance) {
|
|
129
198
|
const ok = await confirm('Write AIES harness files here?', true);
|
|
130
199
|
if (!ok) {
|
|
131
200
|
console.log('Cancelled.');
|
|
@@ -134,29 +203,38 @@ async function main() {
|
|
|
134
203
|
}
|
|
135
204
|
}
|
|
136
205
|
|
|
137
|
-
const bundle = generateStarterKit(profile);
|
|
206
|
+
const bundle = isEnhance ? enhanceStarterKit(cwd, profile) : generateStarterKit(profile);
|
|
207
|
+
// enhance always overwrites generated harness files so MCP recommendations refresh
|
|
208
|
+
const force = Boolean(args.force) || isEnhance;
|
|
138
209
|
const { written, skipped } = await writeBundle(cwd, bundle.files, {
|
|
139
|
-
force
|
|
210
|
+
force,
|
|
140
211
|
dryRun: Boolean(args.dryRun),
|
|
141
212
|
});
|
|
142
213
|
|
|
143
214
|
if (args.dryRun) {
|
|
144
|
-
console.log(
|
|
145
|
-
written.forEach(f => console.log(` ${f}`));
|
|
215
|
+
console.log(`\nDry run — would write ${written.length} file(s):`);
|
|
216
|
+
written.slice(0, 40).forEach(f => console.log(` ${f}`));
|
|
217
|
+
if (written.length > 40) console.log(` … +${written.length - 40} more`);
|
|
146
218
|
} else {
|
|
147
|
-
console.log(`\nWrote ${written.length} file(s)
|
|
148
|
-
written.forEach(f => console.log(` ✓ ${f}`));
|
|
219
|
+
console.log(`\nWrote ${written.length} file(s).`);
|
|
220
|
+
written.slice(0, 25).forEach(f => console.log(` ✓ ${f}`));
|
|
221
|
+
if (written.length > 25) console.log(` … +${written.length - 25} more`);
|
|
149
222
|
}
|
|
150
223
|
|
|
151
224
|
if (skipped.length > 0) {
|
|
152
|
-
console.log(`\nSkipped ${skipped.length} existing file(s) (use --force
|
|
153
|
-
skipped.forEach(f => console.log(` · ${f}`));
|
|
225
|
+
console.log(`\nSkipped ${skipped.length} existing file(s) (use --force):`);
|
|
226
|
+
skipped.slice(0, 10).forEach(f => console.log(` · ${f}`));
|
|
154
227
|
}
|
|
155
228
|
|
|
229
|
+
const L = layoutFor(profile.ide);
|
|
156
230
|
console.log('\nNext:');
|
|
157
|
-
console.log(' 1.
|
|
158
|
-
|
|
159
|
-
|
|
231
|
+
console.log(' 1. Read AIES.md');
|
|
232
|
+
if (!isEnhance) {
|
|
233
|
+
console.log(' 2. npx @grvmithas/create-aies-kit enhance');
|
|
234
|
+
}
|
|
235
|
+
console.log(` ${isEnhance ? '2' : '3'}. Run ${L.promptsDir}/enhance-repo.prompt.md in your IDE agent`);
|
|
236
|
+
console.log(` ${isEnhance ? '3' : '4'}. Fill implementation_plan.md`);
|
|
237
|
+
console.log(` ${isEnhance ? '4' : '5'}. https://www.ai-standards.dev/workflows`);
|
|
160
238
|
}
|
|
161
239
|
|
|
162
240
|
main().catch(err => {
|