great-cto 2.22.3 → 2.23.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/dist/adapt.js CHANGED
@@ -1,16 +1,25 @@
1
- // great-cto adapt — Claude Code config generator.
1
+ // great-cto adapt — AI config generator.
2
2
  //
3
3
  // Writes CLAUDE.md + AGENTS.md from .great_cto/PROJECT.md context.
4
+ // Also generates cross-AI configs for Cursor, Copilot, Windsurf, Aider
5
+ // when ai_tools is set in PROJECT.md.
4
6
  //
5
7
  // Usage:
6
- // great-cto adapt Generate CLAUDE.md + AGENTS.md
8
+ // great-cto adapt Generate all configs (reads ai_tools from PROJECT.md)
7
9
  // great-cto adapt --dry-run Show what would be written
8
10
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
9
11
  import { dirname, join } from "node:path";
12
+ const VALID_AI_TOOLS = ["claude-code", "cursor", "copilot", "windsurf", "aider"];
13
+ function parseAiTools(text) {
14
+ const line = text.match(/^ai_tools:\s*(.+)$/m)?.[1] ?? "";
15
+ // Support: [claude-code, cursor] or claude-code, cursor or claude-code
16
+ const raw = line.replace(/[\[\]]/g, "").split(/[,\s]+/).map(s => s.trim()).filter(Boolean);
17
+ return raw.filter((t) => VALID_AI_TOOLS.includes(t));
18
+ }
10
19
  function readProjectMeta(cwd) {
11
20
  const projectMd = join(cwd, ".great_cto", "PROJECT.md");
12
21
  if (!existsSync(projectMd)) {
13
- return { archetype: "unknown", compliance: [], owners: "", hasGreatCto: false };
22
+ return { archetype: "unknown", compliance: [], owners: "", hasGreatCto: false, aiTools: ["claude-code"], projectName: "project" };
14
23
  }
15
24
  const text = readFileSync(projectMd, "utf8");
16
25
  const archetype = (text.match(/^primary:\s*(\S+)/m)?.[1] ?? "unknown").trim();
@@ -20,7 +29,63 @@ function readProjectMeta(cwd) {
20
29
  .map(s => s.trim())
21
30
  .filter(Boolean);
22
31
  const owners = (text.match(/^owners?:\s*(.+)$/m)?.[1] ?? "").trim();
23
- return { archetype, compliance, owners, hasGreatCto: true };
32
+ const aiTools = parseAiTools(text);
33
+ // Infer project name from first H1 heading
34
+ const projectName = (text.match(/^#\s+(.+)$/m)?.[1] ?? "project").trim();
35
+ return { archetype, compliance, owners, hasGreatCto: true, aiTools: aiTools.length > 0 ? aiTools : ["claude-code"], projectName };
36
+ }
37
+ /**
38
+ * Project Constitution — universal hard constraints injected into every AI config.
39
+ * Inspired by Spec Driven Development (FredAntB/Spec-Driven-Development).
40
+ */
41
+ function getConstitutionBlock(meta) {
42
+ const hasSpec = existsSync(join(process.cwd(), "requirements.md"));
43
+ const specSection = hasSpec ? `
44
+ ## Spec files (source of truth)
45
+
46
+ requirements.md — What the system must do
47
+ design.md — How the system is structured
48
+ tasks.md — Ordered implementation plan
49
+
50
+ MANDATORY BEFORE ANY ACTION:
51
+ 0. If CONTEXT.md exists, read it first — it has session state
52
+ 1. Read requirements.md — understand what is in scope
53
+ 2. Read design.md — understand how it is structured
54
+ 3. Read tasks.md — find the next incomplete [ ] task
55
+ ` : `
56
+ ## Session context
57
+
58
+ 0. If CONTEXT.md exists, read it first — it has the active task and session state
59
+ 1. Read .great_cto/PROJECT.md — archetype, compliance gates, team mode
60
+ 2. Read .great_cto/lessons.md if present — past mistakes and patterns
61
+ `;
62
+ return `
63
+ ═══════════════════════════════════════════════════════════
64
+ PROJECT CONSTITUTION — ${meta.projectName.toUpperCase()}
65
+ Generated by great-cto adapt · ${new Date().toISOString().slice(0, 10)}
66
+ ═══════════════════════════════════════════════════════════
67
+ ${specSection}
68
+ HARD CONSTRAINTS (no exceptions):
69
+ ✗ Never implement requirements not explicitly defined in requirements.md
70
+ ✗ Never alter the data model without updating design.md first
71
+ ✗ Never mark a task [x] without verifying its acceptance criterion
72
+ ✗ Never create files not listed or implied in design.md
73
+ ✗ Never guess when a requirement is ambiguous — ask instead
74
+ ✗ Never skip gates (security-officer, qa-engineer) — use /waiver with reason
75
+
76
+ AFTER COMPLETING A TASK:
77
+ 1. Run the verification step listed in tasks.md (or acceptance criterion)
78
+ 2. Mark the task [x] in tasks.md
79
+ 3. Update CONTEXT.md resume block with the next active task
80
+ 4. Record any divergences from design.md in CONTEXT.md
81
+
82
+ IF IMPLEMENTATION MUST DEVIATE FROM DESIGN:
83
+ 1. Stop immediately
84
+ 2. Describe the conflict clearly
85
+ 3. Wait for explicit approval
86
+ 4. Update design.md FIRST, then implement
87
+ ═══════════════════════════════════════════════════════════
88
+ `;
24
89
  }
25
90
  /**
26
91
  * AGENTS.md — Claude Code reads this as the cross-tool agent contract.
@@ -29,7 +94,9 @@ function getAgentsCore(meta) {
29
94
  const compliance = meta.compliance.length > 0
30
95
  ? meta.compliance.map(c => `- ${c}`).join("\n")
31
96
  : "_(none auto-detected — set in .great_cto/PROJECT.md)_";
97
+ const constitution = getConstitutionBlock(meta);
32
98
  return `# AGENTS.md
99
+ ${constitution}
33
100
 
34
101
  > Project agent contract for Claude Code. Generated by \`great-cto adapt\` —
35
102
  > re-run after editing \`.great_cto/PROJECT.md\`.
@@ -133,6 +200,117 @@ gates "because it's just a small change" — that's the path to incidents.
133
200
  _Generated by \`great-cto@${getCliVersion()}\` adapt at ${new Date().toISOString().slice(0, 10)}_
134
201
  `;
135
202
  }
203
+ // ── Cross-AI config generators ─────────────────────────────────────────────
204
+ function getCursorrules(meta) {
205
+ const constitution = getConstitutionBlock(meta);
206
+ return `${constitution}
207
+
208
+ # .cursorrules — Cursor AI configuration for ${meta.projectName}
209
+ # Generated by great-cto adapt · ${new Date().toISOString().slice(0, 10)}
210
+
211
+ ## Project context
212
+
213
+ - **Archetype:** ${meta.archetype}
214
+ - **Compliance:** ${meta.compliance.join(", ") || "none"}
215
+ - **Stack:** See .great_cto/PROJECT.md
216
+
217
+ ## Coding conventions
218
+
219
+ - TypeScript strict mode — no \`any\` without explanatory comment
220
+ - ESM modules only (.mjs / "type":"module")
221
+ - Conventional commits: feat / fix / docs / refactor / test / chore
222
+ - Tests before implementation (RED → GREEN → REFACTOR), 80%+ coverage
223
+ - One concern per PR — refactors and behaviour changes are separate PRs
224
+
225
+ ## Agent routing
226
+
227
+ For complex tasks, prefer the great_cto agent pipeline (via Claude Code):
228
+ - Architecture decisions → \`architect\` agent
229
+ - Feature planning → \`pm\` agent
230
+ - Implementation → \`senior-dev\` agent
231
+ - Security review → \`security-officer\` agent
232
+
233
+ See AGENTS.md for the full routing table.
234
+ `;
235
+ }
236
+ function getCopilotInstructions(meta) {
237
+ const constitution = getConstitutionBlock(meta);
238
+ return `${constitution}
239
+
240
+ # GitHub Copilot Instructions for ${meta.projectName}
241
+ # Generated by great-cto adapt · ${new Date().toISOString().slice(0, 10)}
242
+
243
+ ## Project context
244
+
245
+ - **Archetype:** ${meta.archetype}
246
+ - **Compliance gates:** ${meta.compliance.join(", ") || "none"}
247
+ - **Read first:** CONTEXT.md (session state), requirements.md (scope)
248
+
249
+ ## Code style
250
+
251
+ - TypeScript strict mode, ESM-only
252
+ - Conventional commits
253
+ - Test-first development — write tests before implementation
254
+ - No secrets in code — great-cto scan blocks ~13 patterns
255
+
256
+ ## What NOT to do
257
+
258
+ - Do not implement features not in requirements.md
259
+ - Do not alter data models without updating design.md
260
+ - Do not generate placeholder files with TODO tokens
261
+ - Do not guess ambiguous requirements — surface them for human decision
262
+ `;
263
+ }
264
+ function getWindsurfrules(meta) {
265
+ const constitution = getConstitutionBlock(meta);
266
+ return `${constitution}
267
+
268
+ # .windsurfrules — Windsurf AI configuration for ${meta.projectName}
269
+ # Generated by great-cto adapt · ${new Date().toISOString().slice(0, 10)}
270
+
271
+ ## Session startup
272
+
273
+ 1. Read CONTEXT.md — resume active task from resume block
274
+ 2. Read requirements.md — understand scope
275
+ 3. Read design.md — understand structure
276
+ 4. Find next incomplete [ ] task in tasks.md
277
+
278
+ ## Project context
279
+
280
+ - Archetype: ${meta.archetype}
281
+ - Compliance: ${meta.compliance.join(", ") || "none"}
282
+ - Spec files: requirements.md / design.md / tasks.md
283
+
284
+ ## Hard rules
285
+
286
+ - Never implement beyond requirements.md scope
287
+ - Never skip the CONTEXT.md update at session end
288
+ - Run verification step before marking any task complete
289
+ `;
290
+ }
291
+ function getAiderConf(meta) {
292
+ return `# .aider.conf.yml — Aider configuration for ${meta.projectName}
293
+ # Generated by great-cto adapt · ${new Date().toISOString().slice(0, 10)}
294
+
295
+ # Read these files as context at startup
296
+ read:
297
+ - CONTEXT.md
298
+ - requirements.md
299
+ - design.md
300
+ - tasks.md
301
+ - .great_cto/PROJECT.md
302
+
303
+ # Commit message format
304
+ commit-prompt: |
305
+ Write a conventional commit message (feat/fix/docs/refactor/test/chore).
306
+ Be specific about what changed and why.
307
+ Never mention private project names — use <private-project> placeholder.
308
+
309
+ # Conventions
310
+ auto-commits: false
311
+ dirty-commits: false
312
+ `;
313
+ }
136
314
  function getCliVersion() {
137
315
  try {
138
316
  const here = dirname(new URL(import.meta.url).pathname);
@@ -171,8 +349,8 @@ conventions. Generated by \`great-cto adapt\`.
171
349
 
172
350
  ## Claude Code specifics
173
351
 
174
- - The great_cto plugin orchestrates 34 specialist agents — pipeline runs
175
- through \`/start\`, \`/inbox\`, \`/save\`, etc.
352
+ - The great_cto plugin orchestrates specialist agents — pipeline runs
353
+ through \`/start\`, \`/inbox\`, \`/save\`, \`/spec\`, etc.
176
354
  - Memory is layered: \`.great_cto/PROJECT.md\` (L1) → \`lessons.md\` (L3) →
177
355
  \`~/.great_cto/decisions.md\` (L4 cross-project ADR log).
178
356
  - Run \`great-cto board\` (\`http://localhost:3141\`) for the kanban + metrics
@@ -180,6 +358,7 @@ conventions. Generated by \`great-cto adapt\`.
180
358
 
181
359
  ## Quick links
182
360
 
361
+ - \`/spec\` — interview → requirements.md + design.md + tasks.md
183
362
  - \`/start "..."\` — kick off a feature pipeline
184
363
  - \`/inbox\` — see what needs your decision
185
364
  - \`/agent-review\` — performance scorecard for agents
@@ -189,6 +368,38 @@ conventions. Generated by \`great-cto adapt\`.
189
368
  out.push("AGENTS.md");
190
369
  if (writeFile(join(cwd, "CLAUDE.md"), claudeBody, dryRun))
191
370
  out.push("CLAUDE.md");
371
+ // Cross-AI config files based on ai_tools in PROJECT.md
372
+ for (const tool of meta.aiTools) {
373
+ switch (tool) {
374
+ case "cursor": {
375
+ const path = join(cwd, ".cursorrules");
376
+ if (writeFile(path, getCursorrules(meta), dryRun))
377
+ out.push(".cursorrules");
378
+ break;
379
+ }
380
+ case "copilot": {
381
+ const path = join(cwd, ".github", "copilot-instructions.md");
382
+ if (writeFile(path, getCopilotInstructions(meta), dryRun))
383
+ out.push(".github/copilot-instructions.md");
384
+ break;
385
+ }
386
+ case "windsurf": {
387
+ const path = join(cwd, ".windsurfrules");
388
+ if (writeFile(path, getWindsurfrules(meta), dryRun))
389
+ out.push(".windsurfrules");
390
+ break;
391
+ }
392
+ case "aider": {
393
+ const path = join(cwd, ".aider.conf.yml");
394
+ if (writeFile(path, getAiderConf(meta), dryRun))
395
+ out.push(".aider.conf.yml");
396
+ break;
397
+ }
398
+ case "claude-code":
399
+ // Already handled above (CLAUDE.md + AGENTS.md)
400
+ break;
401
+ }
402
+ }
192
403
  return out;
193
404
  }
194
405
  // ── Main entry ─────────────────────────────────────────────────────────────
@@ -199,14 +410,19 @@ export async function runAdapt(args) {
199
410
  console.error("Run `npx great-cto init` first to bootstrap the project.");
200
411
  return 1;
201
412
  }
202
- console.log(`great-cto adapt claude${args.dryRun ? " (dry-run)" : ""}`);
413
+ const toolsList = meta.aiTools.join(", ");
414
+ console.log(`great-cto adapt → ${toolsList}${args.dryRun ? " (dry-run)" : ""}`);
203
415
  console.log(` archetype: ${meta.archetype} compliance: ${meta.compliance.join(", ") || "none"}`);
416
+ console.log(` ai_tools: ${toolsList}`);
204
417
  console.log("");
205
418
  const written = adaptClaude(args.cwd, meta, args.dryRun);
206
419
  if (!args.dryRun) {
207
420
  console.log("");
208
- console.log(`✓ generated ${written.length} file(s).`);
209
- console.log(` Re-run after editing .great_cto/PROJECT.md to refresh.`);
421
+ console.log(`✓ generated ${written.length} file(s): ${written.join(", ")}`);
422
+ console.log(` Re-run after editing .great_cto/PROJECT.md or adding tools to ai_tools: [] to refresh.`);
423
+ if (!meta.aiTools.includes("cursor") && !meta.aiTools.includes("copilot") && !meta.aiTools.includes("windsurf")) {
424
+ console.log(` Tip: add other AI tools to ai_tools: [] in PROJECT.md to generate .cursorrules, copilot-instructions.md, etc.`);
425
+ }
210
426
  }
211
427
  return 0;
212
428
  }
package/dist/bootstrap.js CHANGED
@@ -22,6 +22,38 @@ export function bootstrap(dir, detection, archetype, compliance, detectionMeta)
22
22
  : "unknown";
23
23
  const teamSize = 1; // MVP default — user edits later
24
24
  const approvalLevel = "gates-only"; // default per README
25
+ // Write CONTEXT.md in the project root (resume-block for all AI agents).
26
+ const contextMdPath = join(dir, "CONTEXT.md");
27
+ if (!existsSync(contextMdPath)) {
28
+ const contextContent = `# CONTEXT.md
29
+
30
+ > AI session state for all agents. Updated at the end of each session.
31
+ > All AI coding tools (Claude Code, Cursor, Copilot, Windsurf, Aider) read this
32
+ > before starting work.
33
+
34
+ ## Resume block
35
+
36
+ **Current task:** _(none — project just initialized)_
37
+ **Last session:** ${new Date().toISOString().slice(0, 10)}
38
+ **Status:** 🟢 ready to start
39
+
40
+ ## Session log
41
+
42
+ | Session | Date | Summary | Files changed |
43
+ |---------|------|---------|---------------|
44
+ | 1 | ${new Date().toISOString().slice(0, 10)} | Project initialized | CONTEXT.md, .great_cto/PROJECT.md |
45
+
46
+ ## Open questions
47
+
48
+ _(none yet — add questions that need founder/team input before implementation can proceed)_
49
+
50
+ ## Divergences from spec
51
+
52
+ _(none — record any deviations from design.md here with rationale)_
53
+ `;
54
+ writeFileSync(contextMdPath, contextContent, "utf-8");
55
+ success(`created CONTEXT.md ${dim("(session resume block for all AI tools)")}`);
56
+ }
25
57
  const content = `# ${title}
26
58
 
27
59
  > Auto-generated by \`great-cto init\` on ${new Date().toISOString().slice(0, 10)}.
@@ -55,8 +87,12 @@ phase: implementation
55
87
  team-size: ${teamSize}
56
88
  mode: solo
57
89
  approval-level: ${approvalLevel}
90
+ ai_tools: [claude-code]
58
91
 
59
92
  > \`team-size:\` is read at root level (not nested) by /rfc and other commands.
93
+ > \`ai_tools:\` controls which config files \`great-cto adapt\` generates.
94
+ > Supported values: claude-code, cursor, copilot, windsurf, aider
95
+ > Example: ai_tools: [claude-code, cursor, copilot]
60
96
 
61
97
  ## Compliance
62
98
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "great-cto",
3
- "version": "2.22.3",
3
+ "version": "2.23.0",
4
4
  "description": "One command install for the great_cto Claude Code plugin. Auto-detects your stack, picks the right archetype, bootstraps PROJECT.md.",
5
5
  "keywords": [
6
6
  "claude-code",