@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
|
@@ -0,0 +1,693 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { EMBEDDED_CORPUS } from './embedded-corpus.js';
|
|
3
|
+
import {
|
|
4
|
+
MCP_SPECS,
|
|
5
|
+
buildRecommendedMcpConfig,
|
|
6
|
+
detectRepoSignals,
|
|
7
|
+
stackMcpIds,
|
|
8
|
+
} from './mcp-catalog.js';
|
|
9
|
+
import { describeInstallLayout, layoutFor } from './install-api.js';
|
|
10
|
+
import { SITE_URL, STACK_LABELS, STACKS } from './options.js';
|
|
11
|
+
|
|
12
|
+
export { buildInstallQuery, describeInstallLayout, getInstallCommands, layoutFor } from './install-api.js';
|
|
13
|
+
|
|
14
|
+
const CORE_SKILLS = [
|
|
15
|
+
'planning',
|
|
16
|
+
'debug',
|
|
17
|
+
'devops',
|
|
18
|
+
'code-review',
|
|
19
|
+
'evaluation',
|
|
20
|
+
'security',
|
|
21
|
+
'testing',
|
|
22
|
+
'architecture',
|
|
23
|
+
'context',
|
|
24
|
+
'prompt',
|
|
25
|
+
'documentation',
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
const CORE_PROMPTS = [
|
|
29
|
+
'story-kickoff',
|
|
30
|
+
'implementation-plan',
|
|
31
|
+
'coding',
|
|
32
|
+
'security-review',
|
|
33
|
+
'enhance-repo',
|
|
34
|
+
'create-prompt',
|
|
35
|
+
'create-skill',
|
|
36
|
+
'create-agent',
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
const CORE_AGENTS = ['planner', 'coder', 'reviewer', 'prompt-engineer'];
|
|
40
|
+
|
|
41
|
+
function corpus(key) {
|
|
42
|
+
const body = EMBEDDED_CORPUS[key];
|
|
43
|
+
if (!body) {
|
|
44
|
+
return `<!-- Missing embedded corpus: ${key}. Re-run: npm run kit:embed -->\n`;
|
|
45
|
+
}
|
|
46
|
+
return body;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function stackMeta(stack) {
|
|
50
|
+
return STACKS.find(s => s.id === stack) ?? { id: stack, label: stack, skillKey: null, cookbook: null };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function stripFrontmatter(md) {
|
|
54
|
+
if (!md.startsWith('---')) return md;
|
|
55
|
+
const end = md.indexOf('\n---', 3);
|
|
56
|
+
if (end === -1) return md;
|
|
57
|
+
return md.slice(end + 4).replace(/^\s+/, '');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function skillDescription(name, body) {
|
|
61
|
+
const purpose = body.match(/## Purpose\s*\n+([^\n]+)/);
|
|
62
|
+
if (purpose) return purpose[1].trim().slice(0, 180);
|
|
63
|
+
return `AIES ${name} skill — use when this procedure applies.`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function writeSkill(files, L, name, body) {
|
|
67
|
+
if (L.skillStyle === 'cursor-skill') {
|
|
68
|
+
const cleaned = stripFrontmatter(body);
|
|
69
|
+
const desc = skillDescription(name, body).replace(/"/g, "'").replace(/\r?\n/g, ' ');
|
|
70
|
+
files[`${L.skillsDir}/${name}/SKILL.md`] = `---
|
|
71
|
+
name: ${name}
|
|
72
|
+
description: "${desc}"
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
${cleaned}
|
|
76
|
+
`;
|
|
77
|
+
} else {
|
|
78
|
+
files[`${L.skillsDir}/${name}.skill.md`] = body;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function modelPolicy(profile) {
|
|
83
|
+
const model = profile.model ?? 'undecided';
|
|
84
|
+
const dataClass = profile.dataClass ?? 'internal';
|
|
85
|
+
return `# Model & data policy (AIES)
|
|
86
|
+
|
|
87
|
+
Generated for: **${model}** · data class **${dataClass}**
|
|
88
|
+
|
|
89
|
+
## Provider posture
|
|
90
|
+
|
|
91
|
+
| Choice | Guidance |
|
|
92
|
+
|--------|----------|
|
|
93
|
+
| claude / gpt / gemini | Pin model IDs in CI and agent configs; record versions in PRs that change prompts |
|
|
94
|
+
| multi | Route via an org gateway; do not hard-code vendor SDKs in feature code without an abstraction |
|
|
95
|
+
| local | Keep offline evals; never assume cloud tool APIs exist |
|
|
96
|
+
| undecided | Default to least privilege; pick a primary model before production |
|
|
97
|
+
|
|
98
|
+
## Data class rules (${dataClass})
|
|
99
|
+
|
|
100
|
+
${
|
|
101
|
+
dataClass === 'public'
|
|
102
|
+
? '- Public data may use cloud models with org-approved logging.\n- Still ban secrets in prompts.'
|
|
103
|
+
: dataClass === 'confidential'
|
|
104
|
+
? '- Confidential/regulated: prefer private endpoints / VPC; disable training opt-in.\n- No production PII in prompts, traces, or MCP tool args.\n- MCP servers stay empty until security approves allowlist.\n- Require HITL for any tool that can write external systems.'
|
|
105
|
+
: '- Internal data: use org-approved providers only.\n- Redact secrets and customer identifiers from prompts and logs.\n- MCP: enable only from \`_aiesRecommended\` after handbook review.'
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
## Non-negotiables
|
|
109
|
+
|
|
110
|
+
1. Human review is accountable — model output is advisory
|
|
111
|
+
2. Fill \`implementation_plan.md\` before multi-file coding
|
|
112
|
+
3. Keep \`mcpServers: {}\` until a human enables approved stubs
|
|
113
|
+
4. Eval gates for AI-touched paths before production
|
|
114
|
+
|
|
115
|
+
Online: ${SITE_URL}/docs/handbook/mcp-when-and-how
|
|
116
|
+
`;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function maturityReadingPath(maturity) {
|
|
120
|
+
if (maturity === 'beginner') {
|
|
121
|
+
return `1. \`guides/skills-vs-prompts-vs-agents.md\` + \`guides/human-in-the-loop.md\`
|
|
122
|
+
2. Fill \`implementation_plan.md\` using \`prompts/implementation-plan.prompt.md\`
|
|
123
|
+
3. Run **enhance** (below) so artifacts match this repo
|
|
124
|
+
4. Use cookbook generate → coding → review
|
|
125
|
+
5. Online: ${SITE_URL}/docs/handbook/README`;
|
|
126
|
+
}
|
|
127
|
+
if (maturity === 'intermediate') {
|
|
128
|
+
return `1. Fill plan → enhance repo → cookbook generate/review
|
|
129
|
+
2. Wire \`guides/evals-as-quality-gates.md\` into CI
|
|
130
|
+
3. Enable MCP only from recommended stubs after review
|
|
131
|
+
4. Online: ${SITE_URL}/workflows`;
|
|
132
|
+
}
|
|
133
|
+
if (maturity === 'advanced') {
|
|
134
|
+
return `1. Enhance repo + MCP handbook
|
|
135
|
+
2. Compose agents (planner → coder → reviewer) with budgets
|
|
136
|
+
3. Security skill before write tools
|
|
137
|
+
4. Online: ${SITE_URL}/docs/04-agent-engineering/README`;
|
|
138
|
+
}
|
|
139
|
+
return `1. Enhance repo + SoA mapping (${SITE_URL}/portal)
|
|
140
|
+
2. Migration bible: ${SITE_URL}/docs/handbook/ai-migration-bible-path
|
|
141
|
+
3. Eval CI + MCP allowlists + segregation of duties
|
|
142
|
+
4. Enterprise evidence retained on PRs`;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function roleNext(role) {
|
|
146
|
+
const map = {
|
|
147
|
+
'product-manager': 'idea',
|
|
148
|
+
architect: 'architecture',
|
|
149
|
+
frontend: 'ai-coding',
|
|
150
|
+
backend: 'ai-coding',
|
|
151
|
+
fullstack: 'implementation-planning',
|
|
152
|
+
qa: 'testing',
|
|
153
|
+
devops: 'devops',
|
|
154
|
+
'engineering-manager': 'project-kickoff',
|
|
155
|
+
'ai-engineer': 'implementation-planning',
|
|
156
|
+
};
|
|
157
|
+
return map[role] ?? 'implementation-planning';
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function cookbookKeys(cookbookId) {
|
|
161
|
+
const prefix = `cookbook/${cookbookId}/`;
|
|
162
|
+
return Object.keys(EMBEDDED_CORPUS)
|
|
163
|
+
.filter(k => k.startsWith(prefix))
|
|
164
|
+
.sort();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function pathBasename(p) {
|
|
168
|
+
const parts = p.split('/');
|
|
169
|
+
return parts[parts.length - 1] ?? p;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function skillPath(L, name) {
|
|
173
|
+
return L.skillStyle === 'cursor-skill' ? `${L.skillsDir}/${name}/SKILL.md` : `${L.skillsDir}/${name}.skill.md`;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function buildRootInstructions(profile, label, L) {
|
|
177
|
+
return `# AIES project instructions — ${label}
|
|
178
|
+
|
|
179
|
+
This repository uses the **AI Engineering Standard (AIES)** harness.
|
|
180
|
+
|
|
181
|
+
## Profile
|
|
182
|
+
|
|
183
|
+
- Stack: ${label}
|
|
184
|
+
- Role: ${profile.role}
|
|
185
|
+
- Maturity: ${profile.maturity} (docs reading path only)
|
|
186
|
+
- Primary IDE selection: ${profile.ide}
|
|
187
|
+
- Model: ${profile.model ?? 'undecided'}
|
|
188
|
+
- Data class: ${profile.dataClass ?? 'internal'}
|
|
189
|
+
|
|
190
|
+
## Non-negotiables
|
|
191
|
+
|
|
192
|
+
1. Read \`AIES.md\` before coding with AI
|
|
193
|
+
2. Fill and approve \`implementation_plan.md\` before multi-file changes
|
|
194
|
+
3. Prefer installed skills/prompts/cookbook over ad-hoc chat
|
|
195
|
+
4. Human owns merges — AI is advisory
|
|
196
|
+
5. No secrets in prompts, logs, or MCP args
|
|
197
|
+
6. Keep MCP \`mcpServers\` empty until a human enables stubs from \`_aiesRecommended\`
|
|
198
|
+
|
|
199
|
+
## Where to look
|
|
200
|
+
|
|
201
|
+
| Need | Path |
|
|
202
|
+
|------|------|
|
|
203
|
+
| Operator guide | \`AIES.md\` |
|
|
204
|
+
| Plan of record | \`implementation_plan.md\` |
|
|
205
|
+
| Skills | \`${L.skillsDir}/\` |
|
|
206
|
+
| Prompts | \`${L.promptsDir}/\` |
|
|
207
|
+
| Stack cookbook | \`${L.cookbookDir}/\` |
|
|
208
|
+
| Agents | \`${L.agentsDir}/\` |
|
|
209
|
+
| MCP specs | \`${L.mcpsDir}/\` |
|
|
210
|
+
| MCP config | \`${L.mcpFile}\` |
|
|
211
|
+
| Policy | \`${L.policyFile}\` |
|
|
212
|
+
|
|
213
|
+
## First commands after install
|
|
214
|
+
|
|
215
|
+
\`\`\`bash
|
|
216
|
+
npx @grvmithas/create-aies-kit enhance
|
|
217
|
+
\`\`\`
|
|
218
|
+
|
|
219
|
+
Then open \`${L.promptsDir}/enhance-repo.prompt.md\` in your IDE agent and run it against this repo.
|
|
220
|
+
|
|
221
|
+
## Workflow
|
|
222
|
+
|
|
223
|
+
Plan (\`implementation-plan\`) → Enhance → Cookbook generate → Coding → Review → Security (as needed)
|
|
224
|
+
`;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function buildAiesReadme({ profile, label, L, stack, flags, now, recommendedIds }) {
|
|
228
|
+
const model = profile.model ?? 'undecided';
|
|
229
|
+
const dataClass = profile.dataClass ?? 'internal';
|
|
230
|
+
const enhancePrompt = `${L.promptsDir}/enhance-repo.prompt.md`;
|
|
231
|
+
|
|
232
|
+
return `# AIES — Operator guide (${label})
|
|
233
|
+
|
|
234
|
+
**Generated:** ${now}
|
|
235
|
+
**Profile:** ${profile.role} · ${profile.ide} · ${profile.maturity} · ${label} · model **${model}** · data **${dataClass}**
|
|
236
|
+
|
|
237
|
+
This install is **always complete**. Maturity only changes the reading path — not which files were written.
|
|
238
|
+
There is **no** \`.aies/\` folder. Artifacts live in IDE-native paths plus root instruction files.
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## 0. Start from the word go (do this first)
|
|
243
|
+
|
|
244
|
+
1. **Read this file** (AIES.md).
|
|
245
|
+
2. **Enhance for *this* repo** (adapts skills/prompts/MCP/rules to your conventions):
|
|
246
|
+
|
|
247
|
+
\`\`\`bash
|
|
248
|
+
npx @grvmithas/create-aies-kit enhance
|
|
249
|
+
\`\`\`
|
|
250
|
+
|
|
251
|
+
3. In your IDE agent, open and run:
|
|
252
|
+
|
|
253
|
+
\`${enhancePrompt}\`
|
|
254
|
+
|
|
255
|
+
That prompt scans the repo and upgrades installed artifacts (and may create new files) so you can develop immediately.
|
|
256
|
+
|
|
257
|
+
4. Fill \`implementation_plan.md\` (see §1) and get human approval.
|
|
258
|
+
5. Use the right prompt + skill (§2–§3), then code.
|
|
259
|
+
|
|
260
|
+
**Re-install kit (force):**
|
|
261
|
+
|
|
262
|
+
\`\`\`bash
|
|
263
|
+
npx @grvmithas/create-aies-kit ${flags} --force
|
|
264
|
+
\`\`\`
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## 1. How to create and use \`implementation_plan.md\`
|
|
269
|
+
|
|
270
|
+
### Create / fill
|
|
271
|
+
|
|
272
|
+
1. Open root \`implementation_plan.md\`.
|
|
273
|
+
2. Attach \`${L.promptsDir}/implementation-plan.prompt.md\` in chat (or run the **planning** skill).
|
|
274
|
+
3. Also load \`${L.guidesDir}/how-to-set-up-planning.md\`.
|
|
275
|
+
4. Fill: Goal, In/Out of scope, Tasks with verification, Risks, Rollback, Human approval.
|
|
276
|
+
|
|
277
|
+
### Use
|
|
278
|
+
|
|
279
|
+
- **Before** any multi-file AI coding: plan must be filled and approved.
|
|
280
|
+
- Attach the plan file in every coding session for that slice.
|
|
281
|
+
- Update the plan when scope changes — do not silently expand.
|
|
282
|
+
|
|
283
|
+
### Anti-patterns
|
|
284
|
+
|
|
285
|
+
- Coding from a chat transcript with no plan file
|
|
286
|
+
- Approving your own high-risk plan without a second human when policy requires it
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## 2. How to use the right prompts
|
|
291
|
+
|
|
292
|
+
| Situation | Prompt |
|
|
293
|
+
|-----------|--------|
|
|
294
|
+
| New story / kickoff | \`${L.promptsDir}/story-kickoff.prompt.md\` |
|
|
295
|
+
| Build the plan | \`${L.promptsDir}/implementation-plan.prompt.md\` |
|
|
296
|
+
| Implement approved plan | \`${L.promptsDir}/coding.prompt.md\` |
|
|
297
|
+
| Security pass | \`${L.promptsDir}/security-review.prompt.md\` |
|
|
298
|
+
| Adapt harness to this repo | \`${enhancePrompt}\` |
|
|
299
|
+
| Author a new prompt | \`${L.promptsDir}/create-prompt.prompt.md\` |
|
|
300
|
+
| Author a new skill | \`${L.promptsDir}/create-skill.prompt.md\` |
|
|
301
|
+
| Author a new agent | \`${L.promptsDir}/create-agent.prompt.md\` |
|
|
302
|
+
| Stack generate / review / debug | \`${L.cookbookDir}/prompts/\` |
|
|
303
|
+
|
|
304
|
+
**Rule:** Prefer cookbook prompts for stack-idiomatic work; prefer AIDLC prompts for lifecycle gates.
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## 3. How to use the right skills
|
|
309
|
+
|
|
310
|
+
| Situation | Skill |
|
|
311
|
+
|-----------|--------|
|
|
312
|
+
| Multi-step plan | \`${skillPath(L, 'planning')}\` |
|
|
313
|
+
| Bug / incident | \`${skillPath(L, 'debug')}\` |
|
|
314
|
+
| PR review | \`${skillPath(L, 'code-review')}\` |
|
|
315
|
+
| Tests | \`${skillPath(L, 'testing')}\` |
|
|
316
|
+
| Architecture / ADR | \`${skillPath(L, 'architecture')}\` |
|
|
317
|
+
| Context packing | \`${skillPath(L, 'context')}\` |
|
|
318
|
+
| CI/CD / release | \`${skillPath(L, 'devops')}\` |
|
|
319
|
+
| Eval gates | \`${skillPath(L, 'evaluation')}\` |
|
|
320
|
+
| Threat / AuthZ | \`${skillPath(L, 'security')}\` |
|
|
321
|
+
| Write better prompts | \`${skillPath(L, 'prompt')}\` |
|
|
322
|
+
| Docs | \`${skillPath(L, 'documentation')}\` |
|
|
323
|
+
| Stack-specific | skill under \`${L.skillsDir}/\` matching ${label} |
|
|
324
|
+
|
|
325
|
+
**Cursor:** skills are \`.cursor/skills/{name}/SKILL.md\` (auto-discoverable).
|
|
326
|
+
**Copilot / VS Code:** open the \`.skill.md\` file and attach it.
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## 4. Agents
|
|
331
|
+
|
|
332
|
+
| Agent | Path | Use when |
|
|
333
|
+
|-------|------|----------|
|
|
334
|
+
| Planner | \`${L.agentsDir}/planner.agent.md\` | Complex multi-file planning |
|
|
335
|
+
| Coder | \`${L.agentsDir}/coder.agent.md\` | Execution against an approved plan |
|
|
336
|
+
| Reviewer | \`${L.agentsDir}/reviewer.agent.md\` | Severity-calibrated review |
|
|
337
|
+
| Prompt engineer | \`${L.agentsDir}/prompt-engineer.agent.md\` | Designing new prompts/skills |
|
|
338
|
+
|
|
339
|
+
Compose agents; do not give them merge authority.
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
## 5. MCP connections (relevant + safe)
|
|
344
|
+
|
|
345
|
+
Specs (all catalog entries shipped): \`${L.mcpsDir}/\`
|
|
346
|
+
Config: \`${L.mcpFile}\`
|
|
347
|
+
|
|
348
|
+
- \`mcpServers\` starts **empty** (safe default).
|
|
349
|
+
- \`_aiesRecommended\` lists enable-ready stubs for this stack/profile: **${recommendedIds.join(', ')}**
|
|
350
|
+
- After \`enhance\`, recommendations update from repo signals (Docker, Playwright, Postgres, etc.).
|
|
351
|
+
- To enable: copy a stub from \`_aiesRecommended\` → \`mcpServers\`, set env secrets outside git, re-read \`${L.guidesDir}/mcp-when-and-how.md\`.
|
|
352
|
+
|
|
353
|
+
**Never** commit tokens. Prefer read-only scopes first.
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## 6. Root instruction files (always present)
|
|
358
|
+
|
|
359
|
+
| File | Role |
|
|
360
|
+
|------|------|
|
|
361
|
+
| \`CLAUDE.md\` | Claude Code / multi-IDE contract at repo root |
|
|
362
|
+
| \`AGENTS.md\` | Agent-oriented project contract (Cursor/Codex-compatible) |
|
|
363
|
+
| \`copilot-instructions.md\` | Copilot-oriented instructions at repo root |
|
|
364
|
+
| \`.github/copilot-instructions.md\` | Same content for GitHub Copilot discovery |
|
|
365
|
+
| \`${L.rulesFile}\` | Primary IDE rules for **${profile.ide}** |
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
## 7. Layout (${profile.ide})
|
|
370
|
+
|
|
371
|
+
| Path | Purpose |
|
|
372
|
+
|------|---------|
|
|
373
|
+
| \`AIES.md\` | This operator guide |
|
|
374
|
+
| \`implementation_plan.md\` | Plan of record |
|
|
375
|
+
| \`${L.skillsDir}/\` | Skills (complete) |
|
|
376
|
+
| \`${L.promptsDir}/\` | AIDLC + create/enhance prompts |
|
|
377
|
+
| \`${L.cookbookDir}/\` | Full stack cookbook |
|
|
378
|
+
| \`${L.agentsDir}/\` | Agent definitions |
|
|
379
|
+
| \`${L.mcpsDir}/\` | MCP integration specs |
|
|
380
|
+
| \`${L.guidesDir}/\` | Handbook slices |
|
|
381
|
+
| \`${L.templatesDir}/\` | System prompt template |
|
|
382
|
+
| \`${L.policyFile}\` | Model + data policy |
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## 8. Reading path (${profile.maturity})
|
|
387
|
+
|
|
388
|
+
${maturityReadingPath(profile.maturity)}
|
|
389
|
+
|
|
390
|
+
## 9. Role next workflow
|
|
391
|
+
|
|
392
|
+
${SITE_URL}/workflows/${roleNext(profile.role)}
|
|
393
|
+
|
|
394
|
+
## 10. Online
|
|
395
|
+
|
|
396
|
+
- Quick start: ${SITE_URL}/quickstart
|
|
397
|
+
- Cookbook: ${SITE_URL}/docs/cookbook/${stack.cookbook ?? 'README'}/README
|
|
398
|
+
- MCP handbook: ${SITE_URL}/docs/handbook/mcp-when-and-how
|
|
399
|
+
- Workflows: ${SITE_URL}/workflows
|
|
400
|
+
`;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function implementationPlanTemplate(promptsDir) {
|
|
404
|
+
return `# Implementation Plan
|
|
405
|
+
|
|
406
|
+
> AIES plan of record. **Approve before multi-file coding.**
|
|
407
|
+
> Author with \`${promptsDir}/implementation-plan.prompt.md\` + the planning skill.
|
|
408
|
+
|
|
409
|
+
## Goal
|
|
410
|
+
|
|
411
|
+
<!-- One sentence outcome -->
|
|
412
|
+
|
|
413
|
+
## Context
|
|
414
|
+
|
|
415
|
+
<!-- Links: tickets, ADRs, designs, prior PRs -->
|
|
416
|
+
|
|
417
|
+
## Scope
|
|
418
|
+
|
|
419
|
+
### In scope
|
|
420
|
+
|
|
421
|
+
-
|
|
422
|
+
|
|
423
|
+
### Out of scope / non-goals
|
|
424
|
+
|
|
425
|
+
-
|
|
426
|
+
|
|
427
|
+
## Tasks
|
|
428
|
+
|
|
429
|
+
| ID | Task | Files / areas | Verification command or evidence | Owner | Done |
|
|
430
|
+
|----|------|---------------|----------------------------------|-------|------|
|
|
431
|
+
| 1 | | | | | [ ] |
|
|
432
|
+
|
|
433
|
+
## Dependencies & sequencing
|
|
434
|
+
|
|
435
|
+
-
|
|
436
|
+
|
|
437
|
+
## Risks
|
|
438
|
+
|
|
439
|
+
| Risk | Likelihood | Impact | Mitigation |
|
|
440
|
+
|------|------------|--------|------------|
|
|
441
|
+
| | | | |
|
|
442
|
+
|
|
443
|
+
## Rollback
|
|
444
|
+
|
|
445
|
+
-
|
|
446
|
+
|
|
447
|
+
## Test / eval plan
|
|
448
|
+
|
|
449
|
+
-
|
|
450
|
+
|
|
451
|
+
## Human approval
|
|
452
|
+
|
|
453
|
+
- [ ] Plan reviewed for completeness and scope leakage
|
|
454
|
+
- [ ] Approved by: _______________
|
|
455
|
+
- [ ] Date: _______________
|
|
456
|
+
|
|
457
|
+
## Changelog
|
|
458
|
+
|
|
459
|
+
| Date | Change |
|
|
460
|
+
|------|--------|
|
|
461
|
+
| | Initial |
|
|
462
|
+
`;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* @param {object} profile
|
|
467
|
+
* @param {{ recommendedMcpIds?: string[] }} [opts]
|
|
468
|
+
*/
|
|
469
|
+
export function generateStarterKit(profile, opts = {}) {
|
|
470
|
+
const stack = stackMeta(profile.stack);
|
|
471
|
+
const label = STACK_LABELS[profile.stack] ?? profile.stack;
|
|
472
|
+
const now = new Date().toISOString();
|
|
473
|
+
const model = profile.model ?? 'undecided';
|
|
474
|
+
const dataClass = profile.dataClass ?? 'internal';
|
|
475
|
+
const L = layoutFor(profile.ide);
|
|
476
|
+
const recommendedIds = opts.recommendedMcpIds ?? stackMcpIds(profile.stack);
|
|
477
|
+
const recommended = buildRecommendedMcpConfig(recommendedIds);
|
|
478
|
+
|
|
479
|
+
const flags = [
|
|
480
|
+
`--stack ${profile.stack}`,
|
|
481
|
+
`--ide ${profile.ide}`,
|
|
482
|
+
`--role ${profile.role}`,
|
|
483
|
+
`--maturity ${profile.maturity}`,
|
|
484
|
+
`--goal ${profile.goal}`,
|
|
485
|
+
`--model ${model}`,
|
|
486
|
+
`--data-class ${dataClass}`,
|
|
487
|
+
'--yes',
|
|
488
|
+
].join(' ');
|
|
489
|
+
|
|
490
|
+
/** @type {Record<string, string>} */
|
|
491
|
+
const files = {};
|
|
492
|
+
|
|
493
|
+
for (const name of CORE_PROMPTS) {
|
|
494
|
+
files[`${L.promptsDir}/${name}.prompt.md`] = corpus(`aidlc/${name}.prompt.md`);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
for (const name of CORE_SKILLS) {
|
|
498
|
+
writeSkill(files, L, name, corpus(`skills/${name}.skill.md`));
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
for (const name of CORE_AGENTS) {
|
|
502
|
+
files[`${L.agentsDir}/${name}.agent.md`] = corpus(`agents/${name}.agent.md`);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
files[`${L.templatesDir}/system-prompt.template.md`] = corpus('templates/system-prompt.template.md');
|
|
506
|
+
|
|
507
|
+
if (stack.cookbook) {
|
|
508
|
+
const keys = cookbookKeys(stack.cookbook);
|
|
509
|
+
for (const key of keys) {
|
|
510
|
+
const rel = key.slice(`cookbook/${stack.cookbook}/`.length);
|
|
511
|
+
files[`${L.cookbookDir}/${rel}`] = corpus(key);
|
|
512
|
+
}
|
|
513
|
+
const skillKey = keys.find(k => k.includes('/skills/') && k.endsWith('.skill.md'));
|
|
514
|
+
if (skillKey) {
|
|
515
|
+
const skillName = pathBasename(skillKey).replace(/\.skill\.md$/, '');
|
|
516
|
+
writeSkill(files, L, skillName, corpus(skillKey));
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
files[`${L.guidesDir}/human-in-the-loop.md`] = corpus('handbook/human-in-the-loop.md');
|
|
521
|
+
files[`${L.guidesDir}/evals-as-quality-gates.md`] = corpus('handbook/evals-as-quality-gates.md');
|
|
522
|
+
files[`${L.guidesDir}/mcp-when-and-how.md`] = corpus('handbook/mcp-when-and-how.md');
|
|
523
|
+
files[`${L.guidesDir}/skills-vs-prompts-vs-agents.md`] = corpus('handbook/skills-vs-prompts-vs-agents.md');
|
|
524
|
+
files[`${L.guidesDir}/how-to-set-up-planning.md`] = corpus('handbook/how-to-set-up-planning.md');
|
|
525
|
+
|
|
526
|
+
files[`${L.mcpsDir}/README.md`] = corpus('mcps/README.md');
|
|
527
|
+
for (const spec of MCP_SPECS) {
|
|
528
|
+
files[`${L.mcpsDir}/${spec.file}`] = corpus(`mcps/${spec.file}`);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
files[L.policyFile] = modelPolicy(profile);
|
|
532
|
+
|
|
533
|
+
const mcpDoc = {
|
|
534
|
+
mcpServers: {},
|
|
535
|
+
_aiesRecommended: recommended,
|
|
536
|
+
_aies: {
|
|
537
|
+
note: 'mcpServers stays empty until a human copies stubs from _aiesRecommended and sets secrets.',
|
|
538
|
+
guide: `${SITE_URL}/docs/handbook/mcp-when-and-how`,
|
|
539
|
+
dataClass,
|
|
540
|
+
recommendedIds,
|
|
541
|
+
specsDir: L.mcpsDir,
|
|
542
|
+
},
|
|
543
|
+
};
|
|
544
|
+
files[L.mcpFile] = JSON.stringify(mcpDoc, null, 2);
|
|
545
|
+
|
|
546
|
+
files[L.hooksFile] = JSON.stringify(
|
|
547
|
+
{
|
|
548
|
+
version: '1',
|
|
549
|
+
hooks: [
|
|
550
|
+
{ id: 'pre-planning', phase: 'before-plan', requiredEvidence: ['requirements-path', 'risk-tier'] },
|
|
551
|
+
{ id: 'pre-code', phase: 'before-code', requiredEvidence: ['approved-plan-path'] },
|
|
552
|
+
],
|
|
553
|
+
_aies: { hooksGuide: `${SITE_URL}/docs/04-agent-engineering/hooks/README` },
|
|
554
|
+
},
|
|
555
|
+
null,
|
|
556
|
+
2,
|
|
557
|
+
);
|
|
558
|
+
|
|
559
|
+
const rootInstructions = buildRootInstructions(profile, label, L);
|
|
560
|
+
files['CLAUDE.md'] = rootInstructions;
|
|
561
|
+
files['AGENTS.md'] = rootInstructions;
|
|
562
|
+
files['copilot-instructions.md'] = rootInstructions;
|
|
563
|
+
files['.github/copilot-instructions.md'] = rootInstructions;
|
|
564
|
+
|
|
565
|
+
if (profile.ide === 'cursor') {
|
|
566
|
+
files[L.rulesFile] = `---
|
|
567
|
+
description: AIES project harness rules
|
|
568
|
+
globs:
|
|
569
|
+
alwaysApply: true
|
|
570
|
+
---
|
|
571
|
+
|
|
572
|
+
${rootInstructions}
|
|
573
|
+
`;
|
|
574
|
+
} else if (profile.ide === 'claude-code') {
|
|
575
|
+
// CLAUDE.md already written as rootInstructions
|
|
576
|
+
} else if (profile.ide === 'copilot') {
|
|
577
|
+
// .github/copilot-instructions.md already written
|
|
578
|
+
} else if (profile.ide === 'continue') {
|
|
579
|
+
files[L.rulesFile] = rootInstructions;
|
|
580
|
+
files['.continue/config.snippet.json'] = JSON.stringify(
|
|
581
|
+
{
|
|
582
|
+
comment: 'Merge into Continue config — do not overwrite blindly',
|
|
583
|
+
contextProviders: [
|
|
584
|
+
{ name: 'file', params: { path: 'implementation_plan.md' } },
|
|
585
|
+
{ name: 'file', params: { path: L.cookbookDir } },
|
|
586
|
+
{ name: 'file', params: { path: L.skillsDir } },
|
|
587
|
+
],
|
|
588
|
+
},
|
|
589
|
+
null,
|
|
590
|
+
2,
|
|
591
|
+
);
|
|
592
|
+
} else {
|
|
593
|
+
files[L.rulesFile] = rootInstructions;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
files['implementation_plan.md'] = implementationPlanTemplate(L.promptsDir);
|
|
597
|
+
|
|
598
|
+
files['AIES.md'] = buildAiesReadme({
|
|
599
|
+
profile: { ...profile, model, dataClass },
|
|
600
|
+
label,
|
|
601
|
+
L,
|
|
602
|
+
stack,
|
|
603
|
+
flags,
|
|
604
|
+
now,
|
|
605
|
+
recommendedIds,
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
return {
|
|
609
|
+
stack: profile.stack,
|
|
610
|
+
generatedAt: now,
|
|
611
|
+
profile: { ...profile, model, dataClass },
|
|
612
|
+
layout: describeInstallLayout(profile.ide),
|
|
613
|
+
files,
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* Enhance mode: rescan repo, refresh MCP recommendations + AIES.md section, keep corpus.
|
|
619
|
+
* Requires an existing profile — recovered from AIES.md markers or passed flags.
|
|
620
|
+
*/
|
|
621
|
+
export function enhanceStarterKit(cwd, profile) {
|
|
622
|
+
const { signals, recommendedMcpIds } = detectRepoSignals(cwd, fs);
|
|
623
|
+
const mergedIds = [...new Set([...stackMcpIds(profile.stack), ...recommendedMcpIds])];
|
|
624
|
+
const bundle = generateStarterKit(profile, { recommendedMcpIds: mergedIds });
|
|
625
|
+
|
|
626
|
+
const scanReport = `# AIES repo scan
|
|
627
|
+
|
|
628
|
+
Generated: ${new Date().toISOString()}
|
|
629
|
+
|
|
630
|
+
## Signals detected
|
|
631
|
+
|
|
632
|
+
\`\`\`json
|
|
633
|
+
${JSON.stringify(signals, null, 2)}
|
|
634
|
+
\`\`\`
|
|
635
|
+
|
|
636
|
+
## Recommended MCP ids
|
|
637
|
+
|
|
638
|
+
${mergedIds.map(id => `- ${id}`).join('\n')}
|
|
639
|
+
|
|
640
|
+
## Next
|
|
641
|
+
|
|
642
|
+
1. Review \`${layoutFor(profile.ide).mcpFile}\` → \`_aiesRecommended\`
|
|
643
|
+
2. Run \`${layoutFor(profile.ide).promptsDir}/enhance-repo.prompt.md\` in your IDE agent
|
|
644
|
+
3. Fill \`implementation_plan.md\` before multi-file coding
|
|
645
|
+
`;
|
|
646
|
+
|
|
647
|
+
bundle.files['AIES_REPO_SCAN.md'] = scanReport;
|
|
648
|
+
bundle.scan = { signals, recommendedMcpIds: mergedIds };
|
|
649
|
+
return bundle;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
export function renderBashInstallScript(bundle) {
|
|
653
|
+
const lines = [
|
|
654
|
+
'#!/usr/bin/env bash',
|
|
655
|
+
'set -euo pipefail',
|
|
656
|
+
'echo "AIES kit — scaffolding IDE-native harness into $(pwd)"',
|
|
657
|
+
'',
|
|
658
|
+
];
|
|
659
|
+
for (const [relPath, content] of Object.entries(bundle.files)) {
|
|
660
|
+
const dir = relPath.includes('/') ? relPath.slice(0, relPath.lastIndexOf('/')) : '';
|
|
661
|
+
if (dir) lines.push(`mkdir -p "${dir}"`);
|
|
662
|
+
const delim = `AIES_EOF_${Buffer.from(relPath).toString('hex').slice(0, 12)}`;
|
|
663
|
+
lines.push(`cat > "${relPath}" <<'${delim}'`);
|
|
664
|
+
lines.push(content.replace(/\r\n/g, '\n'));
|
|
665
|
+
lines.push(delim);
|
|
666
|
+
lines.push('');
|
|
667
|
+
}
|
|
668
|
+
lines.push('echo "Done. Read AIES.md — then: npx @grvmithas/create-aies-kit enhance"');
|
|
669
|
+
lines.push(`echo "Open: ${SITE_URL}/quickstart"`);
|
|
670
|
+
return lines.join('\n');
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
export function renderPowerShellInstallScript(bundle) {
|
|
674
|
+
const lines = [
|
|
675
|
+
'$ErrorActionPreference = "Stop"',
|
|
676
|
+
'Write-Host "AIES kit — scaffolding IDE-native harness into $(Get-Location)"',
|
|
677
|
+
'',
|
|
678
|
+
];
|
|
679
|
+
for (const [relPath, content] of Object.entries(bundle.files)) {
|
|
680
|
+
const dir = relPath.includes('/') ? relPath.slice(0, relPath.lastIndexOf('/')) : '';
|
|
681
|
+
const psPath = relPath.replace(/\//g, '\\');
|
|
682
|
+
if (dir) {
|
|
683
|
+
lines.push(`New-Item -ItemType Directory -Force -Path "${dir.replace(/\//g, '\\')}" | Out-Null`);
|
|
684
|
+
}
|
|
685
|
+
const b64 = Buffer.from(content, 'utf8').toString('base64');
|
|
686
|
+
lines.push(
|
|
687
|
+
`[System.IO.File]::WriteAllText((Join-Path (Get-Location) "${psPath}"), [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String("${b64}")))`,
|
|
688
|
+
);
|
|
689
|
+
}
|
|
690
|
+
lines.push('Write-Host "Done. Read AIES.md — then: npx @grvmithas/create-aies-kit enhance"');
|
|
691
|
+
lines.push(`Write-Host "Open: ${SITE_URL}/quickstart"`);
|
|
692
|
+
return lines.join('\n');
|
|
693
|
+
}
|