chocolatito-code 1.6.8 → 1.6.9

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # 🦊 Chocolatito Code (v1.0.0)
1
+ # 🦊 Chocolatito Code
2
2
 
3
3
  > **Agente Autónomo de Programación para la Terminal**, desarrollado por **Chocolatito** con la arquitectura del **Motor Espectro**.
4
4
 
@@ -278,6 +278,16 @@ Antes de hacer un commit o desplegar cambios, corre `/audit` o `/review`:
278
278
  - **Limpieza de depuración:** localiza sentencias residuales como `console.log`, `debugger;` o `print()`.
279
279
  - **Sugerencia de Conventional Commits:** genera automáticamente la propuesta de commit semántico según los archivos modificados (ej. `feat(tools): ...`, `test: ...`).
280
280
 
281
+ Y se le puede decir dónde callarse. En una herramienta de terminal, `console.log` no es
282
+ un olvido: es la salida del programa. Las rutas que pongas en un `.chocolatitoauditignore`
283
+ —una por línea, `#` para comentar— dejan de salir en la sección de calidad, y el informe
284
+ dice cuántas calló, para que nadie se encuentre el fichero un año después sin saberlo.
285
+
286
+ **Lo que ese fichero NO puede callar: un secreto.** Una clave, un `.env` o una clave
287
+ privada se avisan siempre, esté la ruta ignorada o no. Una herramienta que se deja
288
+ configurar para callarse una credencial es peor que no tenerla, porque da la
289
+ tranquilidad sin el aviso.
290
+
281
291
  ---
282
292
 
283
293
  ## 📌 Widget de Tareas en Vivo y Selector /resume
@@ -19,6 +19,8 @@ export interface AuditReport {
19
19
  secrets: AuditFinding[];
20
20
  debugLogs: AuditFinding[];
21
21
  residualLogs: AuditFinding[];
22
+ /** Cuantas sentencias se callaron por `.chocolatitoauditignore`. Se dice siempre. */
23
+ debugSilenciados: number;
22
24
  sensitiveFiles: string[];
23
25
  suggestedCommit: string;
24
26
  rawDiff: string;
@@ -35,7 +37,32 @@ export declare const DEBUG_PATTERNS: Array<{
35
37
  export declare function esDocumentacion(archivo: string): boolean;
36
38
  /** Quita los trozos entre comillas invertidas: `asi` y ``asi``. */
37
39
  export declare function sinCitasEnLinea(texto: string): string;
38
- export declare function auditDiffText(rawDiff: string, changedFiles?: string[]): AuditReport;
40
+ /**
41
+ * SE PUEDE CALLAR EL RUIDO, NUNCA UN SECRETO
42
+ *
43
+ * En un programa de terminal, `console.log` NO es un resto de depuracion: es la
44
+ * interfaz. Este repositorio tiene ocho en `src/index.ts` que son justo eso -el
45
+ * enlace de `--servir`, el aviso de que solo escucha en esta maquina- y salian
46
+ * los ocho en cada auditoria. Ocho avisos que hay que ignorar a mano cada vez
47
+ * son ocho razones para dejar de leer la seccion entera.
48
+ *
49
+ * Adivinar cual es interfaz y cual es un olvido no se puede hacer desde fuera:
50
+ * es la misma llamada. Asi que lo dice el proyecto, en un `.chocolatitoauditignore`
51
+ * al lado del `.gitignore`, una ruta o un patron por linea, y `#` para comentar.
52
+ *
53
+ * Con un limite que no se negocia: **esto solo calla la seccion de calidad**. Un
54
+ * secreto, un archivo sensible o una clave privada se avisan siempre, este la
55
+ * ruta ignorada o no. Una herramienta que se puede configurar para callarse una
56
+ * credencial es peor que no tenerla, porque da la tranquilidad sin el aviso.
57
+ *
58
+ * Y lo que se calla se cuenta: el informe dice cuantos silencio, para que nadie
59
+ * descubra el fichero un año despues sin saber que estaba puesto.
60
+ */
61
+ export declare const ARCHIVO_DE_IGNORADOS = ".chocolatitoauditignore";
62
+ export declare function leerPatronesIgnorados(cwd: string): string[];
63
+ /** Un patron de `.chocolatitoauditignore` contra una ruta del diff. */
64
+ export declare function rutaIgnorada(archivo: string, patrones: string[]): boolean;
65
+ export declare function auditDiffText(rawDiff: string, changedFiles?: string[], patronesIgnorados?: string[]): AuditReport;
39
66
  export declare function auditGitDiff(cwd?: string, mockDiff?: string): Promise<AuditReport>;
40
67
  export declare function suggestConventionalCommit(files: string[], _insertions: number, _deletions: number): string;
41
68
  export declare function formatAuditReport(report: AuditReport): string;
@@ -1,3 +1,5 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
1
3
  import chalk from "chalk";
2
4
  import { ejecutarGit } from "./gitTools.js";
3
5
  export const SECRET_PATTERNS = [
@@ -16,7 +18,11 @@ export const SENSITIVE_FILE_PATTERN = /(?:^|[/\\])(\.env(?:\.[a-zA-Z0-9_-]+)?|id
16
18
  export const DEBUG_PATTERNS = [
17
19
  { name: "console.log", pattern: /\bconsole\.log\s*\(/ },
18
20
  { name: "console.debug", pattern: /\bconsole\.debug\s*\(/ },
19
- { name: "debugger", pattern: /\bdebugger\b/ },
21
+ // `debugger` como PALABRA sale tambien dentro de una frase: el propio aviso
22
+ // de esta herramienta dice "ni console.log ni debugger" y se denunciaba solo.
23
+ // Un `debugger` de verdad es una sentencia: lleva punto y coma, o esta sola en
24
+ // su linea. Eso es lo que se busca.
25
+ { name: "debugger", pattern: /(?:^|[;{}])\s*debugger\s*(?:;|$)/ },
20
26
  { name: "print()", pattern: /(?<![\w.])print\s*\(/ },
21
27
  { name: "var_dump", pattern: /\bvar_dump\s*\(/ },
22
28
  { name: "dd()", pattern: /(?<![\w.])dd\s*\(/ },
@@ -60,10 +66,79 @@ export function esDocumentacion(archivo) {
60
66
  export function sinCitasEnLinea(texto) {
61
67
  return texto.replace(/``[^`]*``/g, " ").replace(/`[^`]*`/g, " ");
62
68
  }
63
- export function auditDiffText(rawDiff, changedFiles = []) {
69
+ /**
70
+ * SE PUEDE CALLAR EL RUIDO, NUNCA UN SECRETO
71
+ *
72
+ * En un programa de terminal, `console.log` NO es un resto de depuracion: es la
73
+ * interfaz. Este repositorio tiene ocho en `src/index.ts` que son justo eso -el
74
+ * enlace de `--servir`, el aviso de que solo escucha en esta maquina- y salian
75
+ * los ocho en cada auditoria. Ocho avisos que hay que ignorar a mano cada vez
76
+ * son ocho razones para dejar de leer la seccion entera.
77
+ *
78
+ * Adivinar cual es interfaz y cual es un olvido no se puede hacer desde fuera:
79
+ * es la misma llamada. Asi que lo dice el proyecto, en un `.chocolatitoauditignore`
80
+ * al lado del `.gitignore`, una ruta o un patron por linea, y `#` para comentar.
81
+ *
82
+ * Con un limite que no se negocia: **esto solo calla la seccion de calidad**. Un
83
+ * secreto, un archivo sensible o una clave privada se avisan siempre, este la
84
+ * ruta ignorada o no. Una herramienta que se puede configurar para callarse una
85
+ * credencial es peor que no tenerla, porque da la tranquilidad sin el aviso.
86
+ *
87
+ * Y lo que se calla se cuenta: el informe dice cuantos silencio, para que nadie
88
+ * descubra el fichero un año despues sin saber que estaba puesto.
89
+ */
90
+ export const ARCHIVO_DE_IGNORADOS = ".chocolatitoauditignore";
91
+ export function leerPatronesIgnorados(cwd) {
92
+ try {
93
+ const crudo = fs.readFileSync(path.join(cwd, ARCHIVO_DE_IGNORADOS), "utf-8");
94
+ return crudo
95
+ .split(/\r?\n/)
96
+ .map((l) => l.trim())
97
+ .filter((l) => l.length > 0 && !l.startsWith("#"));
98
+ }
99
+ catch {
100
+ return [];
101
+ }
102
+ }
103
+ /** Un patron de `.chocolatitoauditignore` contra una ruta del diff. */
104
+ export function rutaIgnorada(archivo, patrones) {
105
+ if (!archivo || patrones.length === 0)
106
+ return false;
107
+ const ruta = archivo.replace(/\\/g, "/").replace(/^\.\//, "");
108
+ const base = ruta.split("/").pop() || ruta;
109
+ for (const crudo of patrones) {
110
+ const patron = crudo.replace(/\\/g, "/").replace(/^\.\//, "");
111
+ // Una carpeta: "src/ui/" tapa todo lo que hay dentro.
112
+ if (patron.endsWith("/")) {
113
+ if (ruta.startsWith(patron))
114
+ return true;
115
+ continue;
116
+ }
117
+ // "**" cruza barras, "*" no: src/*.ts no baja a src/ui/marco.ts, src/**/*.ts si.
118
+ const comoRegex = patron
119
+ .split("**")
120
+ .map((trozo) => trozo
121
+ .replace(/[.+^$(){}|[\]\\]/g, (m) => "\\" + m)
122
+ .replace(/\*/g, "[^/]*")
123
+ .replace(/\?/g, "[^/]"))
124
+ .join(".*");
125
+ const re = new RegExp(`^${comoRegex}$`);
126
+ if (re.test(ruta))
127
+ return true;
128
+ // Un patron sin barras ("*.min.js") mira tambien solo el nombre.
129
+ if (!patron.includes("/") && re.test(base))
130
+ return true;
131
+ // Una carpeta escrita sin barra final ("src/ui") tapa igual lo de dentro.
132
+ if (ruta.startsWith(`${patron}/`))
133
+ return true;
134
+ }
135
+ return false;
136
+ }
137
+ export function auditDiffText(rawDiff, changedFiles = [], patronesIgnorados = []) {
64
138
  const secrets = [];
65
139
  const debugLogs = [];
66
140
  const sensitiveFiles = [];
141
+ let debugSilenciados = 0;
67
142
  for (const f of changedFiles) {
68
143
  if (SENSITIVE_FILE_PATTERN.test(f) && !sensitiveFiles.includes(f)) {
69
144
  sensitiveFiles.push(f);
@@ -119,9 +194,16 @@ export function auditDiffText(rawDiff, changedFiles = []) {
119
194
  });
120
195
  }
121
196
  }
197
+ const silenciado = rutaIgnorada(currentFile || "", patronesIgnorados);
122
198
  for (const dp of DEBUG_PATTERNS) {
123
199
  if (enDocumentacion)
124
200
  break;
201
+ if (silenciado) {
202
+ // Se cuenta aunque no se liste: callar no es esconder.
203
+ if (dp.pattern.test(addedContent))
204
+ debugSilenciados++;
205
+ continue;
206
+ }
125
207
  if (dp.pattern.test(addedContent)) {
126
208
  debugLogs.push({
127
209
  type: "debug",
@@ -156,6 +238,7 @@ export function auditDiffText(rawDiff, changedFiles = []) {
156
238
  secrets,
157
239
  debugLogs,
158
240
  residualLogs: debugLogs,
241
+ debugSilenciados,
159
242
  sensitiveFiles,
160
243
  suggestedCommit,
161
244
  rawDiff,
@@ -174,6 +257,7 @@ export async function auditGitDiff(cwd = process.cwd(), mockDiff) {
174
257
  secrets: [],
175
258
  debugLogs: [],
176
259
  residualLogs: [],
260
+ debugSilenciados: 0,
177
261
  sensitiveFiles: [],
178
262
  suggestedCommit: "chore: update project",
179
263
  rawDiff: statusRes.error,
@@ -188,6 +272,7 @@ export async function auditGitDiff(cwd = process.cwd(), mockDiff) {
188
272
  secrets: [],
189
273
  debugLogs: [],
190
274
  residualLogs: [],
275
+ debugSilenciados: 0,
191
276
  sensitiveFiles: [],
192
277
  suggestedCommit: "chore: no pending changes",
193
278
  rawDiff: "",
@@ -205,7 +290,7 @@ export async function auditGitDiff(cwd = process.cwd(), mockDiff) {
205
290
  diffRes = await ejecutarGit(["diff"], cwd);
206
291
  }
207
292
  const rawDiff = diffRes.ok ? diffRes.stdout : "";
208
- return auditDiffText(rawDiff, changedFiles);
293
+ return auditDiffText(rawDiff, changedFiles, leerPatronesIgnorados(cwd));
209
294
  }
210
295
  export function suggestConventionalCommit(files, _insertions, _deletions) {
211
296
  if (files.length === 0)
@@ -268,8 +353,15 @@ export function formatAuditReport(report) {
268
353
  if (report.debugLogs.length > 5) {
269
354
  lines.push(chalk.gray(` ... y ${report.debugLogs.length - 5} más.`));
270
355
  }
356
+ if (report.debugSilenciados > 0) {
357
+ lines.push(chalk.gray(` (${report.debugSilenciados} más en rutas de ${ARCHIVO_DE_IGNORADOS}, sin listar.)`));
358
+ }
271
359
  lines.push("");
272
360
  }
361
+ else if (report.debugSilenciados > 0) {
362
+ lines.push(chalk.green(" ✔ Calidad: Sin rastros nuevos de console.log ni debugger") +
363
+ chalk.gray(` (${report.debugSilenciados} en rutas de ${ARCHIVO_DE_IGNORADOS}, sin listar).`));
364
+ }
273
365
  else {
274
366
  lines.push(chalk.green(" ✔ Calidad: Sin rastros de console.log ni debugger en líneas nuevas."));
275
367
  }
@@ -2,7 +2,7 @@
2
2
  "manifest_version": 3,
3
3
  "minimum_chrome_version": "102",
4
4
  "name": "Chocolatito Code",
5
- "version": "1.6.8",
5
+ "version": "1.6.9",
6
6
  "description": "Deja que Chocolatito Code trabaje dentro de tu Chrome, en segundo plano y con tus sesiones ya iniciadas.",
7
7
  "permissions": [
8
8
  "tabs",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chocolatito-code",
3
- "version": "1.6.8",
3
+ "version": "1.6.9",
4
4
  "description": "Agente autónomo de programación para la terminal, con control real del ordenador y del navegador. Desarrollado por Chocolatito.",
5
5
  "type": "module",
6
6
  "bin": {