agentic-api 2.0.31 → 2.0.491

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 (102) hide show
  1. package/dist/src/agents/agents.example.js +21 -22
  2. package/dist/src/agents/authentication.js +1 -2
  3. package/dist/src/agents/prompts.d.ts +5 -4
  4. package/dist/src/agents/prompts.js +44 -87
  5. package/dist/src/agents/reducer.core.d.ts +24 -2
  6. package/dist/src/agents/reducer.core.js +125 -35
  7. package/dist/src/agents/reducer.loaders.d.ts +55 -1
  8. package/dist/src/agents/reducer.loaders.js +114 -1
  9. package/dist/src/agents/reducer.types.d.ts +45 -2
  10. package/dist/src/agents/semantic.js +1 -2
  11. package/dist/src/agents/simulator.d.ts +11 -3
  12. package/dist/src/agents/simulator.executor.d.ts +14 -4
  13. package/dist/src/agents/simulator.executor.js +81 -23
  14. package/dist/src/agents/simulator.js +128 -42
  15. package/dist/src/agents/simulator.prompts.d.ts +9 -7
  16. package/dist/src/agents/simulator.prompts.js +66 -86
  17. package/dist/src/agents/simulator.types.d.ts +23 -5
  18. package/dist/src/agents/simulator.utils.d.ts +7 -2
  19. package/dist/src/agents/simulator.utils.js +31 -11
  20. package/dist/src/agents/system.js +1 -2
  21. package/dist/src/execute/helpers.d.ts +75 -0
  22. package/dist/src/execute/helpers.js +139 -0
  23. package/dist/src/execute/index.d.ts +11 -0
  24. package/dist/src/execute/index.js +44 -0
  25. package/dist/src/execute/legacy.d.ts +46 -0
  26. package/dist/src/execute/legacy.js +460 -0
  27. package/dist/src/execute/modelconfig.d.ts +19 -0
  28. package/dist/src/execute/modelconfig.js +56 -0
  29. package/dist/src/execute/responses.d.ts +55 -0
  30. package/dist/src/execute/responses.js +594 -0
  31. package/dist/src/execute/shared.d.ts +83 -0
  32. package/dist/src/execute/shared.js +188 -0
  33. package/dist/src/index.d.ts +1 -1
  34. package/dist/src/index.js +2 -2
  35. package/dist/src/{princing.openai.d.ts → pricing.llm.d.ts} +6 -0
  36. package/dist/src/pricing.llm.js +255 -0
  37. package/dist/src/prompts.d.ts +13 -4
  38. package/dist/src/prompts.js +221 -114
  39. package/dist/src/rag/embeddings.d.ts +36 -18
  40. package/dist/src/rag/embeddings.js +131 -128
  41. package/dist/src/rag/index.d.ts +5 -5
  42. package/dist/src/rag/index.js +14 -17
  43. package/dist/src/rag/parser.d.ts +2 -1
  44. package/dist/src/rag/parser.js +11 -14
  45. package/dist/src/rag/rag.examples.d.ts +27 -0
  46. package/dist/src/rag/rag.examples.js +151 -0
  47. package/dist/src/rag/rag.manager.d.ts +383 -0
  48. package/dist/src/rag/rag.manager.js +1390 -0
  49. package/dist/src/rag/types.d.ts +128 -12
  50. package/dist/src/rag/types.js +100 -1
  51. package/dist/src/rag/usecase.d.ts +37 -0
  52. package/dist/src/rag/usecase.js +96 -7
  53. package/dist/src/rules/git/git.e2e.helper.js +22 -2
  54. package/dist/src/rules/git/git.health.d.ts +61 -2
  55. package/dist/src/rules/git/git.health.js +333 -11
  56. package/dist/src/rules/git/index.d.ts +2 -2
  57. package/dist/src/rules/git/index.js +13 -1
  58. package/dist/src/rules/git/repo.d.ts +160 -0
  59. package/dist/src/rules/git/repo.js +777 -0
  60. package/dist/src/rules/git/repo.pr.js +117 -13
  61. package/dist/src/rules/git/repo.tools.d.ts +22 -1
  62. package/dist/src/rules/git/repo.tools.js +50 -1
  63. package/dist/src/rules/types.d.ts +27 -14
  64. package/dist/src/rules/utils.matter.d.ts +0 -4
  65. package/dist/src/rules/utils.matter.js +35 -7
  66. package/dist/src/scrapper.d.ts +15 -22
  67. package/dist/src/scrapper.js +58 -110
  68. package/dist/src/stategraph/index.d.ts +1 -1
  69. package/dist/src/stategraph/stategraph.d.ts +56 -2
  70. package/dist/src/stategraph/stategraph.js +134 -6
  71. package/dist/src/stategraph/stategraph.storage.js +8 -0
  72. package/dist/src/stategraph/types.d.ts +27 -0
  73. package/dist/src/types.d.ts +46 -9
  74. package/dist/src/types.js +8 -7
  75. package/dist/src/usecase.d.ts +11 -2
  76. package/dist/src/usecase.js +27 -35
  77. package/dist/src/utils.d.ts +32 -18
  78. package/dist/src/utils.js +87 -129
  79. package/package.json +10 -3
  80. package/dist/src/agents/digestor.test.d.ts +0 -1
  81. package/dist/src/agents/digestor.test.js +0 -45
  82. package/dist/src/agents/reducer.example.d.ts +0 -28
  83. package/dist/src/agents/reducer.example.js +0 -118
  84. package/dist/src/agents/reducer.process.d.ts +0 -16
  85. package/dist/src/agents/reducer.process.js +0 -143
  86. package/dist/src/agents/reducer.tools.d.ts +0 -29
  87. package/dist/src/agents/reducer.tools.js +0 -157
  88. package/dist/src/agents/simpleExample.d.ts +0 -3
  89. package/dist/src/agents/simpleExample.js +0 -38
  90. package/dist/src/agents/system-review.d.ts +0 -5
  91. package/dist/src/agents/system-review.js +0 -181
  92. package/dist/src/agents/systemReview.d.ts +0 -4
  93. package/dist/src/agents/systemReview.js +0 -22
  94. package/dist/src/execute.d.ts +0 -49
  95. package/dist/src/execute.js +0 -564
  96. package/dist/src/princing.openai.js +0 -54
  97. package/dist/src/rag/tools.d.ts +0 -76
  98. package/dist/src/rag/tools.js +0 -196
  99. package/dist/src/rules/user.mapper.d.ts +0 -61
  100. package/dist/src/rules/user.mapper.js +0 -160
  101. package/dist/src/rules/utils/slug.d.ts +0 -22
  102. package/dist/src/rules/utils/slug.js +0 -35
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GitHealthManager = void 0;
4
4
  const git_1 = require("../git");
5
+ const utils_matter_1 = require("../utils.matter");
6
+ const repo_1 = require("./repo");
5
7
  /**
6
8
  * Git Repository Health Manager
7
9
  *
@@ -29,8 +31,7 @@ class GitHealthManager {
29
31
  await this.git.checkout(branch);
30
32
  }
31
33
  catch (checkoutError) {
32
- // Si checkout normal échoue, forcer le checkout
33
- console.log(`🔧 Checkout forcé vers ${branch}...`, checkoutError);
34
+ // Si checkout normal échoue, continuer (forceRepair gérera l'erreur)
34
35
  }
35
36
  try {
36
37
  // Use the robust health diagnostic function
@@ -140,12 +141,14 @@ class GitHealthManager {
140
141
  const draftHealth = await (0, git_1.gitGetBranchHealth)(this.git, draftBranch);
141
142
  results.push(draftHealth);
142
143
  this.displayHealthSummary(draftHealth);
143
- // Check all validation branches
144
+ // Check all validation branches with optimized function
144
145
  const allBranches = await (0, git_1.gitGetAllBranches)(this.git);
145
146
  const validationBranches = allBranches.filter(b => b.startsWith(validationPrefix));
146
147
  if (validationBranches.length > 0) {
148
+ console.log(`🔍 Diagnostic optimisé de ${validationBranches.length} branche(s) de validation...`);
147
149
  for (const branch of validationBranches) {
148
- const health = await (0, git_1.gitGetBranchHealth)(this.git, branch);
150
+ // OPTIMISATION: Utiliser la version légère pour les validations
151
+ const health = await (0, git_1.gitGetValidationBranchHealth)(this.git, branch, this.config);
149
152
  results.push(health);
150
153
  this.displayHealthSummary(health);
151
154
  }
@@ -173,7 +176,7 @@ class GitHealthManager {
173
176
  */
174
177
  displayHealthSummary(health) {
175
178
  if (health.healthy) {
176
- console.log(`✅ ${health.branch}`);
179
+ //console.log(`✅ ${health.branch}`);
177
180
  }
178
181
  else {
179
182
  console.log(`⚠️ ${health.branch}: ${health.issues.slice(0, 2).join(', ')}${health.issues.length > 2 ? '...' : ''}`);
@@ -292,20 +295,23 @@ class GitHealthManager {
292
295
  * - Notes orphelines sur anciens commits → copie vers HEAD + suppression
293
296
  * - Branches sans historique de notes → ignore silencieusement
294
297
  * - Erreurs de traitement par branche → continue avec les autres
298
+ *
299
+ * @returns GitPrNoteMigrationReport avec le nombre de notes migrées, déjà OK, et perdues
295
300
  */
296
301
  async migrateNotes() {
297
302
  const { mainBranch, validationPrefix, gitNotes } = this.config;
298
303
  if (!validationPrefix || !gitNotes.namespace) {
299
304
  console.error("Erreur: Le préfixe de validation ou le namespace des notes n'est pas configuré.");
300
- return;
305
+ return { migrated: 0, alreadyOk: 0, lost: [] };
301
306
  }
302
307
  const allBranches = await (0, git_1.gitGetAllBranches)(this.git);
303
308
  const validationBranches = allBranches.filter(b => b.startsWith(validationPrefix));
304
309
  if (validationBranches.length === 0) {
305
- return;
310
+ return { migrated: 0, alreadyOk: 0, lost: [] };
306
311
  }
307
312
  let migratedCount = 0;
308
313
  let alreadyOkCount = 0;
314
+ const lostNotes = [];
309
315
  for (const branch of validationBranches) {
310
316
  try {
311
317
  const lastCommit = (await this.git.revparse(branch)).trim();
@@ -323,12 +329,20 @@ class GitHealthManager {
323
329
  }
324
330
  const revListOutput = await this.git.raw('rev-list', `${mergeBase}..${branch}`);
325
331
  const branchCommits = revListOutput.split('\n').filter(Boolean);
332
+ // Extract PR number from branch name (e.g., rule-validation-31 -> 31)
333
+ const prNumber = parseInt(branch.split('-').pop() || '0', 10);
326
334
  let oldNoteCommit = null;
327
335
  for (const commitHash of branchCommits) {
328
336
  const note = await (0, git_1.gitReadNote)(this.git, commitHash, gitNotes.namespace, 1);
329
337
  if (note) {
330
- oldNoteCommit = commitHash;
331
- break; // Found the first note, stop searching
338
+ // CRITICAL FIX: Verify the note belongs to this PR before migrating
339
+ if (note.id === prNumber) {
340
+ oldNoteCommit = commitHash;
341
+ break; // Found the correct note for this PR
342
+ }
343
+ else {
344
+ console.log(` ⚠️ ${branch}: Note trouvée avec ID=${note.id}, attendu ID=${prNumber} - ignorée`);
345
+ }
332
346
  }
333
347
  }
334
348
  // 3. If a note was found on an old commit, migrate it
@@ -339,6 +353,11 @@ class GitHealthManager {
339
353
  console.log(`✅ ${branch}: Migration terminée`);
340
354
  migratedCount++;
341
355
  }
356
+ else {
357
+ // CRITICAL: Note perdue pour cette validation
358
+ console.error(`🚨 ${branch}: NOTE PERDUE - PR ${prNumber} n'a plus de note dans son historique`);
359
+ lostNotes.push({ branch, prNumber });
360
+ }
342
361
  }
343
362
  catch (error) {
344
363
  console.error(`❌ ${branch}: Erreur lors de la migration:`, error);
@@ -346,9 +365,312 @@ class GitHealthManager {
346
365
  }
347
366
  }
348
367
  // Summary only if there was work to do
349
- if (migratedCount > 0 || alreadyOkCount !== validationBranches.length) {
350
- console.log(`✅ Migration des notes terminée: ${migratedCount} migrées, ${alreadyOkCount} déjà OK`);
368
+ if (migratedCount > 0 || alreadyOkCount !== validationBranches.length || lostNotes.length > 0) {
369
+ console.log(`✅ Migration des notes terminée: ${migratedCount} migrées, ${alreadyOkCount} déjà OK${lostNotes.length > 0 ? `, ${lostNotes.length} perdues 🚨` : ''}`);
370
+ }
371
+ return {
372
+ migrated: migratedCount,
373
+ alreadyOk: alreadyOkCount,
374
+ lost: lostNotes
375
+ };
376
+ }
377
+ /**
378
+ * Analyse les IDs des documents Markdown dans une branche
379
+ *
380
+ * @param branch Branche à analyser (par défaut: toutes les branches)
381
+ * @returns Rapport d'analyse avec les fichiers problématiques
382
+ */
383
+ async analyseSafeIDs(branch) {
384
+ const isValidInteger = (value) => {
385
+ return typeof value === 'number' && value > 0 && value % 1 === 0;
386
+ };
387
+ // Vérifier si la validation des IDs est activée
388
+ if (!this.config.withID) {
389
+ console.log('ℹ️ La validation des IDs est désactivée (withID: false)');
390
+ return {
391
+ scanned: 0,
392
+ valid: 0,
393
+ missingID: [],
394
+ missingTitle: [],
395
+ invalidID: [],
396
+ duplicateID: [],
397
+ errors: []
398
+ };
399
+ }
400
+ console.log(`🔍 Analyse des documents Markdown pour validation des IDs...`);
401
+ //
402
+ // First time we check if the ID registry exists, and force the strictID mode
403
+ this.config.strictID = !(0, repo_1.gitIDRegistryExists)(this.config) || this.config.strictID;
404
+ if (this.config.strictID) {
405
+ console.log(` Mode strict activé: documents sans ID seront rejetés`);
406
+ }
407
+ const report = {
408
+ scanned: 0,
409
+ valid: 0,
410
+ missingID: [],
411
+ missingTitle: [],
412
+ invalidID: [],
413
+ duplicateID: [],
414
+ errors: []
415
+ };
416
+ try {
417
+ // Déterminer les branches à scanner
418
+ const branchesToScan = branch
419
+ ? [branch]
420
+ : await (0, git_1.gitGetAllBranches)(this.git);
421
+ console.log(`📂 Branches à scanner: ${branchesToScan.length} (${branchesToScan.join(', ')})`);
422
+ for (const branchName of branchesToScan) {
423
+ try {
424
+ // Lister tous les fichiers .md dans la branche
425
+ const allFiles = await (0, git_1.gitListFilesInBranch)(this.git, branchName);
426
+ const mdFiles = allFiles.filter(f => f.endsWith('.md'));
427
+ // Variables pour suivre les problèmes dans cette branche
428
+ let branchHasIssues = false;
429
+ const branchIssues = [];
430
+ for (const file of mdFiles) {
431
+ report.scanned++;
432
+ try {
433
+ // ✅ OPTIMISATION: Lecture rapide du matter (id + title uniquement)
434
+ // Utilise le cache, évite de parser tout le fichier
435
+ const matter = await (0, git_1.gitFileStrictMatter)(this.git, file, branchName, this.config);
436
+ // Vérification de l'ID et du titre
437
+ let hasValidID = false;
438
+ let hasValidTitle = false;
439
+ const fileRef = `${branchName}:${file}`;
440
+ if (!isValidInteger(matter.id)) {
441
+ report.missingID.push(fileRef);
442
+ branchHasIssues = true;
443
+ branchIssues.push(` ⚠️ ${file}: ID manquant`);
444
+ }
445
+ else if (matter.id <= 999) {
446
+ report.invalidID.push(`${fileRef} (id=${matter.id})`);
447
+ branchHasIssues = true;
448
+ branchIssues.push(` ⚠️ ${file}: ID invalide (${matter.id} <= 999)`);
449
+ }
450
+ else {
451
+ hasValidID = true;
452
+ // Enregistrer l'ID existant dans le registry
453
+ // ✅ gitRegisterExistingID() appelle maintenant setMatterCache() automatiquement si matter est fourni
454
+ try {
455
+ (0, git_1.gitRegisterExistingID)(matter, branchName, file, this.config);
456
+ }
457
+ catch (error) {
458
+ if (error.code === 'id_already_used') {
459
+ // Compter les doublons mais ne pas les ajouter aux erreurs (seront réparés)
460
+ report.duplicateID.push(`${fileRef} (id=${matter.id})`);
461
+ hasValidID = false;
462
+ branchHasIssues = true;
463
+ branchIssues.push(` ⚠️ ${file}: ID ${matter.id} déjà utilisé`);
464
+ }
465
+ }
466
+ }
467
+ // Vérification du titre
468
+ if (!matter.title || matter.title.trim() === '') {
469
+ report.missingTitle.push(fileRef);
470
+ branchHasIssues = true;
471
+ branchIssues.push(` ⚠️ ${file}: Titre manquant`);
472
+ }
473
+ else {
474
+ hasValidTitle = true;
475
+ }
476
+ // Si le document est valide (ID + titre)
477
+ if (hasValidID && hasValidTitle) {
478
+ report.valid++;
479
+ }
480
+ // Mode strict sans auto-fix : rejeter
481
+ if (!hasValidID && this.config.strictID) {
482
+ report.errors.push(`${fileRef} - Document rejeté (strictID: true, ID invalide)`);
483
+ branchIssues.push(` ❌ ${file}: REJETÉ (mode strict)`);
484
+ }
485
+ }
486
+ catch (parseError) {
487
+ const fileRef = `${branchName}:${file}`;
488
+ report.errors.push(`${fileRef} - Erreur de parsing: ${parseError.message}`);
489
+ branchIssues.push(` ❌ ${file}: Erreur de parsing: ${parseError.message}`);
490
+ branchHasIssues = true;
491
+ }
492
+ }
493
+ // Afficher les problèmes de la branche seulement s'il y en a
494
+ if (branchHasIssues) {
495
+ console.log(`\n📂 Scan de la branche: ${branchName} (${mdFiles.length} fichiers)`);
496
+ branchIssues.forEach(issue => console.log(issue));
497
+ }
498
+ }
499
+ catch (branchError) {
500
+ report.errors.push(`${branchName} - Erreur lors du scan: ${branchError.message}`);
501
+ console.error(` ❌ Erreur lors du scan de ${branchName}:`, branchError.message);
502
+ }
503
+ }
504
+ // Résumé
505
+ console.log(`\n📊 Résumé de l'analyse:`);
506
+ console.log(` Documents scannés: ${report.scanned}`);
507
+ console.log(` ✅ Valides: ${report.valid}`);
508
+ if (report.missingID.length > 0)
509
+ console.log(` ⚠️ IDs manquants: ${report.missingID.length}`);
510
+ if (report.missingTitle.length > 0)
511
+ console.log(` ⚠️ Titres manquants: ${report.missingTitle.length}`);
512
+ if (report.invalidID.length > 0)
513
+ console.log(` ⚠️ IDs invalides: ${report.invalidID.length}`);
514
+ if (report.duplicateID.length > 0)
515
+ console.log(` ⚠️ IDs en doublon: ${report.duplicateID.length}`);
516
+ if (report.errors.length > 0)
517
+ console.log(` ❌ Erreurs: ${report.errors.length}`);
518
+ return report;
519
+ }
520
+ catch (error) {
521
+ console.error('❌ Erreur lors de l\'analyse des documents:', error);
522
+ throw error;
523
+ }
524
+ }
525
+ /**
526
+ * Répare les IDs problématiques identifiés dans un rapport d'analyse
527
+ *
528
+ * @param report Rapport d'analyse généré par analyseSafeIDs
529
+ * @param options Options de réparation
530
+ * @param options.dryRun Mode simulation (affiche les réparations sans modifier)
531
+ * @returns Rapport mis à jour avec les fichiers réparés
532
+ */
533
+ async repairSafeIDs(report, options = {}) {
534
+ const { dryRun = false } = options;
535
+ console.log(`\n🔧 ${dryRun ? 'SIMULATION' : 'RÉPARATION'} des IDs problématiques...`);
536
+ const updatedReport = {
537
+ scanned: report.scanned,
538
+ valid: report.valid,
539
+ missingID: [...report.missingID],
540
+ missingTitle: [...report.missingTitle],
541
+ invalidID: [...report.invalidID],
542
+ duplicateID: [...report.duplicateID],
543
+ errors: [...report.errors]
544
+ };
545
+ // Collecter tous les fichiers à réparer
546
+ const filesToFix = [
547
+ ...report.missingID,
548
+ ...report.missingTitle,
549
+ ...report.invalidID.map(e => e.split(' (id=')[0]),
550
+ ...report.duplicateID.map(e => e.split(' (id=')[0])
551
+ ];
552
+ let fixed = 0;
553
+ const fixedFiles = new Set();
554
+ for (const fileRef of filesToFix) {
555
+ // Éviter de réparer deux fois le même fichier
556
+ if (fixedFiles.has(fileRef)) {
557
+ continue;
558
+ }
559
+ const [branchName, ...fileParts] = fileRef.split(':');
560
+ const file = fileParts.join(':');
561
+ try {
562
+ if (!dryRun) {
563
+ // Lire le contenu complet pour réparer
564
+ const fileData = await (0, git_1.gitGetFileContent)(this.git, file, branchName);
565
+ if (!fileData || !fileData.content) {
566
+ updatedReport.errors.push(`${fileRef} - Fichier inaccessible pour réparation`);
567
+ console.log(` ❌ ${file}: Fichier inaccessible`);
568
+ continue;
569
+ }
570
+ // Parser le matter complet
571
+ const parsed = (0, utils_matter_1.matterParse)(fileData.content);
572
+ const { matter: fullMatter, content } = parsed;
573
+ // Générer un nouvel ID si manquant
574
+ if (!fullMatter.id || typeof fullMatter.id !== 'number' || fullMatter.id <= 999) {
575
+ fullMatter.id = (0, git_1.gitGenerateNextID)(this.config);
576
+ console.log(` 🔧 ${file}: Génération d'un nouvel ID: ${fullMatter.id}`);
577
+ }
578
+ // Générer un titre si manquant (basé sur le nom du fichier ou le premier titre de section)
579
+ if (!fullMatter.title || fullMatter.title.trim() === '') {
580
+ // Essayer d'extraire le premier titre de section (# Title)
581
+ const titleMatch = content.match(/^#\s+(.+)$/m);
582
+ if (titleMatch) {
583
+ fullMatter.title = titleMatch[1].trim();
584
+ }
585
+ else {
586
+ // Sinon, utiliser le nom du fichier sans extension
587
+ const fileName = file.replace(/\.md$/, '').replace(/[-_]/g, ' ');
588
+ fullMatter.title = fileName.split(' ').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
589
+ }
590
+ console.log(` 🔧 ${file}: Génération d'un titre: ${fullMatter.title}`);
591
+ }
592
+ // Re-sérialiser et sauvegarder
593
+ const updatedContent = (0, utils_matter_1.matterSerialize)(content, fullMatter);
594
+ // ✅ IMPORTANT: Désactiver withID car l'ID est déjà généré et enregistré
595
+ // Évite la double validation qui cause "ID déjà utilisé"
596
+ await (0, repo_1.gitCreateOrEditFile)(this.git, file, branchName, updatedContent, { name: 'GitHealthManager', email: 'health@system' }, { ...this.config, canForce: true, withID: false });
597
+ fixed++;
598
+ fixedFiles.add(fileRef);
599
+ console.log(` ✅ ${file}: Réparé avec ID ${fullMatter.id}`);
600
+ // Retirer des listes de problèmes
601
+ updatedReport.missingID = updatedReport.missingID.filter(f => f !== fileRef);
602
+ updatedReport.missingTitle = updatedReport.missingTitle.filter(f => f !== fileRef);
603
+ updatedReport.invalidID = updatedReport.invalidID.filter(f => !f.startsWith(fileRef));
604
+ updatedReport.duplicateID = updatedReport.duplicateID.filter(f => !f.startsWith(fileRef));
605
+ updatedReport.valid++;
606
+ }
607
+ else {
608
+ // Mode simulation
609
+ console.log(` 🔍 ${file}: Nécessite réparation (simulation)`);
610
+ fixed++;
611
+ }
612
+ }
613
+ catch (fixError) {
614
+ updatedReport.errors.push(`${fileRef} - Erreur de réparation: ${fixError.message}`);
615
+ console.log(` ❌ ${file}: Erreur de réparation: ${fixError.message}`);
616
+ }
617
+ }
618
+ // Résumé
619
+ console.log(`\n📊 Résumé de la réparation:`);
620
+ console.log(` ${dryRun ? 'Fichiers à réparer' : 'Fichiers réparés'}: ${fixed}`);
621
+ if (!dryRun) {
622
+ console.log(` ✅ Valides après réparation: ${updatedReport.valid}`);
623
+ if (updatedReport.missingID.length > 0)
624
+ console.log(` ⚠️ IDs manquants restants: ${updatedReport.missingID.length}`);
625
+ if (updatedReport.missingTitle.length > 0)
626
+ console.log(` ⚠️ Titres manquants restants: ${updatedReport.missingTitle.length}`);
627
+ if (updatedReport.invalidID.length > 0)
628
+ console.log(` ⚠️ IDs invalides restants: ${updatedReport.invalidID.length}`);
629
+ if (updatedReport.duplicateID.length > 0)
630
+ console.log(` ⚠️ IDs en doublon restants: ${updatedReport.duplicateID.length}`);
631
+ }
632
+ else {
633
+ console.log(`\nℹ️ Mode simulation: Utilisez { dryRun: false } pour réparer effectivement`);
634
+ }
635
+ return updatedReport;
636
+ }
637
+ /**
638
+ * Vérifie et répare les IDs manquants dans tous les documents Markdown du repository
639
+ *
640
+ * Cette méthode orchestre l'analyse et la réparation :
641
+ * 1. Analyse les documents avec analyseSafeIDs()
642
+ * 2. Si autoFix est activé, répare avec repairSafeIDs()
643
+ *
644
+ * @param options Options de scan et réparation
645
+ * @param options.branch Branche spécifique à scanner (par défaut: toutes les branches)
646
+ * @param options.autoFix Active la réparation automatique (par défaut: false)
647
+ * @param options.dryRun Mode simulation (affiche les problèmes sans modifier)
648
+ * @returns Résumé des documents scannés et réparés
649
+ */
650
+ async ensureSafeIDS(options = {}) {
651
+ const { branch, autoFix = false, dryRun = false } = options;
652
+ // Étape 1: Analyser
653
+ const report = await this.analyseSafeIDs(branch);
654
+ let finalReport = report;
655
+ // Étape 2: Réparer si demandé
656
+ if (autoFix && (report.missingID.length > 0 || report.missingTitle.length > 0 || report.invalidID.length > 0 || report.duplicateID.length > 0)) {
657
+ finalReport = await this.repairSafeIDs(report, { dryRun });
351
658
  }
659
+ // Calculer le nombre de fichiers réparés
660
+ // C'est la différence entre les problèmes avant et après réparation
661
+ const fixed = (report.missingID.length + report.missingTitle.length + report.invalidID.length + report.duplicateID.length) -
662
+ (finalReport.missingID.length + finalReport.missingTitle.length + finalReport.invalidID.length + finalReport.duplicateID.length);
663
+ // Retourner dans l'ancien format pour compatibilité
664
+ return {
665
+ scanned: finalReport.scanned,
666
+ valid: finalReport.valid,
667
+ missingID: finalReport.missingID.length,
668
+ missingTitle: finalReport.missingTitle.length,
669
+ invalidID: finalReport.invalidID.length,
670
+ duplicateID: finalReport.duplicateID.length,
671
+ fixed: Math.max(0, fixed), // S'assurer que fixed n'est pas négatif
672
+ errors: finalReport.errors
673
+ };
352
674
  }
353
675
  }
354
676
  exports.GitHealthManager = GitHealthManager;
@@ -1,5 +1,5 @@
1
- export { lock, unlock, gitLoad, gitIsFileMerged, gitLastCommit, gitListFilesInBranch, gitListFilesOutsideRepo, gitFileExistsInBranch, gitGetFilesSummary, gitGetFileContent, gitGetFilePreview, gitGetFileHistory, gitReadFileOutsideRepo, gitGetUnmergedBranchesForFile, gitGetAllBranches, gitGetDiffFiles, gitReadNote, gitWriteNote, gitDeleteNote, } from './repo.tools';
2
- export { gitInit, gitEnsureRepositoryConfiguration, gitEnsureRemoteConfiguration, gitSetupRepository, gitShowConfiguration, gitCheckConfiguration, gitGetBranchHealth, gitCreateOrEditFile, gitEditFile, gitRenameFile, gitDeleteFile, } from './repo';
1
+ export { lock, unlock, gitLoad, isValidInt, gitIsFileMerged, gitLastCommit, gitListFilesInBranch, gitListFilesOutsideRepo, gitFileExistsInBranch, gitGetFilesSummary, gitGetFileContent, gitGetFilePreview, gitGetFileHistory, gitReadFileOutsideRepo, gitGetUnmergedBranchesForFile, gitGetAllBranches, gitGetDiffFiles, gitReadNote, gitWriteNote, gitDeleteNote, } from './repo.tools';
2
+ export { gitInit, gitEnsureRepositoryConfiguration, gitEnsureRemoteConfiguration, gitSetupRepository, gitShowConfiguration, gitCheckConfiguration, gitGetBranchHealth, gitGetValidationBranchHealth, gitCreateOrEditFile, gitEditFile, gitRenameFile, gitDeleteFile, gitGenerateNextID, gitReloadIDRegistry, gitRegisterExistingID, gitEnsureMatterID, gitFileStrictMatter, gitIDRegistryExists, gitIDRegistryRename, } from './repo';
3
3
  export { gitSyncPR, gitIsPRClosed, gitIsPRClosedRobust, gitGetPRMetadata, gitGetAllPR, gitGetClosedPRs, gitLoadPR, gitPRUpdateComments, gitClosePR, gitClosePRRobust, gitGetNextPRNumber, gitNewValidationRequest, gitNewPR, } from './repo.pr';
4
4
  export * from './git.e2e.helper';
5
5
  export * from './git.health';
@@ -14,7 +14,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.gitNewPR = exports.gitNewValidationRequest = exports.gitGetNextPRNumber = exports.gitClosePRRobust = exports.gitClosePR = exports.gitPRUpdateComments = exports.gitLoadPR = exports.gitGetClosedPRs = exports.gitGetAllPR = exports.gitGetPRMetadata = exports.gitIsPRClosedRobust = exports.gitIsPRClosed = exports.gitSyncPR = exports.gitDeleteFile = exports.gitRenameFile = exports.gitEditFile = exports.gitCreateOrEditFile = exports.gitGetBranchHealth = exports.gitCheckConfiguration = exports.gitShowConfiguration = exports.gitSetupRepository = exports.gitEnsureRemoteConfiguration = exports.gitEnsureRepositoryConfiguration = exports.gitInit = exports.gitDeleteNote = exports.gitWriteNote = exports.gitReadNote = exports.gitGetDiffFiles = exports.gitGetAllBranches = exports.gitGetUnmergedBranchesForFile = exports.gitReadFileOutsideRepo = exports.gitGetFileHistory = exports.gitGetFilePreview = exports.gitGetFileContent = exports.gitGetFilesSummary = exports.gitFileExistsInBranch = exports.gitListFilesOutsideRepo = exports.gitListFilesInBranch = exports.gitLastCommit = exports.gitIsFileMerged = exports.gitLoad = exports.unlock = exports.lock = void 0;
17
+ exports.gitGetNextPRNumber = exports.gitClosePRRobust = exports.gitClosePR = exports.gitPRUpdateComments = exports.gitLoadPR = exports.gitGetClosedPRs = exports.gitGetAllPR = exports.gitGetPRMetadata = exports.gitIsPRClosedRobust = exports.gitIsPRClosed = exports.gitSyncPR = exports.gitIDRegistryRename = exports.gitIDRegistryExists = exports.gitFileStrictMatter = exports.gitEnsureMatterID = exports.gitRegisterExistingID = exports.gitReloadIDRegistry = exports.gitGenerateNextID = exports.gitDeleteFile = exports.gitRenameFile = exports.gitEditFile = exports.gitCreateOrEditFile = exports.gitGetValidationBranchHealth = exports.gitGetBranchHealth = exports.gitCheckConfiguration = exports.gitShowConfiguration = exports.gitSetupRepository = exports.gitEnsureRemoteConfiguration = exports.gitEnsureRepositoryConfiguration = exports.gitInit = exports.gitDeleteNote = exports.gitWriteNote = exports.gitReadNote = exports.gitGetDiffFiles = exports.gitGetAllBranches = exports.gitGetUnmergedBranchesForFile = exports.gitReadFileOutsideRepo = exports.gitGetFileHistory = exports.gitGetFilePreview = exports.gitGetFileContent = exports.gitGetFilesSummary = exports.gitFileExistsInBranch = exports.gitListFilesOutsideRepo = exports.gitListFilesInBranch = exports.gitLastCommit = exports.gitIsFileMerged = exports.isValidInt = exports.gitLoad = exports.unlock = exports.lock = void 0;
18
+ exports.gitNewPR = exports.gitNewValidationRequest = void 0;
18
19
  // === OPÉRATIONS GIT BAS NIVEAU ===
19
20
  // Fonctions atomiques pour manipuler Git directement
20
21
  var repo_tools_1 = require("./repo.tools");
@@ -23,6 +24,8 @@ Object.defineProperty(exports, "lock", { enumerable: true, get: function () { re
23
24
  Object.defineProperty(exports, "unlock", { enumerable: true, get: function () { return repo_tools_1.unlock; } });
24
25
  // Configuration
25
26
  Object.defineProperty(exports, "gitLoad", { enumerable: true, get: function () { return repo_tools_1.gitLoad; } });
27
+ // Validation
28
+ Object.defineProperty(exports, "isValidInt", { enumerable: true, get: function () { return repo_tools_1.isValidInt; } });
26
29
  // Lecture de fichiers
27
30
  Object.defineProperty(exports, "gitIsFileMerged", { enumerable: true, get: function () { return repo_tools_1.gitIsFileMerged; } });
28
31
  Object.defineProperty(exports, "gitLastCommit", { enumerable: true, get: function () { return repo_tools_1.gitLastCommit; } });
@@ -50,10 +53,19 @@ Object.defineProperty(exports, "gitSetupRepository", { enumerable: true, get: fu
50
53
  Object.defineProperty(exports, "gitShowConfiguration", { enumerable: true, get: function () { return repo_1.gitShowConfiguration; } });
51
54
  Object.defineProperty(exports, "gitCheckConfiguration", { enumerable: true, get: function () { return repo_1.gitCheckConfiguration; } });
52
55
  Object.defineProperty(exports, "gitGetBranchHealth", { enumerable: true, get: function () { return repo_1.gitGetBranchHealth; } });
56
+ Object.defineProperty(exports, "gitGetValidationBranchHealth", { enumerable: true, get: function () { return repo_1.gitGetValidationBranchHealth; } });
53
57
  Object.defineProperty(exports, "gitCreateOrEditFile", { enumerable: true, get: function () { return repo_1.gitCreateOrEditFile; } });
54
58
  Object.defineProperty(exports, "gitEditFile", { enumerable: true, get: function () { return repo_1.gitEditFile; } });
55
59
  Object.defineProperty(exports, "gitRenameFile", { enumerable: true, get: function () { return repo_1.gitRenameFile; } });
56
60
  Object.defineProperty(exports, "gitDeleteFile", { enumerable: true, get: function () { return repo_1.gitDeleteFile; } });
61
+ // ID Management & Matter Cache
62
+ Object.defineProperty(exports, "gitGenerateNextID", { enumerable: true, get: function () { return repo_1.gitGenerateNextID; } });
63
+ Object.defineProperty(exports, "gitReloadIDRegistry", { enumerable: true, get: function () { return repo_1.gitReloadIDRegistry; } });
64
+ Object.defineProperty(exports, "gitRegisterExistingID", { enumerable: true, get: function () { return repo_1.gitRegisterExistingID; } });
65
+ Object.defineProperty(exports, "gitEnsureMatterID", { enumerable: true, get: function () { return repo_1.gitEnsureMatterID; } });
66
+ Object.defineProperty(exports, "gitFileStrictMatter", { enumerable: true, get: function () { return repo_1.gitFileStrictMatter; } });
67
+ Object.defineProperty(exports, "gitIDRegistryExists", { enumerable: true, get: function () { return repo_1.gitIDRegistryExists; } });
68
+ Object.defineProperty(exports, "gitIDRegistryRename", { enumerable: true, get: function () { return repo_1.gitIDRegistryRename; } });
57
69
  // === GESTION DES PULL REQUESTS (repo.pr.ts) ===
58
70
  var repo_pr_1 = require("./repo.pr");
59
71
  // Synchronisation et statut
@@ -1,5 +1,141 @@
1
1
  import { SimpleGit } from 'simple-git';
2
2
  import { RulesGitConfig, GitCommitHistory, RuleUser, GitHealthStatus } from '../types';
3
+ /**
4
+ * Structure du cache matter pour un fichier
5
+ */
6
+ interface MatterStrict {
7
+ id?: number;
8
+ title?: string;
9
+ service?: string;
10
+ oldfile?: string;
11
+ }
12
+ /**
13
+ * Vérifie si le fichier de registre d'IDs existe dans le repository Git
14
+ *
15
+ * Cette fonction est utile pour détecter si le système d'ID natif a été initialisé
16
+ * dans le repository. Le fichier `with-ids.json` est créé automatiquement lors du
17
+ * premier appel à `gitGenerateNextID()` ou `gitEnsureMatterID()`.
18
+ *
19
+ * @param config Configuration Git optionnelle (utilise la config par défaut si non fournie)
20
+ * @returns `true` si le fichier `.git/with-ids.json` existe, `false` sinon
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const config = gitLoad({ repoPath: './my-repo' });
25
+ *
26
+ * if (gitIDRegistryExists(config)) {
27
+ * console.log('Le registre d\'IDs existe déjà');
28
+ * // On peut charger le registre existant
29
+ * gitReloadIDRegistry(config);
30
+ * } else {
31
+ * console.log('Première utilisation du système d\'IDs');
32
+ * // Le registre sera créé au premier gitGenerateNextID()
33
+ * }
34
+ * ```
35
+ */
36
+ export declare function gitIDRegistryExists(config?: RulesGitConfig): boolean;
37
+ /**
38
+ * Génère un nouvel ID unique en incrémentant de +20
39
+ * @param config Configuration Git optionnelle
40
+ * @returns Un nouvel ID unique
41
+ */
42
+ export declare function gitGenerateNextID(config?: RulesGitConfig): number;
43
+ /**
44
+ * Force le rechargement du registre d'IDs depuis le disque
45
+ *
46
+ * **Utilisé principalement pour les tests qui simulent un redémarrage du serveur.**
47
+ *
48
+ * En production, cette fonction n'est pas nécessaire car le singleton est
49
+ * réinitialisé à chaque redémarrage du process Node.js.
50
+ *
51
+ * @param config Configuration Git optionnelle
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * // Dans un test : simuler un redémarrage
56
+ * await gitCreateOrEditFile(...); // Modifie le registre
57
+ * gitReloadIDRegistry(); // Force le rechargement depuis le disque
58
+ * ```
59
+ */
60
+ export declare function gitReloadIDRegistry(config?: RulesGitConfig): void;
61
+ /**
62
+ * Enregistre un ID existant dans le registre
63
+ *
64
+ * @param matter Le matter contenant l'ID à enregistrer
65
+ * @param branch Branche du fichier (optionnel, pour vérification de propriété)
66
+ * @param file Nom du fichier (optionnel, pour vérification de propriété)
67
+ * @param config Configuration Git optionnelle
68
+ * @throws GitOperationError si l'ID est déjà utilisé par un autre fichier
69
+ *
70
+ * **Note:** Si `branch` et `file` sont fournis, la fonction vérifie si l'ID appartient
71
+ * déjà au même fichier. Si oui, aucune erreur n'est levée (cas de re-scan).
72
+ *
73
+ * **Note:** `setMatterCache()` est appelé automatiquement avant l'enregistrement
74
+ * pour garantir la cohérence du cache.
75
+ */
76
+ export declare function gitRegisterExistingID(matter: MatterStrict, branch?: string, file?: string, config?: RulesGitConfig): void;
77
+ /**
78
+ * Renomme un fichier dans le cache du registre d'IDs
79
+ *
80
+ * Cette fonction met à jour le cache lorsqu'un fichier est renommé:
81
+ * - Supprime l'entrée avec l'ancien nom
82
+ * - Crée une nouvelle entrée avec le nouveau nom
83
+ * - Préserve l'ID et les métadonnées
84
+ *
85
+ * @param oldFile Ancien nom du fichier
86
+ * @param newFile Nouveau nom du fichier
87
+ * @param branch Branche concernée
88
+ * @param config Configuration Git optionnelle
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * // Après un rename dans Git
93
+ * gitIDRegistryRename('procedure-old.md', 'procedure-new.md', 'rule-validation-1');
94
+ * ```
95
+ */
96
+ export declare function gitIDRegistryRename(oldFile: string, newFile: string, branch: string, config?: RulesGitConfig): void;
97
+ /**
98
+ * Valide et assure qu'un matter a un ID valide
99
+ *
100
+ * **Principe d'identité stable**: Un fichier conserve son ID à travers les branches.
101
+ * Cette fonction cherche d'abord si le fichier a déjà un ID dans le registre
102
+ * (peu importe la branche), et le réutilise pour garantir la cohérence.
103
+ *
104
+ * @param matter Le matter à valider/compléter
105
+ * @param config Configuration Git optionnelle
106
+ * @param branch Branche du fichier (optionnel, peut être undefined lors de createPullRequest)
107
+ * @param file Nom du fichier (requis pour chercher l'ID existant)
108
+ * @returns Le matter mis à jour avec un ID valide
109
+ */
110
+ export declare function gitEnsureMatterID(matter: MatterStrict, config?: RulesGitConfig, branch?: string, file?: string): any;
111
+ /**
112
+ * Lecture rapide et stricte du matter d'un fichier (id + title uniquement)
113
+ *
114
+ * **Optimisation : Utilise le cache du registre d'IDs pour éviter de lire le fichier.**
115
+ *
116
+ * Cette fonction :
117
+ * 1. Vérifie d'abord le cache dans `.git/with-ids.json`
118
+ * 2. Si absent ou invalidé, lit le fichier avec regex (pas de parsing complet)
119
+ * 3. Met à jour le cache automatiquement
120
+ *
121
+ * @param git Instance SimpleGit
122
+ * @param filePath Chemin du fichier
123
+ * @param branch Nom de la branche
124
+ * @param config Configuration Git optionnelle
125
+ * @returns { id, title } ou { id: undefined, title: undefined } si absent
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * const matter = await gitFileStrictMatter(git, 'doc.md', 'main');
130
+ * console.log(matter.id); // 1234
131
+ * console.log(matter.title); // "Mon Document"
132
+ * ```
133
+ */
134
+ export declare function gitFileStrictMatter(git: SimpleGit, filePath: string, branch: string, config?: RulesGitConfig): Promise<{
135
+ id?: number;
136
+ title?: string;
137
+ oldfile?: string;
138
+ }>;
3
139
  /**
4
140
  * Vérifie et configure un repository Git existant pour s'assurer qu'il a la configuration requise
5
141
  * @param git Instance SimpleGit
@@ -126,3 +262,27 @@ export declare function gitDeleteFile(git: SimpleGit, filePath: string, branch:
126
262
  * @returns Promise<GitHealthStatus> Diagnostic complet avec liste des problèmes et recommandations de réparation
127
263
  */
128
264
  export declare function gitGetBranchHealth(git: SimpleGit, branch?: string): Promise<GitHealthStatus>;
265
+ /**
266
+ * Version optimisée de gitGetBranchHealth pour les branches de validation
267
+ *
268
+ * Cette fonction utilise une approche en cascade pour diagnostiquer rapidement
269
+ * l'état d'une branche de validation sans effectuer de checkout coûteux.
270
+ *
271
+ * Tests effectués dans l'ordre (arrêt au premier échec) :
272
+ * 1. Branche existe ? (git rev-parse --verify)
273
+ * 2. Note Git présente sur HEAD ? (gitReadNote avec maxCommit=1)
274
+ * 3. Note correspond au bon PR ? (note.id === prNumber)
275
+ *
276
+ * Avantages :
277
+ * - ✅ Pas de checkout (gain 80-90% performance)
278
+ * - ✅ Lecture directe du HEAD sans changer de branche
279
+ * - ✅ Tests cascade (arrêt dès qu'un problème est détecté)
280
+ * - ✅ Optimisé pour branches temporaires (validations)
281
+ *
282
+ * @param git Instance SimpleGit
283
+ * @param branch Nom de la branche de validation à diagnostiquer
284
+ * @param config Configuration Git optionnelle
285
+ * @returns GitHealthStatus avec diagnostic optimisé
286
+ */
287
+ export declare function gitGetValidationBranchHealth(git: SimpleGit, branch: string, config?: RulesGitConfig): Promise<GitHealthStatus>;
288
+ export {};