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