pull-request-split-advisor 3.2.0 → 3.2.1

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.
@@ -60,7 +60,7 @@ async function testApiKeyConnection(provider, model, apiKey, apiKeyEnvVar) {
60
60
  model,
61
61
  apiKey,
62
62
  apiKeyEnvVar,
63
- features: { commitMessages: false, branchDescriptions: false },
63
+ features: { commitMessages: false, branchDescriptions: false, planRebalance: false },
64
64
  timeoutMs: 10000,
65
65
  maxTokens: 16,
66
66
  },
@@ -227,7 +227,7 @@ export async function runConfigWizard() {
227
227
  * Valida la key contra el proveedor antes de guardar. Si falla, aborta con error.
228
228
  *
229
229
  * @param apiKey - La API key del proveedor (literal, no nombre de env var).
230
- * @param provider - ID del proveedor: "groq" | "github" | "copilot". Predeterminado: "groq".
230
+ * @param provider - ID del proveedor: "groq" | "copilot". Predeterminado: "groq".
231
231
  */
232
232
  export async function runConfigWithKey(apiKey, provider = "groq") {
233
233
  const configPath = resolve(process.cwd(), CONFIG_FILE);
package/dist/cli.js CHANGED
@@ -280,6 +280,7 @@ async function main() {
280
280
  config.jsonOutputFile,
281
281
  "pr-split-advisor.config.json",
282
282
  "pr-split-report.html",
283
+ "pr-split-score.html",
283
284
  config.historyFile
284
285
  ].filter(Boolean);
285
286
  if (config.verbose) {
@@ -439,6 +440,7 @@ async function main() {
439
440
  config.jsonOutputFile,
440
441
  "pr-split-advisor.config.json",
441
442
  "pr-split-report.html",
443
+ "pr-split-score.html",
442
444
  config.historyFile
443
445
  ].filter(Boolean);
444
446
  ui.spinner.start("Calculando score del estado actual...");
@@ -455,13 +457,14 @@ async function main() {
455
457
  const totalLines = fileStats.reduce((sum, f) => sum + f.lines, 0);
456
458
  const aheadCommits = localAheadCount(baseBranch);
457
459
  const commitCount = Math.max(aheadCommits, 1);
458
- const filesPerCommit = Math.round((totalFiles / commitCount) * 10) / 10;
460
+ const filesPerCommit = Number((totalFiles / commitCount).toFixed(2));
459
461
  const avgLinesPerCommit = Math.round(totalLines / commitCount);
460
462
  const result = scorePullRequest({ commitCount, filesPerCommit, avgLinesPerCommit, totalLinesChanged: totalLines }, config);
463
+ const warnThreshold = config.targetScore > 4 ? 4 : Math.max(0, config.targetScore - 1);
461
464
  const scoreColor = ui.scoreColor(result.complexity, config.targetScore);
462
465
  const statusBadge = result.complexity >= config.targetScore
463
466
  ? ui.badge("ÓPTIMO", "green")
464
- : result.complexity >= config.targetScore - 1
467
+ : result.complexity >= warnThreshold
465
468
  ? ui.badge("ACEPTABLE", "yellow")
466
469
  : ui.badge("RIESGO", "red");
467
470
  const scoreHtmlFile = "pr-split-score.html";
@@ -304,7 +304,7 @@ export function loadConfig(configPath = "pr-split-advisor.config.json") {
304
304
  }
305
305
  if (isObject(ai["features"])) {
306
306
  const f = ai["features"];
307
- for (const flag of ["commitMessages", "branchDescriptions"]) {
307
+ for (const flag of ["commitMessages", "branchDescriptions", "planRebalance"]) {
308
308
  if (flag in f && typeof f[flag] !== "boolean") {
309
309
  throw new Error(`Configuración inválida: "ai.features.${flag}" debe ser true o false (recibido: ${JSON.stringify(f[flag])}).`);
310
310
  }
@@ -188,9 +188,8 @@ export const defaultConfig = {
188
188
  //
189
189
  // Configurar vía `pr-split-advisor config` o editando directamente el JSON.
190
190
  //
191
- // Opciones de `provider` soportadas: "groq" | "github" | "copilot"
191
+ // Opciones de `provider` soportadas: "groq" | "copilot"
192
192
  // groq → requiere GROQ_API_KEY (console.groq.com, free tier)
193
- // github → requiere GITHUB_TOKEN (github.com/marketplace/models, free)
194
193
  // copilot → sin token — usa automáticamente credenciales de gh CLI
195
194
  //
196
195
  // API key: preferir `apiKeyEnvVar` (ej: GROQ_API_KEY) antes que literal `apiKey`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pull-request-split-advisor",
3
- "version": "3.2.0",
3
+ "version": "3.2.1",
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",
@@ -83,30 +83,56 @@ async function main() {
83
83
  );
84
84
  }
85
85
 
86
- // ── Añadir la entrada al .gitignore del proyecto consumidor ─────────────
86
+ // ── Añadir entradas al .gitignore del proyecto consumidor ──────────────
87
87
  // La config es local por equipo/desarrollador y no debe versionarse.
88
- const gitignorePath = join(targetDir, ".gitignore");
89
- const gitignoreEntry = "pr-split-advisor.config.json";
88
+ // Los artefactos generados (reportes HTML, plan JSON, historial) tampoco.
89
+ const gitignorePath = join(targetDir, ".gitignore");
90
+
91
+ const gitignoreEntries = [
92
+ {
93
+ entry: "pr-split-advisor.config.json",
94
+ comment: "# pr-split-advisor — config local (no compartir en el repositorio)"
95
+ },
96
+ { entry: "pr-split-report.html", comment: null },
97
+ { entry: "pr-split-score.html", comment: null },
98
+ { entry: "pr-split-plan.json", comment: null },
99
+ { entry: ".pr-split-history.json", comment: null }
100
+ ];
101
+
102
+ // Cabecera del grupo de artefactos: solo se añade si al menos uno de ellos
103
+ // no está ya en el .gitignore, y solo una vez para todo el grupo.
104
+ const artifactEntries = ["pr-split-report.html", "pr-split-score.html", "pr-split-plan.json", ".pr-split-history.json"];
90
105
 
91
106
  try {
92
107
  const currentContent = existsSync(gitignorePath)
93
108
  ? readFileSync(gitignorePath, "utf-8")
94
109
  : "";
95
110
 
96
- const alreadyIgnored = currentContent
97
- .split("\n")
98
- .map((l) => l.trim())
99
- .includes(gitignoreEntry);
111
+ const existingLines = currentContent.split("\n").map((l) => l.trim());
112
+ let block = currentContent.length && !currentContent.endsWith("\n") ? "\n" : "";
113
+ let addedAny = false;
114
+ let artifactHeaderAdded = false;
115
+
116
+ for (const { entry, comment } of gitignoreEntries) {
117
+ if (existingLines.includes(entry)) continue;
100
118
 
101
- if (!alreadyIgnored) {
102
- const block =
103
- (currentContent.length && !currentContent.endsWith("\n") ? "\n" : "") +
104
- "\n# pr-split-advisor config local (no compartir en el repositorio)\n" +
105
- gitignoreEntry + "\n";
119
+ const isArtifact = artifactEntries.includes(entry);
120
+ if (isArtifact && !artifactHeaderAdded && !comment) {
121
+ // Escribir la cabecera de artefactos la primera vez que haya uno nuevo
122
+ block += "\n# pr-split-advisor \u2014 artefactos generados\n";
123
+ artifactHeaderAdded = true;
124
+ } else if (comment) {
125
+ block += "\n" + comment + "\n";
126
+ }
127
+
128
+ block += entry + "\n";
129
+ addedAny = true;
130
+ }
106
131
 
132
+ if (addedAny) {
107
133
  appendFileSync(gitignorePath, block, "utf-8");
108
134
  console.log(
109
- "[pr-split-advisor] ✔ Añadido pr-split-advisor.config.json al .gitignore"
135
+ "[pr-split-advisor] ✔ Añadidas entradas de pr-split-advisor al .gitignore"
110
136
  );
111
137
  }
112
138
  } catch (err) {