pull-request-split-advisor 3.2.2 → 3.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -92,16 +92,23 @@ function computeTestCoveragePercent(fileStats) {
92
92
  return Math.round((testFiles / fileStats.length) * 100);
93
93
  }
94
94
  function printSummary(fileStats, config, currentBranch, baseBranch) {
95
- const totalFiles = fileStats.length;
96
- const totalLines = fileStats.reduce((sum, f) => sum + f.lines, 0);
97
- const totalAdditions = fileStats.reduce((sum, f) => sum + f.additions, 0);
98
- const totalDeletions = fileStats.reduce((sum, f) => sum + f.deletions, 0);
99
- const createdFiles = fileStats.filter((f) => f.changeType === "A" || f.changeType === "U").length;
100
- const updatedFiles = fileStats.filter((f) => f.changeType === "M").length;
101
- const deletedFiles = fileStats.filter((f) => f.changeType === "D").length;
102
- const renamedFiles = fileStats.filter((f) => f.changeType === "R").length;
103
- const largeFiles = fileStats.filter((f) => f.lines > config.largeFileThreshold).length;
95
+ // Los stats del resumen se calculan solo sobre archivos WIP/sin-rastrear.
96
+ // Los archivos LOCAL y REMOTO aparecen en la tabla detalle pero no en estas métricas.
97
+ const wipStats = fileStats.filter((f) => !f.origin || f.origin === "working-tree" || f.origin === "untracked");
98
+ const statsBase = wipStats.length > 0 ? wipStats : fileStats;
99
+ const hasInfoFiles = statsBase.length < fileStats.length;
100
+ const infoFileCount = fileStats.length - statsBase.length;
101
+ const totalFiles = statsBase.length;
102
+ const totalLines = statsBase.reduce((sum, f) => sum + f.lines, 0);
103
+ const totalAdditions = statsBase.reduce((sum, f) => sum + f.additions, 0);
104
+ const totalDeletions = statsBase.reduce((sum, f) => sum + f.deletions, 0);
105
+ const createdFiles = statsBase.filter((f) => f.changeType === "A" || f.changeType === "U").length;
106
+ const updatedFiles = statsBase.filter((f) => f.changeType === "M").length;
107
+ const deletedFiles = statsBase.filter((f) => f.changeType === "D").length;
108
+ const renamedFiles = statsBase.filter((f) => f.changeType === "R").length;
109
+ const largeFiles = statsBase.filter((f) => f.lines > config.largeFileThreshold).length;
104
110
  const testCoveragePercent = config.testCoveragePercent;
111
+ ;
105
112
  ui.header(APP_NAME.toUpperCase(), "Asesor de División de PRs", [
106
113
  ["Rama actual", currentBranch],
107
114
  ["Rama base del PR", baseBranch],
@@ -112,8 +119,13 @@ function printSummary(fileStats, config, currentBranch, baseBranch) {
112
119
  ["Número de historia", config.branchNamingContext?.storyNumber ?? "N/A"]
113
120
  ]);
114
121
  ui.section("RESUMEN DE CAMBIOS", "#");
122
+ if (hasInfoFiles) {
123
+ ui.info(`${infoFileCount} archivo${infoFileCount !== 1 ? "s" : ""} con origen LOCAL o REMOTO ` +
124
+ "se muestran en la tabla de archivos de forma informativa. " +
125
+ "Sus métricas no se incluyen en este resumen.");
126
+ }
115
127
  ui.dashboard([
116
- ["Total de archivos", totalFiles, "blue"],
128
+ ["Total de archivos WIP", totalFiles, "blue"],
117
129
  ["Lineas agregadas", totalAdditions, "green"],
118
130
  ["Lineas borradas", totalDeletions, "red"],
119
131
  ["Archivos creados", createdFiles, createdFiles > 0 ? "green" : "cyan"],
@@ -392,7 +404,8 @@ async function main() {
392
404
  printBlocks(blocks);
393
405
  printPlans(plans, baseBranch, currentBranch, config);
394
406
  // ─── Exportar reporte HTML ───────────────────────────────────────────────
395
- const reportInput = { currentBranch, baseBranch, config, fileStats, deps, blocks, plans };
407
+ const wipFileStats = fileStats.filter((f) => !f.origin || f.origin === "working-tree" || f.origin === "untracked");
408
+ const reportInput = { currentBranch, baseBranch, config, fileStats, wipFileStats, deps, blocks, plans };
396
409
  const htmlFile = "pr-split-report.html";
397
410
  writeHtmlReport(htmlFile, reportInput);
398
411
  ui.ok(`Reporte HTML generado: ${htmlFile}`);
@@ -415,15 +415,20 @@ function buildReportStyles() {
415
415
  */
416
416
  export function renderHtmlReport(input) {
417
417
  const { currentBranch, baseBranch, config, fileStats, deps, blocks, plans } = input;
418
- const totalFiles = fileStats.length;
419
- const totalLines = fileStats.reduce((sum, f) => sum + f.lines, 0);
420
- const totalAdditions = fileStats.reduce((sum, f) => sum + f.additions, 0);
421
- const totalDeletions = fileStats.reduce((sum, f) => sum + f.deletions, 0);
422
- const createdFiles = fileStats.filter((f) => f.changeType === "A" || f.changeType === "U").length;
423
- const updatedFiles = fileStats.filter((f) => f.changeType === "M").length;
424
- const deletedFiles = fileStats.filter((f) => f.changeType === "D").length;
425
- const renamedFiles = fileStats.filter((f) => f.changeType === "R").length;
426
- const largeFiles = fileStats.filter((f) => f.lines > config.largeFileThreshold).length;
418
+ // Los stats del hero y del resumen se calculan solo sobre archivos WIP/sin-rastrear.
419
+ // fileStats completo (WIP + LOCAL + REMOTO) se usa únicamente para la tabla de detalle.
420
+ const wipStats = input.wipFileStats ?? fileStats;
421
+ const hasInfoFiles = input.wipFileStats != null && input.wipFileStats.length < fileStats.length;
422
+ const infoFileCount = fileStats.length - wipStats.length;
423
+ const totalFiles = wipStats.length;
424
+ const totalLines = wipStats.reduce((sum, f) => sum + f.lines, 0);
425
+ const totalAdditions = wipStats.reduce((sum, f) => sum + f.additions, 0);
426
+ const totalDeletions = wipStats.reduce((sum, f) => sum + f.deletions, 0);
427
+ const createdFiles = wipStats.filter((f) => f.changeType === "A" || f.changeType === "U").length;
428
+ const updatedFiles = wipStats.filter((f) => f.changeType === "M").length;
429
+ const deletedFiles = wipStats.filter((f) => f.changeType === "D").length;
430
+ const renamedFiles = wipStats.filter((f) => f.changeType === "R").length;
431
+ const largeFiles = wipStats.filter((f) => f.lines > config.largeFileThreshold).length;
427
432
  const avgScore = plans.length > 0
428
433
  ? plans.reduce((sum, p) => sum + p.score, 0) / plans.length
429
434
  : 0;
@@ -487,8 +492,9 @@ export function renderHtmlReport(input) {
487
492
  <div class="value" style="color:#f87171">${riskPlans}</div>
488
493
  </div>
489
494
  <div class="hero-item">
490
- <div class="label">Archivos modificados</div>
491
- <div class="value">${totalFiles}</div>
495
+ <div class="label">Archivos WIP${hasInfoFiles ? ` / total` : ""}</div>
496
+ <div class="value">${totalFiles}${hasInfoFiles ? ` <span style="font-size:.8em;opacity:.7">/ ${fileStats.length}</span>` : ""}</div>
497
+ ${hasInfoFiles ? `<div class="sub" style="font-size:.75em;opacity:.65">${infoFileCount} commit${infoFileCount !== 1 ? "s" : ""} local/remoto</div>` : ""}
492
498
  </div>
493
499
  </div>
494
500
  </header>
@@ -586,6 +592,17 @@ export function renderHtmlReport(input) {
586
592
  <!-- ══ DETALLE DE ARCHIVOS ════════════════════════════════════════ -->
587
593
  <section class="section">
588
594
  <h2 class="section-heading">📄 Detalle de archivos</h2>
595
+ ${hasInfoFiles ? `<div class="disclaimer-banner" style="margin-bottom:16px;padding:12px 18px" role="note">
596
+ <div class="disclaimer-icon" style="font-size:1.1em">ℹ️</div>
597
+ <div class="disclaimer-body" style="margin:0">
598
+ <strong>Archivos informativos</strong>
599
+ — ${infoFileCount} archivo${infoFileCount !== 1 ? "s" : ""} con badge
600
+ <span class="origin-badge origin-pushed">REMOTO</span> o
601
+ <span class="origin-badge origin-local-commit">LOCAL</span>
602
+ se muestran a modo de referencia.
603
+ Sus métricas <strong>no</strong> se incluyen en el resumen de cambios ni en el score.
604
+ </div>
605
+ </div>` : ""}
589
606
  <table>
590
607
  <thead>
591
608
  <tr>
@@ -694,7 +711,7 @@ export function renderHtmlReport(input) {
694
711
  <!-- ══ FOOTER ════════════════════════════════════════════════════ -->
695
712
  <footer class="footer">
696
713
  <p>Generado por <strong>${APP_REPORT_TITLE}</strong> · ${timestamp}</p>
697
- <p>Score objetivo: <strong>${config.targetScore}</strong> · Ramas analizadas: <strong>${plans.length}</strong> · Archivos: <strong>${totalFiles}</strong></p>
714
+ <p>Score objetivo: <strong>${config.targetScore}</strong> · Ramas analizadas: <strong>${plans.length}</strong> · Archivos WIP: <strong>${totalFiles}</strong>${hasInfoFiles ? ` (+ ${infoFileCount} informativo${infoFileCount !== 1 ? "s" : ""})` : ""}</p>
698
715
  </footer>
699
716
 
700
717
  </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pull-request-split-advisor",
3
- "version": "3.2.2",
3
+ "version": "3.2.3",
4
4
  "description": "CLI that analyses your Git working tree and suggests how to split changes into smaller, reviewable pull requests and commits.",
5
5
  "keywords": [
6
6
  "git",