@aicgen/aicgen 1.0.0-beta.1 → 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.
Files changed (160) hide show
  1. package/{.claude/guidelines → .agent/rules}/api-design.md +5 -1
  2. package/{.claude/guidelines → .agent/rules}/architecture.md +5 -1
  3. package/{.claude/guidelines → .agent/rules}/best-practices.md +5 -1
  4. package/{.claude/guidelines → .agent/rules}/code-style.md +5 -1
  5. package/{.claude/guidelines → .agent/rules}/design-patterns.md +5 -1
  6. package/{.claude/guidelines → .agent/rules}/devops.md +5 -1
  7. package/{.claude/guidelines → .agent/rules}/error-handling.md +5 -1
  8. package/.agent/rules/instructions.md +28 -0
  9. package/{.claude/guidelines → .agent/rules}/language.md +5 -1
  10. package/{.claude/guidelines → .agent/rules}/performance.md +5 -1
  11. package/{.claude/guidelines → .agent/rules}/security.md +5 -1
  12. package/{.claude/guidelines → .agent/rules}/testing.md +5 -1
  13. package/.agent/workflows/add-documentation.md +10 -0
  14. package/.agent/workflows/generate-integration-tests.md +10 -0
  15. package/.agent/workflows/generate-unit-tests.md +11 -0
  16. package/.agent/workflows/performance-audit.md +11 -0
  17. package/.agent/workflows/refactor-extract-module.md +12 -0
  18. package/.agent/workflows/security-audit.md +12 -0
  19. package/.gemini/instructions.md +4843 -0
  20. package/.vs/ProjectSettings.json +2 -2
  21. package/.vs/VSWorkspaceState.json +15 -15
  22. package/.vs/aicgen.slnx/v18/DocumentLayout.json +53 -53
  23. package/AGENTS.md +9 -11
  24. package/assets/icon.svg +33 -33
  25. package/bun.lock +734 -26
  26. package/{CLAUDE.md → claude.md} +2 -2
  27. package/config.example.yml +129 -0
  28. package/config.yml +38 -0
  29. package/data/architecture/microservices/api-gateway.md +56 -56
  30. package/data/devops/observability.md +73 -73
  31. package/data/guideline-mappings.yml +128 -0
  32. package/data/language/dart/async.md +289 -0
  33. package/data/language/dart/basics.md +280 -0
  34. package/data/language/dart/error-handling.md +355 -0
  35. package/data/language/dart/index.md +10 -0
  36. package/data/language/dart/testing.md +352 -0
  37. package/data/language/swift/basics.md +477 -0
  38. package/data/language/swift/concurrency.md +654 -0
  39. package/data/language/swift/error-handling.md +679 -0
  40. package/data/language/swift/swiftui-mvvm.md +795 -0
  41. package/data/language/swift/testing.md +708 -0
  42. package/data/version.json +10 -8
  43. package/dist/index.js +50153 -28959
  44. package/jest.config.js +46 -0
  45. package/package.json +14 -3
  46. package/.claude/agents/architecture-reviewer.md +0 -88
  47. package/.claude/agents/guideline-checker.md +0 -73
  48. package/.claude/agents/security-auditor.md +0 -108
  49. package/.claude/settings.json +0 -98
  50. package/.claude/settings.local.json +0 -8
  51. package/.eslintrc.json +0 -28
  52. package/.github/workflows/release.yml +0 -180
  53. package/.github/workflows/test.yml +0 -81
  54. package/CONTRIBUTING.md +0 -821
  55. package/dist/commands/init.d.ts +0 -8
  56. package/dist/commands/init.d.ts.map +0 -1
  57. package/dist/commands/init.js +0 -46
  58. package/dist/commands/init.js.map +0 -1
  59. package/dist/config/profiles.d.ts +0 -4
  60. package/dist/config/profiles.d.ts.map +0 -1
  61. package/dist/config/profiles.js +0 -30
  62. package/dist/config/profiles.js.map +0 -1
  63. package/dist/config/settings.d.ts +0 -7
  64. package/dist/config/settings.d.ts.map +0 -1
  65. package/dist/config/settings.js +0 -7
  66. package/dist/config/settings.js.map +0 -1
  67. package/dist/index.d.ts +0 -3
  68. package/dist/index.d.ts.map +0 -1
  69. package/dist/index.js.map +0 -1
  70. package/dist/models/guideline.d.ts +0 -15
  71. package/dist/models/guideline.d.ts.map +0 -1
  72. package/dist/models/guideline.js +0 -2
  73. package/dist/models/guideline.js.map +0 -1
  74. package/dist/models/preference.d.ts +0 -9
  75. package/dist/models/preference.d.ts.map +0 -1
  76. package/dist/models/preference.js +0 -2
  77. package/dist/models/preference.js.map +0 -1
  78. package/dist/models/profile.d.ts +0 -9
  79. package/dist/models/profile.d.ts.map +0 -1
  80. package/dist/models/profile.js +0 -2
  81. package/dist/models/profile.js.map +0 -1
  82. package/dist/models/project.d.ts +0 -13
  83. package/dist/models/project.d.ts.map +0 -1
  84. package/dist/models/project.js +0 -2
  85. package/dist/models/project.js.map +0 -1
  86. package/dist/services/ai/anthropic.d.ts +0 -7
  87. package/dist/services/ai/anthropic.d.ts.map +0 -1
  88. package/dist/services/ai/anthropic.js +0 -39
  89. package/dist/services/ai/anthropic.js.map +0 -1
  90. package/dist/services/generator.d.ts +0 -2
  91. package/dist/services/generator.d.ts.map +0 -1
  92. package/dist/services/generator.js +0 -4
  93. package/dist/services/generator.js.map +0 -1
  94. package/dist/services/learner.d.ts +0 -2
  95. package/dist/services/learner.d.ts.map +0 -1
  96. package/dist/services/learner.js +0 -4
  97. package/dist/services/learner.js.map +0 -1
  98. package/dist/services/scanner.d.ts +0 -3
  99. package/dist/services/scanner.d.ts.map +0 -1
  100. package/dist/services/scanner.js +0 -54
  101. package/dist/services/scanner.js.map +0 -1
  102. package/dist/utils/errors.d.ts +0 -15
  103. package/dist/utils/errors.d.ts.map +0 -1
  104. package/dist/utils/errors.js +0 -27
  105. package/dist/utils/errors.js.map +0 -1
  106. package/dist/utils/file.d.ts +0 -7
  107. package/dist/utils/file.d.ts.map +0 -1
  108. package/dist/utils/file.js +0 -32
  109. package/dist/utils/file.js.map +0 -1
  110. package/dist/utils/logger.d.ts +0 -6
  111. package/dist/utils/logger.d.ts.map +0 -1
  112. package/dist/utils/logger.js +0 -17
  113. package/dist/utils/logger.js.map +0 -1
  114. package/dist/utils/path.d.ts +0 -6
  115. package/dist/utils/path.d.ts.map +0 -1
  116. package/dist/utils/path.js +0 -14
  117. package/dist/utils/path.js.map +0 -1
  118. package/docs/planning/memory-lane.md +0 -83
  119. package/packaging/linux/aicgen.spec +0 -23
  120. package/packaging/linux/control +0 -9
  121. package/packaging/macos/scripts/postinstall +0 -12
  122. package/packaging/windows/setup.nsi +0 -92
  123. package/scripts/add-categories.ts +0 -87
  124. package/scripts/build-binary.ts +0 -46
  125. package/scripts/embed-data.ts +0 -105
  126. package/scripts/generate-version.ts +0 -150
  127. package/scripts/test-decompress.ts +0 -27
  128. package/scripts/test-extract.ts +0 -31
  129. package/src/__tests__/services/assistant-file-writer.test.ts +0 -400
  130. package/src/__tests__/services/guideline-loader.test.ts +0 -281
  131. package/src/__tests__/services/tarball-extraction.test.ts +0 -125
  132. package/src/commands/add-guideline.ts +0 -296
  133. package/src/commands/clear.ts +0 -61
  134. package/src/commands/guideline-selector.ts +0 -123
  135. package/src/commands/init.ts +0 -645
  136. package/src/commands/quick-add.ts +0 -586
  137. package/src/commands/remove-guideline.ts +0 -152
  138. package/src/commands/stats.ts +0 -49
  139. package/src/commands/update.ts +0 -240
  140. package/src/config.ts +0 -82
  141. package/src/embedded-data.ts +0 -1492
  142. package/src/index.ts +0 -67
  143. package/src/models/profile.ts +0 -24
  144. package/src/models/project.ts +0 -43
  145. package/src/services/assistant-file-writer.ts +0 -612
  146. package/src/services/config-generator.ts +0 -150
  147. package/src/services/config-manager.ts +0 -70
  148. package/src/services/data-source.ts +0 -248
  149. package/src/services/first-run-init.ts +0 -148
  150. package/src/services/guideline-loader.ts +0 -311
  151. package/src/services/hook-generator.ts +0 -178
  152. package/src/services/subagent-generator.ts +0 -310
  153. package/src/utils/banner.ts +0 -66
  154. package/src/utils/errors.ts +0 -27
  155. package/src/utils/file.ts +0 -67
  156. package/src/utils/formatting.ts +0 -172
  157. package/src/utils/logger.ts +0 -89
  158. package/src/utils/path.ts +0 -17
  159. package/src/utils/wizard-state.ts +0 -132
  160. package/tsconfig.json +0 -25
@@ -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
-