@aicgen/aicgen 1.0.0-beta.1 → 1.0.0-beta.2

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.
Files changed (136) hide show
  1. package/.vs/ProjectSettings.json +2 -2
  2. package/.vs/VSWorkspaceState.json +15 -15
  3. package/.vs/aicgen.slnx/v18/DocumentLayout.json +53 -53
  4. package/assets/icon.svg +33 -33
  5. package/bun.lock +0 -43
  6. package/data/architecture/microservices/api-gateway.md +56 -56
  7. package/data/devops/observability.md +73 -73
  8. package/dist/index.js +9299 -9299
  9. package/package.json +2 -2
  10. package/.claude/agents/architecture-reviewer.md +0 -88
  11. package/.claude/agents/guideline-checker.md +0 -73
  12. package/.claude/agents/security-auditor.md +0 -108
  13. package/.claude/guidelines/api-design.md +0 -645
  14. package/.claude/guidelines/architecture.md +0 -2503
  15. package/.claude/guidelines/best-practices.md +0 -618
  16. package/.claude/guidelines/code-style.md +0 -304
  17. package/.claude/guidelines/design-patterns.md +0 -573
  18. package/.claude/guidelines/devops.md +0 -226
  19. package/.claude/guidelines/error-handling.md +0 -413
  20. package/.claude/guidelines/language.md +0 -782
  21. package/.claude/guidelines/performance.md +0 -706
  22. package/.claude/guidelines/security.md +0 -583
  23. package/.claude/guidelines/testing.md +0 -568
  24. package/.claude/settings.json +0 -98
  25. package/.claude/settings.local.json +0 -8
  26. package/.eslintrc.json +0 -28
  27. package/.github/workflows/release.yml +0 -180
  28. package/.github/workflows/test.yml +0 -81
  29. package/CONTRIBUTING.md +0 -821
  30. package/dist/commands/init.d.ts +0 -8
  31. package/dist/commands/init.d.ts.map +0 -1
  32. package/dist/commands/init.js +0 -46
  33. package/dist/commands/init.js.map +0 -1
  34. package/dist/config/profiles.d.ts +0 -4
  35. package/dist/config/profiles.d.ts.map +0 -1
  36. package/dist/config/profiles.js +0 -30
  37. package/dist/config/profiles.js.map +0 -1
  38. package/dist/config/settings.d.ts +0 -7
  39. package/dist/config/settings.d.ts.map +0 -1
  40. package/dist/config/settings.js +0 -7
  41. package/dist/config/settings.js.map +0 -1
  42. package/dist/index.d.ts +0 -3
  43. package/dist/index.d.ts.map +0 -1
  44. package/dist/index.js.map +0 -1
  45. package/dist/models/guideline.d.ts +0 -15
  46. package/dist/models/guideline.d.ts.map +0 -1
  47. package/dist/models/guideline.js +0 -2
  48. package/dist/models/guideline.js.map +0 -1
  49. package/dist/models/preference.d.ts +0 -9
  50. package/dist/models/preference.d.ts.map +0 -1
  51. package/dist/models/preference.js +0 -2
  52. package/dist/models/preference.js.map +0 -1
  53. package/dist/models/profile.d.ts +0 -9
  54. package/dist/models/profile.d.ts.map +0 -1
  55. package/dist/models/profile.js +0 -2
  56. package/dist/models/profile.js.map +0 -1
  57. package/dist/models/project.d.ts +0 -13
  58. package/dist/models/project.d.ts.map +0 -1
  59. package/dist/models/project.js +0 -2
  60. package/dist/models/project.js.map +0 -1
  61. package/dist/services/ai/anthropic.d.ts +0 -7
  62. package/dist/services/ai/anthropic.d.ts.map +0 -1
  63. package/dist/services/ai/anthropic.js +0 -39
  64. package/dist/services/ai/anthropic.js.map +0 -1
  65. package/dist/services/generator.d.ts +0 -2
  66. package/dist/services/generator.d.ts.map +0 -1
  67. package/dist/services/generator.js +0 -4
  68. package/dist/services/generator.js.map +0 -1
  69. package/dist/services/learner.d.ts +0 -2
  70. package/dist/services/learner.d.ts.map +0 -1
  71. package/dist/services/learner.js +0 -4
  72. package/dist/services/learner.js.map +0 -1
  73. package/dist/services/scanner.d.ts +0 -3
  74. package/dist/services/scanner.d.ts.map +0 -1
  75. package/dist/services/scanner.js +0 -54
  76. package/dist/services/scanner.js.map +0 -1
  77. package/dist/utils/errors.d.ts +0 -15
  78. package/dist/utils/errors.d.ts.map +0 -1
  79. package/dist/utils/errors.js +0 -27
  80. package/dist/utils/errors.js.map +0 -1
  81. package/dist/utils/file.d.ts +0 -7
  82. package/dist/utils/file.d.ts.map +0 -1
  83. package/dist/utils/file.js +0 -32
  84. package/dist/utils/file.js.map +0 -1
  85. package/dist/utils/logger.d.ts +0 -6
  86. package/dist/utils/logger.d.ts.map +0 -1
  87. package/dist/utils/logger.js +0 -17
  88. package/dist/utils/logger.js.map +0 -1
  89. package/dist/utils/path.d.ts +0 -6
  90. package/dist/utils/path.d.ts.map +0 -1
  91. package/dist/utils/path.js +0 -14
  92. package/dist/utils/path.js.map +0 -1
  93. package/docs/planning/memory-lane.md +0 -83
  94. package/packaging/linux/aicgen.spec +0 -23
  95. package/packaging/linux/control +0 -9
  96. package/packaging/macos/scripts/postinstall +0 -12
  97. package/packaging/windows/setup.nsi +0 -92
  98. package/scripts/add-categories.ts +0 -87
  99. package/scripts/build-binary.ts +0 -46
  100. package/scripts/embed-data.ts +0 -105
  101. package/scripts/generate-version.ts +0 -150
  102. package/scripts/test-decompress.ts +0 -27
  103. package/scripts/test-extract.ts +0 -31
  104. package/src/__tests__/services/assistant-file-writer.test.ts +0 -400
  105. package/src/__tests__/services/guideline-loader.test.ts +0 -281
  106. package/src/__tests__/services/tarball-extraction.test.ts +0 -125
  107. package/src/commands/add-guideline.ts +0 -296
  108. package/src/commands/clear.ts +0 -61
  109. package/src/commands/guideline-selector.ts +0 -123
  110. package/src/commands/init.ts +0 -645
  111. package/src/commands/quick-add.ts +0 -586
  112. package/src/commands/remove-guideline.ts +0 -152
  113. package/src/commands/stats.ts +0 -49
  114. package/src/commands/update.ts +0 -240
  115. package/src/config.ts +0 -82
  116. package/src/embedded-data.ts +0 -1492
  117. package/src/index.ts +0 -67
  118. package/src/models/profile.ts +0 -24
  119. package/src/models/project.ts +0 -43
  120. package/src/services/assistant-file-writer.ts +0 -612
  121. package/src/services/config-generator.ts +0 -150
  122. package/src/services/config-manager.ts +0 -70
  123. package/src/services/data-source.ts +0 -248
  124. package/src/services/first-run-init.ts +0 -148
  125. package/src/services/guideline-loader.ts +0 -311
  126. package/src/services/hook-generator.ts +0 -178
  127. package/src/services/subagent-generator.ts +0 -310
  128. package/src/utils/banner.ts +0 -66
  129. package/src/utils/errors.ts +0 -27
  130. package/src/utils/file.ts +0 -67
  131. package/src/utils/formatting.ts +0 -172
  132. package/src/utils/logger.ts +0 -89
  133. package/src/utils/path.ts +0 -17
  134. package/src/utils/wizard-state.ts +0 -132
  135. package/tsconfig.json +0 -25
  136. /package/{CLAUDE.md → claude.md} +0 -0
@@ -1,645 +0,0 @@
1
- import { select, confirm } from '@inquirer/prompts';
2
- import ora from 'ora';
3
- import chalk from 'chalk';
4
- import { ConfigGenerator } from '../services/config-generator.js';
5
- import { ProfileSelection, InstructionLevel, ArchitectureType, DatasourceType } from '../models/profile.js';
6
- import { AIAssistant, Language, ProjectType } from '../models/project.js';
7
- import { GuidelineLoader } from '../services/guideline-loader.js';
8
- import { showBanner, showInstructions } from '../utils/banner.js';
9
- import { WizardStateManager, BACK_VALUE, addBackOption } from '../utils/wizard-state.js';
10
- import { createSummaryBox, createMetricsBox } from '../utils/formatting.js';
11
- import { selectGuidelines } from './guideline-selector.js';
12
- import { CONFIG, GITHUB_RELEASES_URL } from '../config.js';
13
- import { ensureDataInitialized } from '../services/first-run-init.js';
14
-
15
-
16
- interface InitOptions {
17
- assistant?: string;
18
- level?: string;
19
- architecture?: string;
20
- force?: boolean;
21
- dryRun?: boolean;
22
- }
23
-
24
- const LANGUAGES: { value: Language; name: string }[] = [
25
- { value: 'typescript', name: 'TypeScript' },
26
- { value: 'javascript', name: 'JavaScript' },
27
- { value: 'python', name: 'Python' },
28
- { value: 'go', name: 'Go' },
29
- { value: 'rust', name: 'Rust' },
30
- { value: 'java', name: 'Java' },
31
- { value: 'csharp', name: 'C#' },
32
- { value: 'ruby', name: 'Ruby' }
33
- ];
34
-
35
- const PROJECT_TYPES: { value: ProjectType; name: string; description: string }[] = [
36
- { value: 'web', name: 'Web Application', description: 'Frontend or full-stack web app' },
37
- { value: 'api', name: 'API / Backend', description: 'REST API, GraphQL, or backend service' },
38
- { value: 'cli', name: 'CLI Tool', description: 'Command-line application' },
39
- { value: 'library', name: 'Library / Package', description: 'Reusable library or npm/pip package' },
40
- { value: 'desktop', name: 'Desktop Application', description: 'Electron, Tauri, or native desktop app' },
41
- { value: 'mobile', name: 'Mobile Application', description: 'React Native, Flutter, or native mobile' },
42
- { value: 'other', name: 'Other', description: 'Something else' }
43
- ];
44
-
45
- const ASSISTANTS: { value: AIAssistant; name: string; description: string }[] = [
46
- { value: 'claude-code', name: 'Claude Code', description: 'Anthropic\'s Claude for coding' },
47
- { value: 'copilot', name: 'GitHub Copilot', description: 'GitHub\'s AI pair programmer' },
48
- { value: 'gemini', name: 'Google Gemini', description: 'Google\'s AI model' },
49
- { value: 'antigravity', name: 'Google Antigravity', description: 'Google\'s agentic platform' },
50
- { value: 'codex', name: 'OpenAI Codex', description: 'OpenAI\'s code model' }
51
- ];
52
-
53
- const ARCHITECTURES: { value: ArchitectureType; name: string; description: string }[] = [
54
- { value: 'layered', name: 'Layered', description: 'Simple layers: UI → Business → Data' },
55
- { value: 'modular-monolith', name: 'Modular Monolith', description: 'Single deploy with clear module boundaries' },
56
- { value: 'microservices', name: 'Microservices', description: 'Independent services with separate deploys' },
57
- { value: 'event-driven', name: 'Event-Driven', description: 'Event sourcing, CQRS, message queues' },
58
- { value: 'hexagonal', name: 'Hexagonal (Ports & Adapters)', description: 'Business logic isolated from infrastructure' },
59
- { value: 'clean-architecture', name: 'Clean Architecture', description: 'Uncle Bob\'s concentric layers with dependency rule' },
60
- { value: 'ddd', name: 'Domain-Driven Design', description: 'Bounded contexts, aggregates, domain events' },
61
- { value: 'serverless', name: 'Serverless', description: 'FaaS, event triggers, managed services' },
62
- { value: 'other', name: 'Other / None', description: 'Scripts, APIs, frontends, or no specific architecture' }
63
- ];
64
-
65
- const DATASOURCES: { value: DatasourceType; name: string; description: string }[] = [
66
- { value: 'sql', name: 'SQL Database', description: 'PostgreSQL, MySQL, SQLite, etc.' },
67
- { value: 'nosql', name: 'NoSQL Database', description: 'MongoDB, Redis, DynamoDB, etc.' },
68
- { value: 'none', name: 'No Database', description: 'No persistent data storage needed' }
69
- ];
70
-
71
- export async function initCommand(options: InitOptions) {
72
- showBanner();
73
- showInstructions();
74
-
75
- // First-run initialization
76
- await ensureDataInitialized();
77
-
78
- // Check for guideline updates (non-blocking)
79
- checkForUpdatesInBackground();
80
-
81
- const generator = await ConfigGenerator.create();
82
- const projectPath = process.cwd();
83
- const wizard = new WizardStateManager();
84
-
85
- const spinner = ora('Detecting project...').start();
86
-
87
- try {
88
- // Detect project
89
- const detected = await generator.detectProject(projectPath);
90
- spinner.succeed('Project detected');
91
-
92
- wizard.updateState({
93
- detectedLanguage: detected.language !== 'unknown' ? detected.language : undefined,
94
- detectedProjectName: detected.name,
95
- hasExistingConfig: detected.hasExistingConfig
96
- });
97
-
98
- // Show detection results in box
99
- console.log('\n' + createSummaryBox('šŸ“ Project Detection', [
100
- { label: 'Name', value: detected.name },
101
- { label: 'Language', value: detected.language !== 'unknown' ? detected.language : 'Not detected' }
102
- ]));
103
-
104
-
105
-
106
- // Check for existing config
107
- if (detected.hasExistingConfig && !options.force) {
108
- console.log(chalk.yellow('\nāš ļø Existing AI config detected'));
109
-
110
- const action = await select({
111
- message: 'How would you like to proceed?',
112
- choices: [
113
- { value: 'overwrite', name: 'Overwrite existing config', description: 'Keep other AI configs, replace matching ones' },
114
- { value: 'clear', name: 'Clear all configs first', description: 'Remove all AI configs, then generate new' },
115
- { value: 'cancel', name: 'Cancel', description: 'Exit without making changes' }
116
- ]
117
- });
118
-
119
- if (action === 'cancel') {
120
- console.log(chalk.gray('\nCancelled.'));
121
- return;
122
- }
123
-
124
- if (action === 'clear') {
125
- // Import and run clear command logic
126
- const { clearCommand } = await import('./clear.js');
127
- await clearCommand({ force: true });
128
- console.log(''); // Add spacing
129
- }
130
- }
131
-
132
- // Wizard loop with back navigation
133
- while (!wizard.isComplete()) {
134
- const state = wizard.getState();
135
-
136
- switch (state.currentStep) {
137
- case 'language':
138
- await handleLanguageStep(wizard, detected.language);
139
- break;
140
-
141
- case 'projectType':
142
- if (await handleProjectTypeStep(wizard) === BACK_VALUE) {
143
- wizard.goBack();
144
- continue;
145
- }
146
- break;
147
-
148
- case 'assistant':
149
- if (await handleAssistantStep(wizard, options) === BACK_VALUE) {
150
- wizard.goBack();
151
- continue;
152
- }
153
- break;
154
-
155
- case 'setupType':
156
- if (await handleSetupTypeStep(wizard) === BACK_VALUE) {
157
- wizard.goBack();
158
- continue;
159
- }
160
- break;
161
-
162
- case 'architecture':
163
- if (await handleArchitectureStep(wizard, options) === BACK_VALUE) {
164
- wizard.goBack();
165
- continue;
166
- }
167
- break;
168
-
169
- case 'datasource':
170
- if (await handleDatasourceStep(wizard) === BACK_VALUE) {
171
- wizard.goBack();
172
- continue;
173
- }
174
- break;
175
-
176
- case 'level':
177
- if (await handleLevelStep(wizard, options) === BACK_VALUE) {
178
- wizard.goBack();
179
- continue;
180
- }
181
- break;
182
-
183
- case 'guidelines':
184
- if (state.setupType === 'custom') {
185
- if (await handleGuidelinesStep(wizard) === BACK_VALUE) {
186
- wizard.goBack();
187
- continue;
188
- }
189
- } else {
190
- wizard.goToNextStep();
191
- }
192
- break;
193
-
194
- case 'summary': {
195
- const shouldGenerate = await handleSummaryStep(wizard);
196
- if (shouldGenerate === BACK_VALUE) {
197
- wizard.goBack();
198
- continue;
199
- } else if (!shouldGenerate) {
200
- console.log(chalk.gray('\nCancelled.'));
201
- return;
202
- }
203
- break;
204
- }
205
- }
206
-
207
- if (state.currentStep !== 'summary') {
208
- wizard.goToNextStep();
209
- } else {
210
- break;
211
- }
212
- }
213
-
214
- // Generate configuration
215
- const state = wizard.getState();
216
- const selection: ProfileSelection = {
217
- assistant: state.assistant!,
218
- language: state.language!,
219
- level: state.level!,
220
- architecture: state.architecture!,
221
- projectType: state.projectType!,
222
- projectName: detected.name,
223
- datasource: state.datasource!
224
- };
225
-
226
- spinner.start('Generating configuration...');
227
-
228
- const result = await generator.generate({
229
- projectPath,
230
- selection,
231
- customGuidelineIds: state.selectedGuidelineIds,
232
- dryRun: options.dryRun
233
- });
234
-
235
- if (!result.success) {
236
- spinner.fail('Generation failed');
237
- console.error(chalk.red('\nāŒ Errors:'));
238
- result.errors.forEach(err => console.error(chalk.red(` - ${err}`)));
239
- process.exit(1);
240
- }
241
-
242
- spinner.succeed(options.dryRun ? 'Dry run complete' : 'Configuration generated');
243
-
244
- // Show results
245
- if (options.dryRun) {
246
- console.log(chalk.yellow('\nšŸ“‹ Files that would be generated:'));
247
- } else {
248
- console.log(chalk.green('\nāœ… Generated files:'));
249
- }
250
-
251
- result.filesGenerated.forEach(file => {
252
- const relativePath = file.replace(projectPath, '').replace(/^[/\\]/, '');
253
- console.log(chalk.gray(` ${relativePath}`));
254
- });
255
-
256
- if (!options.dryRun) {
257
- console.log(chalk.cyan('\nšŸš€ Next steps:'));
258
- printNextSteps(state.assistant!);
259
- }
260
-
261
- } catch (error) {
262
- spinner.fail('Error');
263
- console.error(chalk.red(`\nāŒ ${(error as Error).message}`));
264
- process.exit(1);
265
- }
266
- }
267
-
268
- async function handleLanguageStep(wizard: WizardStateManager, detectedLanguage?: Language): Promise<void> {
269
- let language: Language;
270
-
271
- if (wizard.getState().language) return;
272
-
273
- if (detectedLanguage && detectedLanguage !== 'unknown') {
274
- const useDetected = await confirm({
275
- message: `Use detected language: ${chalk.cyan(detectedLanguage)}?`,
276
- default: true
277
- });
278
-
279
- if (useDetected) {
280
- language = detectedLanguage;
281
- } else {
282
- language = await select({
283
- message: 'Select language:',
284
- choices: LANGUAGES.map(l => ({ value: l.value, name: l.name }))
285
- }) as Language;
286
- }
287
- } else {
288
- language = await select({
289
- message: 'Select language:',
290
- choices: LANGUAGES.map(l => ({ value: l.value, name: l.name }))
291
- }) as Language;
292
- }
293
-
294
- wizard.updateState({ language });
295
- }
296
-
297
- async function handleProjectTypeStep(wizard: WizardStateManager): Promise<string> {
298
- const state = wizard.getState();
299
- if (state.projectType) return state.projectType;
300
-
301
- const choices = addBackOption(
302
- PROJECT_TYPES.map(pt => ({
303
- value: pt.value,
304
- name: pt.name,
305
- description: pt.description
306
- })),
307
- wizard.canGoBack()
308
- );
309
-
310
- const projectType = await select({
311
- message: 'What type of project is this?',
312
- choices
313
- }) as ProjectType | typeof BACK_VALUE;
314
-
315
- if (projectType !== BACK_VALUE) {
316
- wizard.updateState({ projectType: projectType as ProjectType });
317
- }
318
-
319
- return projectType;
320
- }
321
-
322
- async function handleAssistantStep(wizard: WizardStateManager, options: InitOptions): Promise<string> {
323
- const state = wizard.getState();
324
- if (state.assistant) return state.assistant;
325
-
326
- if (options.assistant) {
327
- wizard.updateState({ assistant: options.assistant as AIAssistant });
328
- return options.assistant;
329
- }
330
-
331
- const choices = addBackOption(
332
- ASSISTANTS.map(a => ({
333
- value: a.value,
334
- name: a.name,
335
- description: a.description
336
- })),
337
- wizard.canGoBack()
338
- );
339
-
340
- const assistant = await select({
341
- message: 'Which AI assistant?',
342
- choices
343
- }) as AIAssistant | typeof BACK_VALUE;
344
-
345
- if (assistant !== BACK_VALUE) {
346
- wizard.updateState({ assistant: assistant as AIAssistant });
347
- }
348
-
349
- return assistant;
350
- }
351
-
352
- async function handleSetupTypeStep(wizard: WizardStateManager): Promise<string> {
353
- const choices = addBackOption(
354
- [
355
- { value: 'quick', name: 'Quick Setup', description: 'Recommended settings for common use cases' },
356
- { value: 'custom', name: 'Custom', description: 'Select individual guidelines' }
357
- ],
358
- wizard.canGoBack()
359
- );
360
-
361
- const setupType = await select({
362
- message: 'Setup type?',
363
- choices
364
- }) as 'quick' | 'custom' | typeof BACK_VALUE;
365
-
366
- if (setupType !== BACK_VALUE) {
367
- wizard.updateState({ setupType: setupType as 'quick' | 'custom' });
368
- }
369
-
370
- return setupType;
371
- }
372
-
373
- async function handleArchitectureStep(wizard: WizardStateManager, options: InitOptions): Promise<string> {
374
- const state = wizard.getState();
375
- if (state.architecture) return state.architecture;
376
-
377
- if (options.architecture) {
378
- wizard.updateState({ architecture: options.architecture as ArchitectureType });
379
- return options.architecture;
380
- }
381
-
382
- const choices = addBackOption(
383
- ARCHITECTURES.map(a => ({
384
- value: a.value,
385
- name: a.name,
386
- description: a.description
387
- })),
388
- wizard.canGoBack()
389
- );
390
-
391
- const architecture = await select({
392
- message: 'Architecture pattern?',
393
- choices,
394
- default: 'modular-monolith'
395
- }) as ArchitectureType | typeof BACK_VALUE;
396
-
397
- if (architecture !== BACK_VALUE) {
398
- wizard.updateState({ architecture: architecture as ArchitectureType });
399
- }
400
-
401
- return architecture;
402
- }
403
-
404
- async function handleDatasourceStep(wizard: WizardStateManager): Promise<string> {
405
- const state = wizard.getState();
406
- if (state.datasource) return state.datasource;
407
-
408
- const choices = addBackOption(
409
- DATASOURCES.map(d => ({
410
- value: d.value,
411
- name: d.name,
412
- description: d.description
413
- })),
414
- wizard.canGoBack()
415
- );
416
-
417
- const datasource = await select({
418
- message: 'Data storage?',
419
- choices,
420
- default: 'sql'
421
- }) as DatasourceType | typeof BACK_VALUE;
422
-
423
- if (datasource !== BACK_VALUE) {
424
- wizard.updateState({ datasource: datasource as DatasourceType });
425
- }
426
-
427
- return datasource;
428
- }
429
-
430
- async function handleLevelStep(wizard: WizardStateManager, options: InitOptions): Promise<string> {
431
- const state = wizard.getState();
432
-
433
- if (options.level) {
434
- wizard.updateState({ level: options.level as InstructionLevel });
435
- return options.level;
436
- }
437
-
438
- const levelsWithMetrics = await getLevelsWithMetrics(
439
- state.language!,
440
- state.architecture!,
441
- state.datasource
442
- );
443
-
444
- const choices = addBackOption(
445
- levelsWithMetrics.map(l => ({
446
- value: l.value,
447
- name: l.name,
448
- description: l.description
449
- })),
450
- wizard.canGoBack()
451
- );
452
-
453
- const level = await select({
454
- message: 'Instruction detail level?',
455
- choices,
456
- default: 'standard'
457
- }) as InstructionLevel | typeof BACK_VALUE;
458
-
459
- if (level !== BACK_VALUE) {
460
- wizard.updateState({ level: level as InstructionLevel });
461
- }
462
-
463
- return level;
464
- }
465
-
466
- async function handleGuidelinesStep(wizard: WizardStateManager): Promise<string> {
467
- const state = wizard.getState();
468
-
469
- const selectedIds = await selectGuidelines(
470
- state.language!,
471
- state.level!,
472
- state.architecture!,
473
- wizard.canGoBack(),
474
- state.datasource
475
- );
476
-
477
- if (selectedIds === BACK_VALUE) {
478
- return BACK_VALUE;
479
- }
480
-
481
- wizard.updateState({ selectedGuidelineIds: selectedIds as string[] });
482
- return 'OK';
483
- }
484
-
485
- async function handleSummaryStep(wizard: WizardStateManager): Promise<boolean | string> {
486
- const state = wizard.getState();
487
- const loader = await GuidelineLoader.create();
488
-
489
- const guidelineIds = state.selectedGuidelineIds || loader.getGuidelinesForProfile(
490
- state.language!,
491
- state.level!,
492
- state.architecture!,
493
- state.datasource
494
- );
495
-
496
- const metrics = loader.getMetrics(guidelineIds);
497
-
498
- console.log('\n' + createSummaryBox('šŸ“‹ Configuration Summary', [
499
- { label: 'Assistant', value: state.assistant! },
500
- { label: 'Language', value: state.language! },
501
- { label: 'Project Type', value: state.projectType! },
502
- { label: 'Architecture', value: state.architecture! },
503
- { label: 'Data Storage', value: state.datasource! },
504
- { label: 'Level', value: state.level! },
505
- { label: 'Setup Type', value: state.setupType || 'standard' }
506
- ]));
507
-
508
- console.log('\n' + createMetricsBox([
509
- { label: 'guidelines', value: metrics.guidelineCount },
510
- { label: 'hooks', value: metrics.hooksCount },
511
- { label: 'sub-agents', value: metrics.subAgentsCount },
512
- { label: 'estimated size', value: metrics.estimatedSize }
513
- ]));
514
-
515
- // Show selected guidelines if in custom mode
516
- if (state.setupType === 'custom' && state.selectedGuidelineIds && state.selectedGuidelineIds.length > 0) {
517
- console.log(chalk.cyan('\nšŸ“š Selected Guidelines:'));
518
- const guidelineNames = state.selectedGuidelineIds.map(id => {
519
- const mapping = loader.getMapping(id);
520
- return mapping ? ` • ${mapping.category || 'General'}: ${id}` : ` • ${id}`;
521
- });
522
- console.log(guidelineNames.slice(0, 10).join('\n'));
523
- if (guidelineNames.length > 10) {
524
- console.log(chalk.gray(` ... and ${guidelineNames.length - 10} more`));
525
- }
526
- }
527
-
528
- console.log('');
529
-
530
- const shouldGenerate = await select({
531
- message: 'Proceed with generation?',
532
- choices: [
533
- { value: 'yes', name: 'Yes, generate configuration', description: 'Create config files' },
534
- ...(wizard.canGoBack() ? [{ value: BACK_VALUE, name: '← Back', description: 'Modify settings' }] : []),
535
- { value: 'no', name: 'Cancel', description: 'Exit without generating' }
536
- ]
537
- });
538
-
539
- if (shouldGenerate === 'yes') {
540
- return true;
541
- } else if (shouldGenerate === BACK_VALUE) {
542
- return BACK_VALUE;
543
- } else {
544
- return false;
545
- }
546
- }
547
-
548
- async function getLevelsWithMetrics(language: Language, architecture: ArchitectureType, datasource?: DatasourceType): Promise<{ value: InstructionLevel; name: string; description: string }[]> {
549
- const loader = await GuidelineLoader.create();
550
- const levels: InstructionLevel[] = ['basic', 'standard', 'expert', 'full'];
551
-
552
- return levels.map(level => {
553
- const guidelineIds = loader.getGuidelinesForProfile(language, level, architecture, datasource);
554
- const metrics = loader.getMetrics(guidelineIds);
555
-
556
- const descriptions: Record<InstructionLevel, string> = {
557
- basic: 'Essential guidelines for quick projects',
558
- standard: 'Production-ready practices',
559
- expert: 'Advanced patterns for scaling',
560
- full: 'Everything - all guidelines'
561
- };
562
-
563
- return {
564
- value: level,
565
- name: `${level.charAt(0).toUpperCase() + level.slice(1)}`,
566
- description: `${descriptions[level]} (${metrics.guidelineCount} guidelines, ${metrics.hooksCount} hooks, ${metrics.subAgentsCount} agents, ${metrics.estimatedSize})`
567
- };
568
- });
569
- }
570
-
571
- function printNextSteps(assistant: AIAssistant) {
572
- switch (assistant) {
573
- case 'claude-code':
574
- console.log(chalk.gray(' 1. Review .claude/CLAUDE.md'));
575
- console.log(chalk.gray(' 2. Check .claude/settings.json for hooks'));
576
- console.log(chalk.gray(' 3. Review sub-agents in .claude/agents/'));
577
- console.log(chalk.gray(' 4. Open project in Claude Code'));
578
- break;
579
- case 'copilot':
580
- console.log(chalk.gray(' 1. Review .github/copilot-instructions.md'));
581
- console.log(chalk.gray(' 2. Check .github/instructions/ for details'));
582
- console.log(chalk.gray(' 3. Open project in VS Code'));
583
- break;
584
- case 'gemini':
585
- console.log(chalk.gray(' 1. Review .gemini/instructions.md'));
586
- console.log(chalk.gray(' 2. Configure Gemini integration'));
587
- break;
588
- case 'antigravity':
589
- console.log(chalk.gray(' 1. Review .agent/rules/instructions.md'));
590
- console.log(chalk.gray(' 2. Open project in Antigravity'));
591
- break;
592
- case 'codex':
593
- console.log(chalk.gray(' 1. Review .codex/instructions.md'));
594
- console.log(chalk.gray(' 2. Configure Codex integration'));
595
- break;
596
- }
597
- console.log(chalk.gray(' \n Also check AGENTS.md for universal instructions'));
598
- }
599
-
600
- async function checkForUpdatesInBackground() {
601
- try {
602
- const loader = await GuidelineLoader.create();
603
- const currentVersion = loader.getVersion();
604
-
605
- if (currentVersion === 'embedded' || currentVersion === 'unknown') {
606
- return;
607
- }
608
-
609
- const response = await fetch(GITHUB_RELEASES_URL, {
610
- headers: {
611
- 'Accept': 'application/vnd.github+json',
612
- 'User-Agent': CONFIG.USER_AGENT
613
- }
614
- });
615
-
616
- if (!response.ok) return;
617
-
618
- const data = await response.json() as { tag_name: string };
619
- const latestVersion = data.tag_name.replace(/^v/, '');
620
-
621
- const currentParts = currentVersion.split('.').map(Number);
622
- const latestParts = latestVersion.split('.').map(Number);
623
-
624
- let needsUpdate = false;
625
- for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
626
- const curr = currentParts[i] || 0;
627
- const lat = latestParts[i] || 0;
628
-
629
- if (lat > curr) {
630
- needsUpdate = true;
631
- break;
632
- }
633
- if (lat < curr) break;
634
- }
635
-
636
- if (needsUpdate) {
637
- console.log(chalk.yellow(`\n šŸ“¦ New guidelines available: v${latestVersion}`));
638
- console.log(chalk.gray(` Run ${chalk.white('aicgen update')} to download\n`));
639
- }
640
- } catch {
641
- // Silently fail if can't check for updates
642
- }
643
- }
644
-
645
-