@silvestv/migration-planificator 7.1.0 → 7.1.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 (34) hide show
  1. package/dist/client.bundle.js +200 -182
  2. package/dist/src/autofix/cli/fix-command.js +6 -4
  3. package/dist/src/autofix/generators/context-generator.js +71 -2
  4. package/dist/src/autofix/generators/file-prompt-generator.js +22 -3
  5. package/dist/src/autofix/prompts/constitution.js +23 -0
  6. package/dist/src/autofix/prompts/file-prompt-complex.js +129 -0
  7. package/dist/src/autofix/prompts/file-prompt-diagnostics.js +2 -98
  8. package/dist/src/autofix/prompts/file-prompt-phases.js +106 -44
  9. package/dist/src/autofix/prompts/file-prompt-reference.js +7 -25
  10. package/dist/src/autofix/prompts/file-prompt-routine.js +160 -0
  11. package/dist/src/autofix/prompts/file-prompt-shared.js +82 -0
  12. package/dist/src/data/rules/to18/rules-18-obligatoire.json +382 -368
  13. package/dist/src/data/rules/to18/rules-18-optionnelle.json +135 -131
  14. package/dist/src/data/rules/to18/rules-18-recommande.json +113 -110
  15. package/dist/src/data/rules/to19/rules-19-obligatoire.json +204 -15
  16. package/dist/src/data/rules/to19/rules-19-optionnelle.json +12 -6
  17. package/dist/src/data/rules/to19/rules-19-recommande.json +11 -5
  18. package/dist/src/data/rules/to20/rules-20-obligatoire.json +15 -3
  19. package/dist/src/data/rules/to20/rules-20-optionnelle.json +2 -2
  20. package/dist/src/data/rules/to20/rules-20-recommande.json +2 -0
  21. package/dist/src/data/rules/to21/rules-21-obligatoire.json +12 -2
  22. package/dist/src/data/rules/to21/rules-21-optionnelle.json +2 -1
  23. package/dist/src/data/rules/to21/rules-21-recommande.json +4 -0
  24. package/dist/src/models/constants/fix-ai-cli-permissions.js +35 -6
  25. package/dist/src/models/constants/nx-angular-compatibility.js +50 -0
  26. package/dist/src/models/interfaces/ai-specification.interface.js +18 -0
  27. package/dist/src/models/types/routine-type.type.js +2 -0
  28. package/dist/src/templates/workload/rule-modal.template.js +74 -0
  29. package/dist/src/utils/autofix/bash-commands-helpers.js +14 -0
  30. package/dist/src/utils/autofix/compatibility-helpers.js +35 -0
  31. package/dist/src/utils/core/rule-helpers.js +3 -2
  32. package/dist/src/utils/shared/rule-helpers.js +32 -0
  33. package/dist/styles.css +1 -1
  34. package/package.json +1 -1
@@ -5,14 +5,15 @@
5
5
  "description": "Angular 21 requiert Node.js 20.19.0+, 22.12.0+ ou 24.0.0+ et TypeScript 5.9+. Cette version active le mode zoneless par defaut pour les nouvelles applications et introduit Vitest comme test runner stable. Les applications existantes utilisant Zone.js doivent ajouter explicitement provideZoneChangeDetection().",
6
6
  "estimated_time_per_occurrence": 30,
7
7
  "onFile": "package.json",
8
+ "routineType": "environment-migration",
8
9
  "fileTypes": ["package.json"],
9
10
  "regex": "\"@angular/(core|cli)\"\\s*:\\s*\"(?:(?:\\^|~)?(?:1[0-9]|20)(?:\\.\\d+){0,2})\"",
10
11
  "category": "environment",
11
12
  "isAutoFixable": false,
12
13
  "migration_command": "npx ng update @angular/core@21 @angular/cli@21",
13
- "nxMigrationCommand": "npx nx migrate @angular/core@21 @angular/cli@21 && npx nx migrate --run-migrations",
14
+ "nxMigrationCommand": "npx nx migrate nx@22.4.1 && npm install && npm install typescript@~5.9.0 && npx nx migrate --run-migrations",
14
15
  "risk_level": "critical",
15
- "code_description": "// Migration Angular 21\n// Node : ^20.19.0 || ^22.12.0 || ^24.0.0\n// TypeScript : ~5.9.0\n// Commande Angular CLI :\n// npx ng update @angular/core@21 @angular/cli@21\n// Commande Nx :\n// npx nx migrate @angular/core@21 @angular/cli@21 && npx nx migrate --run-migrations",
16
+ "code_description": "// Migration Angular 20 → 21 (Nx)\n// 1. npx nx migrate nx@22.4.1\n// 2. Mettre à jour deps tierces Angular dans package.json vers @21+ !!! Bonne version de typescript si non spécifié !!!\n// 3. npm install && npm install typescript@~5.9.0\n// 4. npx nx migrate --run-migrations",
16
17
  "doc_url": "https://angular.dev/reference/migrations"
17
18
  },
18
19
  {
@@ -25,6 +26,7 @@
25
26
  "regex": "^(?![\\s\\S]*\"typescript\"[\\s\\S]*\"[<>=~^]*(?:5\\.9|[6-9]\\d*)\\.)[\\s\\S]+",
26
27
  "category": "environment",
27
28
  "isAutoFixable": true,
29
+ "minAngularVersion": 20,
28
30
  "migration_command": "npm install typescript@~5.9.0",
29
31
  "risk_level": "medium",
30
32
  "code_description": "// package.json\n// Avant: \"typescript\": \"~5.8.0\"\n// Apres: \"typescript\": \"~5.9.0\"",
@@ -59,6 +61,7 @@
59
61
  },
60
62
  "category": "environment",
61
63
  "isAutoFixable": true,
64
+ "minAngularVersion": 20,
62
65
  "migration_command": null,
63
66
  "risk_level": "critical",
64
67
  "code_description": "// BREAKING CHANGE: Zoneless par defaut en Angular 21\n// Projets utilisant Zone.js doivent declarer explicitement leur choix:\n\n// Option 1 - Garder Zone.js:\nbootstrapApplication(AppComponent, {\n providers: [\n provideZoneChangeDetection(), // Explicite pour Zone.js\n provideRouter(routes)\n ]\n});\n\n// Option 2 - Migrer vers zoneless:\nbootstrapApplication(AppComponent, {\n providers: [\n provideZonelessChangeDetection(), // Mode zoneless\n provideBrowserGlobalErrorListeners()\n ]\n});",
@@ -93,6 +96,7 @@
93
96
  },
94
97
  "category": "environment",
95
98
  "isAutoFixable": true,
99
+ "minAngularVersion": 20,
96
100
  "migration_command": null,
97
101
  "risk_level": "critical",
98
102
  "code_description": "// BREAKING CHANGE: Zoneless par defaut en Angular 21\n// Projets NgModule utilisant Zone.js doivent declarer explicitement leur choix:\n\n// Option 1 - Garder Zone.js:\n@NgModule({\n bootstrap: [AppComponent],\n providers: [\n provideZoneChangeDetection() // Explicite pour Zone.js\n ]\n})\nexport class AppModule {}\n\n// Option 2 - Migrer vers zoneless (standalone recommande):\n// Convertir en standalone et utiliser provideZonelessChangeDetection()",
@@ -109,6 +113,7 @@
109
113
  "regex": "zone\\.js",
110
114
  "category": "environment",
111
115
  "isAutoFixable": true,
116
+ "minAngularVersion": 20,
112
117
  "migration_command": null,
113
118
  "risk_level": "high",
114
119
  "code_description": "// Si migration vers zoneless:\n\n// angular.json - Supprimer de polyfills:\n\"polyfills\": [\n // \"zone.js\" - SUPPRIMER\n // \"zone.js/testing\" - SUPPRIMER\n]\n\n// polyfills.ts - Supprimer:\n// import 'zone.js'; - SUPPRIMER\n\n// ATTENTION: Garder zone.js si vous utilisez provideZoneChangeDetection()",
@@ -182,6 +187,7 @@
182
187
  },
183
188
  "category": "component",
184
189
  "isAutoFixable": true,
190
+ "minAngularVersion": 20,
185
191
  "migration_command": null,
186
192
  "risk_level": "low",
187
193
  "code_description": "// BREAKING CHANGE: Propriete moduleId supprimee\n\n// Avant:\n@Component({\n selector: 'app-legacy',\n moduleId: module.id,\n templateUrl: './legacy.component.html'\n})\n\n// Apres - Supprimer moduleId:\n@Component({\n selector: 'app-legacy',\n templateUrl: './legacy.component.html'\n})",
@@ -260,6 +266,7 @@
260
266
  },
261
267
  "category": "imports",
262
268
  "isAutoFixable": true,
269
+ "minAngularVersion": 20,
263
270
  "migration_command": null,
264
271
  "risk_level": "low",
265
272
  "code_description": "// BREAKING CHANGE: Import ApplicationConfig change\n\n// Avant:\nimport { ApplicationConfig } from '@angular/platform-browser';\n\n// Apres:\nimport { ApplicationConfig } from '@angular/core';",
@@ -385,6 +392,7 @@
385
392
  "regex": "\"emitDeclarationOnly\"\\s*:\\s*true",
386
393
  "category": "config",
387
394
  "isAutoFixable": true,
395
+ "minAngularVersion": 20,
388
396
  "migration_command": null,
389
397
  "risk_level": "medium",
390
398
  "code_description": "// BREAKING CHANGE: emitDeclarationOnly non supporte\n\n// Avant - tsconfig.json:\n{\n \"compilerOptions\": {\n \"emitDeclarationOnly\": true\n }\n}\n\n// Apres - Supprimer ou false:\n{\n \"compilerOptions\": {\n // \"emitDeclarationOnly\": false - ou supprimer\n }\n}",
@@ -408,6 +416,7 @@
408
416
  },
409
417
  "category": "routing",
410
418
  "isAutoFixable": true,
419
+ "minAngularVersion": 20,
411
420
  "migration_command": null,
412
421
  "risk_level": "medium",
413
422
  "code_description": "// BREAKING CHANGE: lastSuccessfulNavigation est un Signal\n\n// Avant:\nconst nav = this.router.lastSuccessfulNavigation;\nconst state = nav?.extras.state;\n\n// Apres:\nconst nav = this.router.lastSuccessfulNavigation();\nconst state = nav?.extras.state;\n\n// Dans template:\n{{ router.lastSuccessfulNavigation()?.extractedUrl }}",
@@ -431,6 +440,7 @@
431
440
  },
432
441
  "category": "routing",
433
442
  "isAutoFixable": true,
443
+ "minAngularVersion": 20,
434
444
  "migration_command": null,
435
445
  "risk_level": "low",
436
446
  "code_description": "// getCurrentNavigation() deprecie\n\n// Avant:\nconst nav = this.router.getCurrentNavigation();\n\n// Apres - Signal:\nconst nav = this.router.currentNavigation();",
@@ -148,7 +148,8 @@
148
148
  "fileTypes": ["package.json"],
149
149
  "regex": "^(?![\\s\\S]*\"tailwindcss\"[\\s\\S]*:)[\\s\\S]+",
150
150
  "category": "style",
151
- "isAutoFixable": true,
151
+ "isAutoFixable": false,
152
+ "minAngularVersion": 20,
152
153
  "migration_command": "npx ng add tailwindcss",
153
154
  "nxMigrationCommand": "npx nx add tailwindcss",
154
155
  "risk_level": "low",
@@ -33,6 +33,7 @@
33
33
  },
34
34
  "category": "http",
35
35
  "isAutoFixable": true,
36
+ "minAngularVersion": 20,
36
37
  "migration_command": null,
37
38
  "risk_level": "low",
38
39
  "code_description": "// HttpClient fourni par defaut en Angular 21\n\n// Avant - provideHttpClient necessaire:\nexport const appConfig: ApplicationConfig = {\n providers: [\n provideHttpClient(), // N'est plus necessaire\n ]\n};\n\n// Apres - Configuration basique:\nexport const appConfig: ApplicationConfig = {\n providers: [\n // HttpClient disponible automatiquement\n ]\n};\n\n// Avec interceptors (provideHttpClient toujours requis):\nexport const appConfig: ApplicationConfig = {\n providers: [\n provideHttpClient(\n withInterceptors([authInterceptor]),\n withFetch() // Optionnel\n )\n ]\n};",
@@ -81,6 +82,7 @@
81
82
  },
82
83
  "category": "template",
83
84
  "isAutoFixable": true,
85
+ "minAngularVersion": 17,
84
86
  "migration_command": "npx ng generate @angular/core:ngclass-to-class --path=./",
85
87
  "nxMigrationCommand": "npx nx generate @angular/core:ngclass-to-class --path=./",
86
88
  "risk_level": "low",
@@ -102,6 +104,7 @@
102
104
  },
103
105
  "category": "template",
104
106
  "isAutoFixable": true,
107
+ "minAngularVersion": 17,
105
108
  "migration_command": "npx ng generate @angular/core:ngstyle-to-style --path=./",
106
109
  "nxMigrationCommand": "npx nx generate @angular/core:ngstyle-to-style --path=./",
107
110
  "risk_level": "low",
@@ -133,6 +136,7 @@
133
136
  },
134
137
  "category": "imports",
135
138
  "isAutoFixable": true,
139
+ "minAngularVersion": 15,
136
140
  "migration_command": "npx ng generate @angular/core:common-to-standalone --path=./",
137
141
  "nxMigrationCommand": "npx nx generate @angular/core:common-to-standalone --path=./",
138
142
  "risk_level": "low",
@@ -33,6 +33,9 @@ exports.CLI_ALLOWED_COMMANDS = [
33
33
  'Bash(npx nx migrate @angular/core@* @angular/cli@*)',
34
34
  'Bash(npx nx migrate --run-migrations)',
35
35
  'Bash(npx nx migrate --run-migrations=*)',
36
+ "Bash(npx nx migrate nx@*)",
37
+ "Bash(npx nx migrate *)",
38
+ "Bash(npx nx report)",
36
39
  // === Nx CLI - Schematics (generate/g) ===
37
40
  'Bash(npx nx generate @angular/*)',
38
41
  'Bash(npx nx g @angular/*)',
@@ -43,19 +46,37 @@ exports.CLI_ALLOWED_COMMANDS = [
43
46
  // === npm - Install packages ===
44
47
  'Bash(npm install typescript@*)',
45
48
  'Bash(npm install @angular/*)',
49
+ 'Bash(npm i)',
50
+ 'Bash(npm i -D)',
51
+ 'Bash(npm i -D*)',
52
+ 'Bash(npm install)',
53
+ 'Bash(npm install -D)',
46
54
  'Bash(npm i * --save-dev)',
47
55
  'Bash(npm i *)',
48
56
  'Bash(npm install * --save-dev)',
49
57
  'Bash(npm install *)',
58
+ 'Bash(rm -rf node_modules package-lock.json && npm install)',
50
59
  'Bash(npm pkg *)',
51
60
  'Bash(npm pkg get *)',
52
61
  // === Build & Test ===
53
- 'Bash(npm run build)',
62
+ 'Bash(npm run build*)',
54
63
  'Bash(npm run build:*)',
55
- 'Bash(npm test)',
64
+ 'Bash(npm test*)',
56
65
  'Bash(npm test:*)',
57
- 'Bash(npm run test)',
66
+ 'Bash(npm run test*)',
58
67
  'Bash(npm run test:*)',
68
+ 'Bash(npm ls *)',
69
+ 'Bash(npm view*)',
70
+ 'Bash(grep*)',
71
+ 'Bash(grep *)',
72
+ 'Bash(echo*)',
73
+ 'Bash(echo *)',
74
+ 'Bash(sed*)',
75
+ 'Bash(sed *)',
76
+ 'Bash(perl*)',
77
+ 'Bash(perl *)',
78
+ 'Bash(tee*)',
79
+ 'Bash(tee *)',
59
80
  // === Git - Read operations ===
60
81
  'Bash(git status)',
61
82
  'Bash(git status *)',
@@ -69,8 +90,16 @@ exports.CLI_ALLOWED_COMMANDS = [
69
90
  'Bash(git checkout *)',
70
91
  'Bash(git checkout -b *)',
71
92
  'Bash(git add *)',
72
- 'Bash(git commit *)',
73
- 'Bash(git commit -m *)',
93
+ "Bash(git commit*)",
74
94
  'Bash(git push *)',
75
- 'Bash(git push -u *)'
95
+ 'Bash(git push -u *)',
96
+ // === Nx / Angular - Versions ===
97
+ 'Bash(npx nx --version)',
98
+ // === AST Engine ===
99
+ 'Bash(npx @silvestv/migration-planificator *)',
100
+ // === FileSystem Visualisation ===
101
+ 'Bash(ls *)',
102
+ 'Bash(pwd *)',
103
+ // === Web Search - Angular Documentation ===
104
+ 'WebFetch(domain:angular.dev)',
76
105
  ];
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ /**
3
+ * Table de migration Nx → Angular pour migrations incrémentales
4
+ *
5
+ * IMPORTANT: Les migrations Angular sont embarquées dans chaque version majeure de Nx.
6
+ * - Nx 19 contient les migrations Angular 17 → 18
7
+ * - Nx 20 contient les migrations Angular 18 → 19
8
+ * - Nx 21 contient les migrations Angular 19 → 20
9
+ * - Nx 22 contient les migrations Angular 20 → 21
10
+ *
11
+ * On ne peut PAS sauter des versions ! `nx migrate nx@22` sur Angular 17
12
+ * ne génèrera PAS les migrations Angular 17→18 car elles n'existent plus dans Nx 22.
13
+ *
14
+ * Source: https://github.com/nrwl/nx/issues/31960
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.NX_ANGULAR_MIGRATION = void 0;
18
+ exports.getNxMigrateVersion = getNxMigrateVersion;
19
+ exports.getNxMigrateCommand = getNxMigrateCommand;
20
+ /**
21
+ * Table de migration Nx → Angular
22
+ * Clé = version Angular cible (18, 19, 20, 21)
23
+ */
24
+ exports.NX_ANGULAR_MIGRATION = {
25
+ '18': { nxVersion: '19.8.14', description: 'Angular 17 → 18' },
26
+ '19': { nxVersion: '20.8.4', description: 'Angular 18 → 19' },
27
+ '20': { nxVersion: '21.6.10', description: 'Angular 19 → 20' },
28
+ '21': { nxVersion: '22.4.1', description: 'Angular 20 → 21' },
29
+ };
30
+ /**
31
+ * Retourne la version Nx à utiliser pour migrer vers une version Angular
32
+ * @param angularTargetVersion Version Angular cible (ex: "18", "19")
33
+ * @returns Version Nx pour la migration ou null si non trouvée
34
+ */
35
+ function getNxMigrateVersion(angularTargetVersion) {
36
+ const target = exports.NX_ANGULAR_MIGRATION[angularTargetVersion];
37
+ return target?.nxVersion ?? null;
38
+ }
39
+ /**
40
+ * Génère la commande complète de migration Nx pour une version Angular cible
41
+ * Inclut: nx migrate + npm install + run-migrations + stabilisation deps
42
+ * @param angularTargetVersion Version Angular cible (ex: "18")
43
+ * @returns Commande complète de migration
44
+ */
45
+ function getNxMigrateCommand(angularTargetVersion) {
46
+ const nxVersion = getNxMigrateVersion(angularTargetVersion);
47
+ if (!nxVersion)
48
+ return null;
49
+ return `npx nx migrate nx@${nxVersion}`;
50
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ /**
3
+ * Spécification AI pour règles de migration complexes
4
+ * Permet de définir un workflow multi-stages structuré pour l'agent
5
+ *
6
+ * Terminologie (évite confusion avec PHASE 1-7 du file-prompt) :
7
+ * - Stage = Étape macro du workflow (ex: PRE-SCHEMATIC, POST-SCHEMATIC)
8
+ * - Action = Instruction individuelle avec exemple de code
9
+ *
10
+ * @example
11
+ * ai_specification: {
12
+ * isComplex: true,
13
+ * criticalNote: "Le schematic ne migre que 90-95% des cas",
14
+ * stages: [...],
15
+ * knownLimitations: ["SharedModule", "CoreModule"]
16
+ * }
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -5,12 +5,14 @@
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.renderRuleModals = renderRuleModals;
7
7
  exports.renderDescriptionSection = renderDescriptionSection;
8
+ exports.renderAiSpecificationSection = renderAiSpecificationSection;
8
9
  exports.renderCodeExamplesSection = renderCodeExamplesSection;
9
10
  exports.renderMigrationCommandSection = renderMigrationCommandSection;
10
11
  exports.renderDocumentationSection = renderDocumentationSection;
11
12
  exports.renderAffectedFilesSection = renderAffectedFilesSection;
12
13
  exports.renderMetadataSection = renderMetadataSection;
13
14
  const shared_1 = require("../../utils/shared");
15
+ const rule_helpers_1 = require("../../utils/shared/rule-helpers");
14
16
  /**
15
17
  * Génère tous les modals pour les règles
16
18
  * @param rules Liste des règles
@@ -86,6 +88,7 @@ function renderModalBody(rule, matches, projectType) {
86
88
  return `
87
89
  <div class="p-6 space-y-6">
88
90
  ${renderDescriptionSection(rule)}
91
+ ${renderAiSpecificationSection(rule)}
89
92
  ${renderCodeExamplesSection(rule)}
90
93
  ${renderMigrationCommandSection(rule, projectType)}
91
94
  ${renderDocumentationSection(rule)}
@@ -106,6 +109,77 @@ function renderDescriptionSection(rule) {
106
109
  </section>
107
110
  `;
108
111
  }
112
+ /**
113
+ * Section Spécification AI pour règles complexes
114
+ * Affiche le workflow multi-phases si ai_specification existe
115
+ */
116
+ function renderAiSpecificationSection(rule) {
117
+ if (!(0, rule_helpers_1.hasComplexAiSpecification)(rule))
118
+ return '';
119
+ const spec = rule.ai_specification;
120
+ return `
121
+ <section class="bg-gradient-to-r from-purple-50 to-blue-50 border border-purple-200 rounded-lg p-4">
122
+ <h3 class="text-lg font-bold text-purple-800 mb-3 flex items-center">
123
+ <span class="mr-2">🤖</span> Workflow AI (Règle Complexe)
124
+ </h3>
125
+
126
+ ${spec.criticalNote ? `
127
+ <div class="bg-amber-100 border-l-4 border-amber-500 p-3 mb-4 rounded">
128
+ <p class="text-amber-800 font-medium">⚠️ ${(0, shared_1.escapeHtml)(spec.criticalNote)}</p>
129
+ </div>
130
+ ` : ''}
131
+
132
+ ${spec.knownLimitations?.length ? `
133
+ <div class="mb-4">
134
+ <h4 class="font-semibold text-gray-700 mb-2">Limitations connues (schematic) :</h4>
135
+ <ul class="list-disc list-inside text-sm text-gray-600 space-y-1">
136
+ ${spec.knownLimitations.map(l => `<li>${(0, shared_1.escapeHtml)(l)}</li>`).join('')}
137
+ </ul>
138
+ </div>
139
+ ` : ''}
140
+
141
+ <div class="space-y-3">
142
+ <h4 class="font-semibold text-gray-700">Stages de migration (${spec.stages.length}) :</h4>
143
+ ${spec.stages.map(stage => renderAiStageCard(stage)).join('')}
144
+ </div>
145
+
146
+ ${spec.verificationCommands?.length ? `
147
+ <div class="mt-4 pt-3 border-t border-purple-200">
148
+ <h4 class="font-semibold text-gray-700 mb-2">Commandes de vérification :</h4>
149
+ <div class="bg-gray-800 rounded p-2 text-xs">
150
+ ${spec.verificationCommands.map(c => `<code class="block text-green-400 font-mono">${(0, shared_1.escapeHtml)(c)}</code>`).join('')}
151
+ </div>
152
+ </div>
153
+ ` : ''}
154
+ </section>
155
+ `;
156
+ }
157
+ /**
158
+ * Génère une card pour un stage AI
159
+ */
160
+ function renderAiStageCard(stage) {
161
+ return `
162
+ <details class="bg-white rounded-lg border border-gray-200 overflow-hidden">
163
+ <summary class="px-4 py-2 cursor-pointer hover:bg-gray-50 flex items-center">
164
+ <span class="w-6 h-6 rounded-full bg-purple-600 text-white text-xs flex items-center justify-center mr-3">${stage.number}</span>
165
+ <span class="font-medium text-gray-800">${(0, shared_1.escapeHtml)(stage.name)}</span>
166
+ <span class="ml-2 text-sm text-gray-500">— ${(0, shared_1.escapeHtml)(stage.description)}</span>
167
+ </summary>
168
+ <div class="px-4 py-3 bg-gray-50 border-t border-gray-200">
169
+ <ol class="list-decimal list-inside space-y-2 text-sm text-gray-700">
170
+ ${stage.actions.map(action => `
171
+ <li>
172
+ <span>${(0, shared_1.escapeHtml)(action.instruction)}</span>
173
+ ${action.codeExample ? `
174
+ <pre class="mt-1 ml-4 bg-gray-800 text-green-400 p-2 rounded text-xs overflow-x-auto"><code>${(0, shared_1.escapeHtml)(action.codeExample)}</code></pre>
175
+ ` : ''}
176
+ </li>
177
+ `).join('')}
178
+ </ol>
179
+ </div>
180
+ </details>
181
+ `;
182
+ }
109
183
  /**
110
184
  * Section Exemples de Code
111
185
  * Exportée pour réutilisation dans guide-rule-card.template.ts
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.logCmd = void 0;
4
+ /**
5
+ * Génère la commande de capture de log pour build/test
6
+ * Note: \\x1b produit le texte littéral \x1b dans le markdown (pas le caractère ESC)
7
+ */
8
+ const logCmd = (migrationNumber, ruleKey, type) => {
9
+ const command = type === 'build' ? 'npm run build' : 'npm test';
10
+ const label = type === 'build' ? 'BUILD' : 'TEST';
11
+ const logDir = `./output/ai/migration/${migrationNumber}/${ruleKey}-prompts/${type}_logs`;
12
+ return `${command} 2>&1 | perl -pe 's/\\x1b\\[[0-9;]*m//g' | grep -iE -A 60 "error|fail|exception|fatal" > ${logDir}/log_N.txt; echo "${label} EXIT: $?"`;
13
+ };
14
+ exports.logCmd = logCmd;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractAngularVersion = extractAngularVersion;
4
+ exports.getTypescriptVersion = getTypescriptVersion;
5
+ /**
6
+ * Extrait la version Angular cible depuis la commande de migration
7
+ * Ex: "npx nx migrate nx@19.8.14" → "18" (Nx 19 = Angular 18)
8
+ */
9
+ function extractAngularVersion(command) {
10
+ if (!command)
11
+ return 'X';
12
+ // Pattern pour ng update @angular/core@XX
13
+ const ngMatch = command.match(/@angular\/core@(\d+)/);
14
+ if (ngMatch)
15
+ return ngMatch[1];
16
+ // Pattern pour nx migrate nx@XX (Nx version = Angular version + 1)
17
+ const nxMatch = command.match(/nx@(\d+)/);
18
+ if (nxMatch) {
19
+ const nxMajor = parseInt(nxMatch[1], 10);
20
+ return String(nxMajor - 1); // Nx 19 → Angular 18
21
+ }
22
+ return 'X';
23
+ }
24
+ /**
25
+ * Retourne la version TypeScript recommandée pour une version Angular
26
+ */
27
+ function getTypescriptVersion(angularVersion) {
28
+ const tsVersions = {
29
+ '18': '5.4.5',
30
+ '19': '5.5.4',
31
+ '20': '5.8.3',
32
+ '21': '5.9.3',
33
+ };
34
+ return tsVersions[angularVersion] ?? '5.4.0';
35
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isRoutineRule = void 0;
3
+ exports.isEnvironmentMigrationRule = exports.isRoutineRule = void 0;
4
4
  exports.createRuleMap = createRuleMap;
5
5
  /**
6
6
  * Crée une Map ruleKey → Rule pour accès rapide O(1)
@@ -10,6 +10,7 @@ exports.createRuleMap = createRuleMap;
10
10
  function createRuleMap(rules) {
11
11
  return new Map(rules.map(r => [r.key, r]));
12
12
  }
13
- // Re-export isRoutineRule depuis shared pour rétrocompatibilité
13
+ // Re-export depuis shared pour rétrocompatibilité
14
14
  var rule_helpers_1 = require("../shared/rule-helpers");
15
15
  Object.defineProperty(exports, "isRoutineRule", { enumerable: true, get: function () { return rule_helpers_1.isRoutineRule; } });
16
+ Object.defineProperty(exports, "isEnvironmentMigrationRule", { enumerable: true, get: function () { return rule_helpers_1.isEnvironmentMigrationRule; } });
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isRoutineRule = isRoutineRule;
4
+ exports.isEnvironmentMigrationRule = isEnvironmentMigrationRule;
5
+ exports.hasComplexAiSpecification = hasComplexAiSpecification;
4
6
  /**
5
7
  * Identifie si une règle est une routine (tâche manuelle unique par projet)
6
8
  *
@@ -18,3 +20,33 @@ exports.isRoutineRule = isRoutineRule;
18
20
  function isRoutineRule(rule) {
19
21
  return !!rule.onFile;
20
22
  }
23
+ /**
24
+ * Identifie si une règle est une migration d'environnement complète
25
+ *
26
+ * Ces règles déclenchent le workflow complet avec :
27
+ * - Mise à jour des dépendances tierces Angular
28
+ * - Clean install (Nx) ou ng update (standalone)
29
+ * - Mise à jour TypeScript
30
+ *
31
+ * Exemples : angular_18_environment, angular_19_environment, etc.
32
+ *
33
+ * @param rule Règle à vérifier
34
+ * @returns true si la règle est une migration d'environnement
35
+ */
36
+ function isEnvironmentMigrationRule(rule) {
37
+ return rule.routineType === 'environment-migration';
38
+ }
39
+ /**
40
+ * Identifie si une règle a une spécification AI complexe
41
+ *
42
+ * Ces règles nécessitent un workflow multi-phases personnalisé
43
+ * au lieu du workflow standard (schematic + delta agent)
44
+ *
45
+ * Exemples : standalone_default (migration standalone complète)
46
+ *
47
+ * @param rule Règle à vérifier
48
+ * @returns true si la règle a une ai_specification avec isComplex: true
49
+ */
50
+ function hasComplexAiSpecification(rule) {
51
+ return !!rule.ai_specification?.isComplex;
52
+ }