@grvmithas/create-aies-kit 1.0.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/LICENSE +21 -0
- package/README.md +44 -0
- package/bin/create-aies-kit.js +165 -0
- package/lib/options.js +56 -0
- package/lib/prompts.js +45 -0
- package/lib/scaffold.js +352 -0
- package/package.json +43 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gaurav Mithas / Open AI Engineering Standard contributor
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# @grvmithas/create-aies-kit
|
|
2
|
+
|
|
3
|
+
Scaffold an **AIES** (AI Engineering Standard) harness into your app repo in under a minute.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx @grvmithas/create-aies-kit
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Or non-interactive:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx @grvmithas/create-aies-kit --stack nextjs --ide cursor --role fullstack --maturity intermediate --goal new-product --yes
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## What it writes
|
|
16
|
+
|
|
17
|
+
| Path | Purpose |
|
|
18
|
+
|------|---------|
|
|
19
|
+
| `.aies/` | Plan, prompts, skills, MCP/hooks stubs |
|
|
20
|
+
| IDE rules | e.g. `.cursor/rules/aies.mdc`, `CLAUDE.md`, `.github/copilot-instructions.md` |
|
|
21
|
+
|
|
22
|
+
## Flags
|
|
23
|
+
|
|
24
|
+
| Flag | Values |
|
|
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
|
+
|
|
35
|
+
## After install
|
|
36
|
+
|
|
37
|
+
1. Fill `.aies/implementation_plan.md`
|
|
38
|
+
2. Attach it in IDE chat before coding
|
|
39
|
+
3. Continue: https://open-ai-engineering-standards.vercel.app/workflows
|
|
40
|
+
|
|
41
|
+
## Docs
|
|
42
|
+
|
|
43
|
+
- Quick start: https://open-ai-engineering-standards.vercel.app/quickstart
|
|
44
|
+
- Corpus: https://github.com/grvmithas/open-ai-engineering-standards
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { mkdir, writeFile, access } from 'node:fs/promises';
|
|
4
|
+
import { dirname, join, resolve } from 'node:path';
|
|
5
|
+
import { constants } from 'node:fs';
|
|
6
|
+
import { GOALS, ROLES, MATURITIES, IDES, STACKS, idsOf } from '../lib/options.js';
|
|
7
|
+
import { generateStarterKit } from '../lib/scaffold.js';
|
|
8
|
+
import { choose, confirm } from '../lib/prompts.js';
|
|
9
|
+
|
|
10
|
+
function printHelp() {
|
|
11
|
+
console.log(`
|
|
12
|
+
create-aies-kit — scaffold an AIES project harness
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
npx @grvmithas/create-aies-kit
|
|
16
|
+
npx @grvmithas/create-aies-kit --stack nextjs --ide cursor --role fullstack --maturity intermediate --goal new-product --yes
|
|
17
|
+
|
|
18
|
+
Flags:
|
|
19
|
+
--stack ${idsOf(STACKS).join(' | ')}
|
|
20
|
+
--ide ${idsOf(IDES).join(' | ')}
|
|
21
|
+
--role ${idsOf(ROLES).join(' | ')}
|
|
22
|
+
--maturity ${idsOf(MATURITIES).join(' | ')}
|
|
23
|
+
--goal ${idsOf(GOALS).join(' | ')}
|
|
24
|
+
--force Overwrite existing files
|
|
25
|
+
--dry-run Print files without writing
|
|
26
|
+
--yes, -y Non-interactive when all profile flags are set
|
|
27
|
+
--help, -h Show help
|
|
28
|
+
`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function parseArgs(argv) {
|
|
32
|
+
/** @type {Record<string, string | boolean>} */
|
|
33
|
+
const out = {};
|
|
34
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
35
|
+
const arg = argv[i];
|
|
36
|
+
if (arg === '--help' || arg === '-h') out.help = true;
|
|
37
|
+
else if (arg === '--force') out.force = true;
|
|
38
|
+
else if (arg === '--dry-run') out.dryRun = true;
|
|
39
|
+
else if (arg === '--yes' || arg === '-y') out.yes = true;
|
|
40
|
+
else if (arg.startsWith('--') && argv[i + 1] && !argv[i + 1].startsWith('--')) {
|
|
41
|
+
out[arg.slice(2)] = argv[i + 1];
|
|
42
|
+
i += 1;
|
|
43
|
+
} else if (arg.startsWith('--') && arg.includes('=')) {
|
|
44
|
+
const [k, v] = arg.slice(2).split('=');
|
|
45
|
+
out[k] = v;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function assertChoice(name, value, allowed) {
|
|
52
|
+
if (!value) return;
|
|
53
|
+
if (!allowed.includes(value)) {
|
|
54
|
+
throw new Error(`Invalid --${name} "${value}". Allowed: ${allowed.join(', ')}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function pathExists(path) {
|
|
59
|
+
try {
|
|
60
|
+
await access(path, constants.F_OK);
|
|
61
|
+
return true;
|
|
62
|
+
} catch {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function writeBundle(cwd, files, { force, dryRun }) {
|
|
68
|
+
const written = [];
|
|
69
|
+
const skipped = [];
|
|
70
|
+
|
|
71
|
+
for (const [relPath, content] of Object.entries(files)) {
|
|
72
|
+
const abs = join(cwd, relPath);
|
|
73
|
+
const exists = await pathExists(abs);
|
|
74
|
+
if (exists && !force) {
|
|
75
|
+
skipped.push(relPath);
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (dryRun) {
|
|
79
|
+
written.push(relPath);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
await mkdir(dirname(abs), { recursive: true });
|
|
83
|
+
await writeFile(abs, content, 'utf8');
|
|
84
|
+
written.push(relPath);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return { written, skipped };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function main() {
|
|
91
|
+
const args = parseArgs(process.argv.slice(2));
|
|
92
|
+
if (args.help) {
|
|
93
|
+
printHelp();
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
assertChoice('stack', args.stack, idsOf(STACKS));
|
|
98
|
+
assertChoice('ide', args.ide, idsOf(IDES));
|
|
99
|
+
assertChoice('role', args.role, idsOf(ROLES));
|
|
100
|
+
assertChoice('maturity', args.maturity, idsOf(MATURITIES));
|
|
101
|
+
assertChoice('goal', args.goal, idsOf(GOALS));
|
|
102
|
+
|
|
103
|
+
let profile = {
|
|
104
|
+
goal: /** @type {string} */ (args.goal),
|
|
105
|
+
role: /** @type {string} */ (args.role),
|
|
106
|
+
maturity: /** @type {string} */ (args.maturity),
|
|
107
|
+
ide: /** @type {string} */ (args.ide),
|
|
108
|
+
stack: /** @type {string} */ (args.stack),
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const missing = Object.entries(profile).filter(([, v]) => !v).map(([k]) => k);
|
|
112
|
+
if (missing.length > 0) {
|
|
113
|
+
if (args.yes) {
|
|
114
|
+
throw new Error(`Missing required flags in --yes mode: ${missing.join(', ')}`);
|
|
115
|
+
}
|
|
116
|
+
console.log('AIES starter kit — answer a few questions (or pass flags for CI).');
|
|
117
|
+
if (!profile.goal) profile.goal = await choose('What is your goal?', GOALS, 'new-product');
|
|
118
|
+
if (!profile.role) profile.role = await choose('What is your role?', ROLES, 'fullstack');
|
|
119
|
+
if (!profile.maturity) profile.maturity = await choose('AI experience?', MATURITIES, 'intermediate');
|
|
120
|
+
if (!profile.ide) profile.ide = await choose('Which IDE?', IDES, 'cursor');
|
|
121
|
+
if (!profile.stack) profile.stack = await choose('Technology stack?', STACKS, 'nextjs');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const cwd = resolve(process.cwd());
|
|
125
|
+
console.log(`\nTarget directory: ${cwd}`);
|
|
126
|
+
console.log(`Profile: ${profile.stack} · ${profile.ide} · ${profile.role} · ${profile.maturity}`);
|
|
127
|
+
|
|
128
|
+
if (!args.yes && !args.dryRun) {
|
|
129
|
+
const ok = await confirm('Write AIES harness files here?', true);
|
|
130
|
+
if (!ok) {
|
|
131
|
+
console.log('Cancelled.');
|
|
132
|
+
process.exitCode = 1;
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const bundle = generateStarterKit(profile);
|
|
138
|
+
const { written, skipped } = await writeBundle(cwd, bundle.files, {
|
|
139
|
+
force: Boolean(args.force),
|
|
140
|
+
dryRun: Boolean(args.dryRun),
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
if (args.dryRun) {
|
|
144
|
+
console.log('\nDry run — would write:');
|
|
145
|
+
written.forEach(f => console.log(` ${f}`));
|
|
146
|
+
} else {
|
|
147
|
+
console.log(`\nWrote ${written.length} file(s):`);
|
|
148
|
+
written.forEach(f => console.log(` ✓ ${f}`));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (skipped.length > 0) {
|
|
152
|
+
console.log(`\nSkipped ${skipped.length} existing file(s) (use --force to overwrite):`);
|
|
153
|
+
skipped.forEach(f => console.log(` · ${f}`));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
console.log('\nNext:');
|
|
157
|
+
console.log(' 1. Fill .aies/implementation_plan.md');
|
|
158
|
+
console.log(' 2. Attach it in IDE chat before coding');
|
|
159
|
+
console.log(' 3. https://open-ai-engineering-standards.vercel.app/workflows');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
main().catch(err => {
|
|
163
|
+
console.error(`\nError: ${err.message}`);
|
|
164
|
+
process.exitCode = 1;
|
|
165
|
+
});
|
package/lib/options.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export const SITE_URL = 'https://open-ai-engineering-standards.vercel.app';
|
|
2
|
+
|
|
3
|
+
export const GOALS = [
|
|
4
|
+
{ id: 'new-product', label: 'Build a new product' },
|
|
5
|
+
{ id: 'existing-codebase', label: 'Join an existing codebase' },
|
|
6
|
+
{ id: 'legacy-modernize', label: 'Modernize legacy software' },
|
|
7
|
+
{ id: 'learn', label: 'Learn AI Engineering' },
|
|
8
|
+
{ id: 'browse-standards', label: 'Browse standards' },
|
|
9
|
+
{ id: 'explore-examples', label: 'Explore examples' },
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
export const ROLES = [
|
|
13
|
+
{ id: 'product-manager', label: 'Product Manager' },
|
|
14
|
+
{ id: 'architect', label: 'Architect' },
|
|
15
|
+
{ id: 'frontend', label: 'Frontend Developer' },
|
|
16
|
+
{ id: 'backend', label: 'Backend Developer' },
|
|
17
|
+
{ id: 'fullstack', label: 'Full Stack Engineer' },
|
|
18
|
+
{ id: 'qa', label: 'QA Engineer' },
|
|
19
|
+
{ id: 'devops', label: 'DevOps Engineer' },
|
|
20
|
+
{ id: 'engineering-manager', label: 'Engineering Manager' },
|
|
21
|
+
{ id: 'ai-engineer', label: 'AI Engineer' },
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
export const MATURITIES = [
|
|
25
|
+
{ id: 'beginner', label: 'Beginner' },
|
|
26
|
+
{ id: 'intermediate', label: 'Intermediate' },
|
|
27
|
+
{ id: 'advanced', label: 'Advanced' },
|
|
28
|
+
{ id: 'enterprise', label: 'Enterprise transformation' },
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
export const IDES = [
|
|
32
|
+
{ id: 'cursor', label: 'Cursor' },
|
|
33
|
+
{ id: 'copilot', label: 'GitHub Copilot' },
|
|
34
|
+
{ id: 'claude-code', label: 'Claude Code' },
|
|
35
|
+
{ id: 'vscode', label: 'VS Code' },
|
|
36
|
+
{ id: 'windsurf', label: 'Windsurf' },
|
|
37
|
+
{ id: 'continue', label: 'Continue' },
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
export const STACKS = [
|
|
41
|
+
{ id: 'react', label: 'React' },
|
|
42
|
+
{ id: 'nextjs', label: 'Next.js' },
|
|
43
|
+
{ id: 'react-native', label: 'React Native' },
|
|
44
|
+
{ id: 'nodejs', label: 'Node.js' },
|
|
45
|
+
{ id: 'nestjs', label: 'NestJS' },
|
|
46
|
+
{ id: 'python', label: 'Python' },
|
|
47
|
+
{ id: 'fastapi', label: 'FastAPI' },
|
|
48
|
+
{ id: 'java', label: 'Java' },
|
|
49
|
+
{ id: 'dotnet', label: '.NET' },
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
export const STACK_LABELS = Object.fromEntries(STACKS.map(s => [s.id, s.label]));
|
|
53
|
+
|
|
54
|
+
export function idsOf(list) {
|
|
55
|
+
return list.map(item => item.id);
|
|
56
|
+
}
|
package/lib/prompts.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import readline from 'node:readline/promises';
|
|
2
|
+
import { stdin as input, stdout as output } from 'node:process';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @param {string} question
|
|
6
|
+
* @param {Array<{ id: string, label: string }>} choices
|
|
7
|
+
* @param {string} [defaultId]
|
|
8
|
+
*/
|
|
9
|
+
export async function choose(question, choices, defaultId) {
|
|
10
|
+
const rl = readline.createInterface({ input, output });
|
|
11
|
+
try {
|
|
12
|
+
output.write(`\n${question}\n`);
|
|
13
|
+
choices.forEach((c, i) => {
|
|
14
|
+
output.write(` ${i + 1}. ${c.label} (${c.id})\n`);
|
|
15
|
+
});
|
|
16
|
+
const hint = defaultId ? ` [${defaultId}]` : '';
|
|
17
|
+
const answer = (await rl.question(`Select number or id${hint}: `)).trim();
|
|
18
|
+
if (!answer && defaultId) return defaultId;
|
|
19
|
+
const asNum = Number.parseInt(answer, 10);
|
|
20
|
+
if (!Number.isNaN(asNum) && asNum >= 1 && asNum <= choices.length) {
|
|
21
|
+
return choices[asNum - 1].id;
|
|
22
|
+
}
|
|
23
|
+
const byId = choices.find(c => c.id === answer || c.label.toLowerCase() === answer.toLowerCase());
|
|
24
|
+
if (byId) return byId.id;
|
|
25
|
+
throw new Error(`Invalid selection: ${answer}`);
|
|
26
|
+
} finally {
|
|
27
|
+
rl.close();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {string} question
|
|
33
|
+
* @param {boolean} [defaultYes]
|
|
34
|
+
*/
|
|
35
|
+
export async function confirm(question, defaultYes = true) {
|
|
36
|
+
const rl = readline.createInterface({ input, output });
|
|
37
|
+
try {
|
|
38
|
+
const suffix = defaultYes ? ' [Y/n] ' : ' [y/N] ';
|
|
39
|
+
const answer = (await rl.question(`${question}${suffix}`)).trim().toLowerCase();
|
|
40
|
+
if (!answer) return defaultYes;
|
|
41
|
+
return answer === 'y' || answer === 'yes';
|
|
42
|
+
} finally {
|
|
43
|
+
rl.close();
|
|
44
|
+
}
|
|
45
|
+
}
|
package/lib/scaffold.js
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import { SITE_URL, STACK_LABELS } from './options.js';
|
|
2
|
+
|
|
3
|
+
function stackDocsUrl(stack) {
|
|
4
|
+
const map = {
|
|
5
|
+
react: `${SITE_URL}/docs/cookbook/react/README`,
|
|
6
|
+
nextjs: `${SITE_URL}/docs/cookbook/nextjs/README`,
|
|
7
|
+
'react-native': `${SITE_URL}/docs/cookbook/react-native/README`,
|
|
8
|
+
nodejs: `${SITE_URL}/docs/cookbook/node/README`,
|
|
9
|
+
python: `${SITE_URL}/docs/cookbook/python/README`,
|
|
10
|
+
java: `${SITE_URL}/docs/cookbook/java/README`,
|
|
11
|
+
dotnet: `${SITE_URL}/docs/cookbook/dotnet/README`,
|
|
12
|
+
};
|
|
13
|
+
return map[stack] ?? `${SITE_URL}/docs/cookbook/README`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function idePlacementGuide(ide) {
|
|
17
|
+
switch (ide) {
|
|
18
|
+
case 'cursor':
|
|
19
|
+
return `### Cursor
|
|
20
|
+
- Project rules: \`.cursor/rules/aies.mdc\`
|
|
21
|
+
- Attach \`.aies/implementation_plan.md\` before coding`;
|
|
22
|
+
case 'claude-code':
|
|
23
|
+
return `### Claude Code
|
|
24
|
+
- \`CLAUDE.md\` at repo root
|
|
25
|
+
- Skills under \`.aies/skills/\``;
|
|
26
|
+
case 'copilot':
|
|
27
|
+
return `### GitHub Copilot
|
|
28
|
+
- \`.github/copilot-instructions.md\`
|
|
29
|
+
- Human PR review remains accountable`;
|
|
30
|
+
case 'vscode':
|
|
31
|
+
return `### VS Code
|
|
32
|
+
- \`.vscode/aies-instructions.md\``;
|
|
33
|
+
case 'windsurf':
|
|
34
|
+
return `### Windsurf
|
|
35
|
+
- \`.windsurfrules\``;
|
|
36
|
+
case 'continue':
|
|
37
|
+
return `### Continue
|
|
38
|
+
- See \`.aies/ide/continue-config.snippet.json\``;
|
|
39
|
+
default:
|
|
40
|
+
return '### IDE\n- Use `.aies/` as the project AI harness folder.';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function buildContextFile(profile, label) {
|
|
45
|
+
return `# AIES project context
|
|
46
|
+
|
|
47
|
+
This repository uses the Open AI Engineering Standard (AIES) harness.
|
|
48
|
+
|
|
49
|
+
- Stack: ${label}
|
|
50
|
+
- Role profile: ${profile.role}
|
|
51
|
+
- Maturity: ${profile.maturity}
|
|
52
|
+
- IDE: ${profile.ide}
|
|
53
|
+
|
|
54
|
+
## Non-negotiables
|
|
55
|
+
|
|
56
|
+
1. Plan before multi-file coding (\`.aies/implementation_plan.md\`)
|
|
57
|
+
2. Human review is accountable — AI output is advisory
|
|
58
|
+
3. No secrets in prompts, logs, or MCP tool args
|
|
59
|
+
4. Prefer stack skill + AIDLC prompts over ad-hoc chat
|
|
60
|
+
|
|
61
|
+
## Start here
|
|
62
|
+
|
|
63
|
+
1. Read \`.aies/README.md\`
|
|
64
|
+
2. Fill \`.aies/implementation_plan.md\`
|
|
65
|
+
3. Open the matching workflow: ${SITE_URL}/workflows
|
|
66
|
+
4. Stack cookbook: ${stackDocsUrl(profile.stack)}
|
|
67
|
+
|
|
68
|
+
## Corpus (online)
|
|
69
|
+
|
|
70
|
+
- Handbook: ${SITE_URL}/docs/handbook/README
|
|
71
|
+
- Hooks: ${SITE_URL}/docs/04-agent-engineering/hooks/README
|
|
72
|
+
- MCP: ${SITE_URL}/docs/handbook/mcp-when-and-how
|
|
73
|
+
`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @param {{ goal: string, role: string, maturity: string, ide: string, stack: string }} profile
|
|
78
|
+
* @returns {{ stack: string, generatedAt: string, profile: object, files: Record<string, string> }}
|
|
79
|
+
*/
|
|
80
|
+
export function generateStarterKit(profile) {
|
|
81
|
+
const label = STACK_LABELS[profile.stack] ?? profile.stack;
|
|
82
|
+
const now = new Date().toISOString();
|
|
83
|
+
const flagArgs = [
|
|
84
|
+
`--stack ${profile.stack}`,
|
|
85
|
+
`--ide ${profile.ide}`,
|
|
86
|
+
`--role ${profile.role}`,
|
|
87
|
+
`--maturity ${profile.maturity}`,
|
|
88
|
+
`--goal ${profile.goal}`,
|
|
89
|
+
].join(' ');
|
|
90
|
+
|
|
91
|
+
const readme = `# AIES Starter Kit — ${label}
|
|
92
|
+
|
|
93
|
+
**This folder is your project harness.** It is not the full AIES corpus.
|
|
94
|
+
|
|
95
|
+
Generated: ${now}
|
|
96
|
+
Profile: **${profile.role}** · **${profile.ide}** · **${profile.maturity}** · **${label}**
|
|
97
|
+
|
|
98
|
+
## What got installed
|
|
99
|
+
|
|
100
|
+
| Path | Purpose |
|
|
101
|
+
|------|---------|
|
|
102
|
+
| \`.aies/implementation_plan.md\` | Plan of record before coding |
|
|
103
|
+
| \`.aies/prompts/\` | Pasteable AIDLC prompts |
|
|
104
|
+
| \`.aies/skills/\` | Procedural skills for agents |
|
|
105
|
+
| \`.aies/mcp.json\` | Example MCP config (edit before enabling) |
|
|
106
|
+
| \`.aies/agentHooks.json\` | Hook map — wire to real scripts from the corpus |
|
|
107
|
+
| IDE context file | Rules/instructions for ${profile.ide} |
|
|
108
|
+
|
|
109
|
+
## How to use (5 minutes)
|
|
110
|
+
|
|
111
|
+
1. Confirm you are in your **app repo root**
|
|
112
|
+
2. Fill \`.aies/implementation_plan.md\`
|
|
113
|
+
3. Attach that plan in IDE chat before generating code
|
|
114
|
+
4. Do not enable MCPs until you read: ${SITE_URL}/docs/handbook/mcp-when-and-how
|
|
115
|
+
5. Continue your lifecycle: ${SITE_URL}/workflows
|
|
116
|
+
|
|
117
|
+
${idePlacementGuide(profile.ide)}
|
|
118
|
+
|
|
119
|
+
## Re-install / upgrade
|
|
120
|
+
|
|
121
|
+
\`\`\`bash
|
|
122
|
+
npx @grvmithas/create-aies-kit ${flagArgs} --force
|
|
123
|
+
\`\`\`
|
|
124
|
+
|
|
125
|
+
## Not enough alone
|
|
126
|
+
|
|
127
|
+
For production teams you still need HITL gates, eval/CI gates, and an MCP allowlist.
|
|
128
|
+
|
|
129
|
+
Quick start: ${SITE_URL}/quickstart
|
|
130
|
+
Cookbook: ${stackDocsUrl(profile.stack)}
|
|
131
|
+
`;
|
|
132
|
+
|
|
133
|
+
const implementationPlan = `# Implementation Plan
|
|
134
|
+
|
|
135
|
+
> AIES plan of record. Approve this before multi-file coding.
|
|
136
|
+
|
|
137
|
+
## Goal
|
|
138
|
+
|
|
139
|
+
<!-- One sentence outcome -->
|
|
140
|
+
|
|
141
|
+
## Scope
|
|
142
|
+
|
|
143
|
+
### In scope
|
|
144
|
+
|
|
145
|
+
-
|
|
146
|
+
|
|
147
|
+
### Out of scope
|
|
148
|
+
|
|
149
|
+
-
|
|
150
|
+
|
|
151
|
+
## Architecture touchpoints
|
|
152
|
+
|
|
153
|
+
-
|
|
154
|
+
|
|
155
|
+
## Tasks
|
|
156
|
+
|
|
157
|
+
| ID | Task | Verification | Owner |
|
|
158
|
+
|----|------|--------------|-------|
|
|
159
|
+
| 1 | | | |
|
|
160
|
+
|
|
161
|
+
## Risks
|
|
162
|
+
|
|
163
|
+
-
|
|
164
|
+
|
|
165
|
+
## Rollback
|
|
166
|
+
|
|
167
|
+
-
|
|
168
|
+
|
|
169
|
+
## Human approval
|
|
170
|
+
|
|
171
|
+
- [ ] Plan approved by:
|
|
172
|
+
- [ ] Date:
|
|
173
|
+
`;
|
|
174
|
+
|
|
175
|
+
const storyKickoffSkill = `---
|
|
176
|
+
name: story-kickoff
|
|
177
|
+
description: Frame a bounded story before implementation
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
# Story kickoff
|
|
181
|
+
|
|
182
|
+
## Inputs
|
|
183
|
+
- Ticket / user story
|
|
184
|
+
- Acceptance criteria
|
|
185
|
+
- Non-goals
|
|
186
|
+
|
|
187
|
+
## Procedure
|
|
188
|
+
1. Restate the problem in one paragraph
|
|
189
|
+
2. List constraints (security, perf, compliance)
|
|
190
|
+
3. Propose the smallest verifiable slice
|
|
191
|
+
4. Stop for human approval before writing the plan file
|
|
192
|
+
|
|
193
|
+
## Online prompt
|
|
194
|
+
${SITE_URL}/docs/08-ai-sdlc/prompts/story-kickoff.prompt
|
|
195
|
+
`;
|
|
196
|
+
|
|
197
|
+
const implementationPrompt = `# Implementation prompt
|
|
198
|
+
|
|
199
|
+
Use with the approved \`.aies/implementation_plan.md\` attached.
|
|
200
|
+
|
|
201
|
+
1. Restate the plan boundaries
|
|
202
|
+
2. Implement only in-scope tasks
|
|
203
|
+
3. Add/adjust tests for verification column
|
|
204
|
+
4. Do not invent integrations outside the plan
|
|
205
|
+
5. Summarize files changed and residual risks
|
|
206
|
+
|
|
207
|
+
Online: ${SITE_URL}/docs/08-ai-sdlc/prompts/implementation-plan.prompt
|
|
208
|
+
Stack cookbook: ${stackDocsUrl(profile.stack)}
|
|
209
|
+
`;
|
|
210
|
+
|
|
211
|
+
const codeReviewPrompt = `# Code review prompt
|
|
212
|
+
|
|
213
|
+
Human reviewer is accountable. AI output is advisory only.
|
|
214
|
+
|
|
215
|
+
Review for:
|
|
216
|
+
- Correctness vs plan
|
|
217
|
+
- Security / secrets / injection
|
|
218
|
+
- Missing tests
|
|
219
|
+
- Maintainability
|
|
220
|
+
|
|
221
|
+
Online: ${SITE_URL}/docs/08-ai-sdlc/prompts/security-review.prompt
|
|
222
|
+
`;
|
|
223
|
+
|
|
224
|
+
const debugSkill = `---
|
|
225
|
+
name: debug
|
|
226
|
+
description: Systematic debug for ${label}
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
1. Reproduce with a minimal failing case
|
|
230
|
+
2. Form a hypothesis
|
|
231
|
+
3. Change one variable at a time
|
|
232
|
+
4. Capture evidence before asking for a large rewrite
|
|
233
|
+
|
|
234
|
+
Online: ${SITE_URL}/docs/03-skill-engineering/skills/debug.skill
|
|
235
|
+
`;
|
|
236
|
+
|
|
237
|
+
const devopsSkill = `---
|
|
238
|
+
name: devops
|
|
239
|
+
description: Release and pipeline discipline
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
1. Prefer automated gates over manual checklists alone
|
|
243
|
+
2. Canary / feature flags for risky paths
|
|
244
|
+
3. Rollback verified before production promote
|
|
245
|
+
|
|
246
|
+
Online: ${SITE_URL}/docs/03-skill-engineering/skills/devops.skill
|
|
247
|
+
`;
|
|
248
|
+
|
|
249
|
+
const mcpJson = JSON.stringify(
|
|
250
|
+
{
|
|
251
|
+
mcpServers: {},
|
|
252
|
+
_aies: {
|
|
253
|
+
note: 'Empty by default. Add only org-approved servers after reading MCP when-and-how.',
|
|
254
|
+
guide: `${SITE_URL}/docs/handbook/mcp-when-and-how`,
|
|
255
|
+
catalog: `${SITE_URL}/docs/mcps/README`,
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
null,
|
|
259
|
+
2,
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
const agentHooksJson = JSON.stringify(
|
|
263
|
+
{
|
|
264
|
+
version: '1',
|
|
265
|
+
hooks: [
|
|
266
|
+
{
|
|
267
|
+
id: 'pre-planning',
|
|
268
|
+
phase: 'before-plan',
|
|
269
|
+
requiredEvidence: ['requirements-path', 'risk-tier'],
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
id: 'pre-code',
|
|
273
|
+
phase: 'before-code',
|
|
274
|
+
requiredEvidence: ['approved-plan-path'],
|
|
275
|
+
},
|
|
276
|
+
],
|
|
277
|
+
_aies: {
|
|
278
|
+
note: 'Wire these phases to shell hooks from the AIES corpus when you adopt the full harness.',
|
|
279
|
+
hooksGuide: `${SITE_URL}/docs/04-agent-engineering/hooks/README`,
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
null,
|
|
283
|
+
2,
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
const commands = `# Useful next commands
|
|
287
|
+
|
|
288
|
+
npx @grvmithas/create-aies-kit ${flagArgs} --force
|
|
289
|
+
|
|
290
|
+
# Then open:
|
|
291
|
+
# ${SITE_URL}/quickstart
|
|
292
|
+
# ${SITE_URL}/workflows
|
|
293
|
+
`;
|
|
294
|
+
|
|
295
|
+
const context = buildContextFile(profile, label);
|
|
296
|
+
/** @type {Record<string, string>} */
|
|
297
|
+
const files = {
|
|
298
|
+
'.aies/README.md': readme,
|
|
299
|
+
'.aies/implementation_plan.md': implementationPlan,
|
|
300
|
+
'.aies/skills/story-kickoff.skill.md': storyKickoffSkill,
|
|
301
|
+
'.aies/prompts/implementation.prompt.md': implementationPrompt,
|
|
302
|
+
'.aies/prompts/code-review.prompt.md': codeReviewPrompt,
|
|
303
|
+
'.aies/skills/debug.skill.md': debugSkill,
|
|
304
|
+
'.aies/skills/devops.skill.md': devopsSkill,
|
|
305
|
+
'.aies/mcp.json': mcpJson,
|
|
306
|
+
'.aies/agentHooks.json': agentHooksJson,
|
|
307
|
+
'.aies/commands.md': commands,
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
switch (profile.ide) {
|
|
311
|
+
case 'cursor':
|
|
312
|
+
files['.cursor/rules/aies.mdc'] = `---
|
|
313
|
+
description: AIES project harness rules
|
|
314
|
+
globs:
|
|
315
|
+
alwaysApply: true
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
${context}
|
|
319
|
+
`;
|
|
320
|
+
break;
|
|
321
|
+
case 'claude-code':
|
|
322
|
+
files['CLAUDE.md'] = context;
|
|
323
|
+
break;
|
|
324
|
+
case 'copilot':
|
|
325
|
+
files['.github/copilot-instructions.md'] = context;
|
|
326
|
+
break;
|
|
327
|
+
case 'vscode':
|
|
328
|
+
files['.vscode/aies-instructions.md'] = context;
|
|
329
|
+
break;
|
|
330
|
+
case 'windsurf':
|
|
331
|
+
files['.windsurfrules'] = context;
|
|
332
|
+
break;
|
|
333
|
+
case 'continue':
|
|
334
|
+
files['.aies/ide/continue-context.md'] = context;
|
|
335
|
+
files['.aies/ide/continue-config.snippet.json'] = JSON.stringify(
|
|
336
|
+
{
|
|
337
|
+
comment: 'Merge into your Continue config — do not overwrite blindly',
|
|
338
|
+
contextProviders: [{ name: 'file', params: { path: '.aies' } }],
|
|
339
|
+
},
|
|
340
|
+
null,
|
|
341
|
+
2,
|
|
342
|
+
);
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
return {
|
|
347
|
+
stack: profile.stack,
|
|
348
|
+
generatedAt: now,
|
|
349
|
+
profile: { ...profile },
|
|
350
|
+
files,
|
|
351
|
+
};
|
|
352
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@grvmithas/create-aies-kit",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Scaffold an AIES (AI Engineering Standard) starter kit into your project — prompts, skills, MCP stubs, and IDE rules.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"create-aies-kit": "bin/create-aies-kit.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin",
|
|
12
|
+
"lib",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE"
|
|
15
|
+
],
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=18"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"aies",
|
|
21
|
+
"ai-engineering",
|
|
22
|
+
"starter-kit",
|
|
23
|
+
"cursor",
|
|
24
|
+
"claude-code",
|
|
25
|
+
"copilot",
|
|
26
|
+
"mcp",
|
|
27
|
+
"aidlc",
|
|
28
|
+
"create-aies-kit"
|
|
29
|
+
],
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/grvmithas/open-ai-engineering-standards.git",
|
|
33
|
+
"directory": "packages/create-aies-kit"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://open-ai-engineering-standards.vercel.app/quickstart",
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/grvmithas/open-ai-engineering-standards/issues"
|
|
38
|
+
},
|
|
39
|
+
"author": "Gaurav Mithas",
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
}
|
|
43
|
+
}
|