@nac3/forge-cli 1.15.0 → 1.16.0

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.
@@ -0,0 +1,101 @@
1
+ /**
2
+ * El candado que faltaba: la interfaz de persistencia es ASINCRONICA desde la
3
+ * linea 1.
4
+ *
5
+ * POR QUE EXISTE (Pablo, 13-oct-2026, mirando ADIP-Kikan). El brain construyo
6
+ * Kikan bien en lo estructural: el primer commit dice "nucleo kawa/sazanami +
7
+ * persistencia MariaDB", hay capa de repositorio, y `mysqlStore` hace
8
+ * write-through a MariaDB con hidratacion al arranque -- el dato productivo es
9
+ * durable y siempre lo fue. La decision equivocada fue UNA, y es una FIRMA:
10
+ * la interfaz del repositorio quedo SINCRONICA. De ahi sale todo lo demas, por
11
+ * mecanica pura:
12
+ *
13
+ * 1. un driver SQL real es asincronico, y una interfaz sincronica no lo puede
14
+ * envolver;
15
+ * 2. entonces el store "de MariaDB" tuvo que quedarse el working set en RAM
16
+ * para servir lecturas sincronas -- su propia cabecera lo dice: "lecturas
17
+ * sincronas, interfaz IDENTICA a createMemoryStore -> no reescribe el
18
+ * motor";
19
+ * 3. y como un working set en memoria no necesita columnas, el esquema
20
+ * degenero en UNA tabla generica de JSON (`engine_rows`), con las 57
21
+ * tablas 3NF como read-model DERIVADO en vez de sistema de registro.
22
+ *
23
+ * Una firma de funcion, y de ahi 1.543 puntos de deuda y nueve slices de
24
+ * conversion.
25
+ *
26
+ * LA ASIMETRIA, que es la razon por la que esto no necesita ninguna ronda de
27
+ * dimensionamiento para decidirse:
28
+ *
29
+ * - `await` sobre un valor que no es Promise NO HACE NADA. Declarar el store
30
+ * asincronico desde la linea 1 cuesta CERO cuando el store es de memoria.
31
+ * - El camino inverso -- sincronico a asincronico -- es cada punto de
32
+ * llamada del sistema. En Kikan fueron 1.543.
33
+ *
34
+ * Dos opciones donde una es gratis y reversible y la otra es una reescritura no
35
+ * son dos opciones: una decision asimetrica se toma SIEMPRE del lado
36
+ * recuperable, incluso sin un solo dato de volumetria.
37
+ *
38
+ * POR QUE "DECLARADO async" Y NO "DEVUELVE UNA PROMISE": la segunda es mas
39
+ * precisa y requiere analisis de flujo. La primera es trivial de cumplir
40
+ * (`async` sobre algo que ya devuelve una promesa no cambia nada) y trivial de
41
+ * verificar. Una regla estricta y simple que cualquiera puede satisfacer vale
42
+ * mas que una regla astuta que hay que interpretar.
43
+ *
44
+ * EL MODO DE FALLAR QUE IMPORTA ES EL FALSO NEGATIVO: un store que el detector
45
+ * no reconoce es deuda que el candado no cuenta, y el numero daria verde sin
46
+ * que nadie haya hecho nada. Por eso un archivo que no se puede analizar va a
47
+ * `ilegibles` y el control FALLA, en vez de contar cero. Misma disciplina que
48
+ * el trinquete de Kikan.
49
+ *
50
+ * ASCII-only.
51
+ */
52
+ /** Los verbos que tocan una fila. Si un modulo expone varios de estos, es un
53
+ * store, se llame como se llame. */
54
+ export declare const VERBOS_DATOS: readonly ["insert", "bulkInsert", "insertMany", "update", "patch", "upsert", "save", "remove", "removeAll", "delete", "deleteAll", "destroy", "get", "getById", "find", "findOne", "findAll", "findMany", "all", "list", "query", "select", "count", "exists", "first"];
55
+ /** Cuantos verbos distintos tiene que exponer un modulo sin nombre delator
56
+ * para que lo tratemos como store. */
57
+ export declare const VERBOS_MINIMOS_POR_FORMA = 4;
58
+ export type Forma = 'metodo' | 'propiedad-funcion' | 'propiedad-flecha';
59
+ export interface Hallazgo {
60
+ archivo: string;
61
+ linea: number;
62
+ metodo: string;
63
+ forma: Forma;
64
+ }
65
+ export interface Exento {
66
+ archivo: string;
67
+ linea: number;
68
+ metodo: string;
69
+ motivo: string;
70
+ }
71
+ export interface Resultado {
72
+ /** Los modulos que el detector trata como store. */
73
+ modulos: string[];
74
+ /** Metodos de acceso a datos vistos en esos modulos. */
75
+ vistos: number;
76
+ /** De esos, los declarados async. */
77
+ asincronicos: number;
78
+ /** Los SINCRONICOS: cada uno es una ocasion de repetir el defecto de Kikan. */
79
+ hallazgos: Hallazgo[];
80
+ /** Eximidos a mano, con su motivo. */
81
+ exentos: Exento[];
82
+ /** No se pudieron analizar. El control FALLA con esto no vacio. */
83
+ ilegibles: string[];
84
+ }
85
+ export declare function enmascarar(texto: string): string;
86
+ /** Las llaves balancean. Si no, el archivo no se puede analizar con confianza. */
87
+ export declare function balancea(mascara: string): boolean;
88
+ /** Es este archivo un store? */
89
+ export declare function esStore(ruta: string, mascara: string): boolean;
90
+ /**
91
+ * Analiza un archivo. `fuentes` es [ruta, texto].
92
+ *
93
+ * Devuelve null cuando el archivo NO es un store (nada que decir), y un
94
+ * resultado parcial cuando si lo es.
95
+ */
96
+ export declare function analizarArchivo(ruta: string, texto: string): Resultado | null;
97
+ /** Junta el analisis de muchos archivos. */
98
+ export declare function analizar(fuentes: Array<[string, string]>): Resultado;
99
+ /** Pasa el control? Un ilegible lo hace fallar: no se afirma lo que no se midio. */
100
+ export declare function aprueba(r: Resultado): boolean;
101
+ //# sourceMappingURL=persistence_async.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence_async.d.ts","sourceRoot":"","sources":["../../src/audit/persistence_async.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAEH;qCACqC;AACrC,eAAO,MAAM,YAAY,yQAMf,CAAC;AAIX;uCACuC;AACvC,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAuB1C,MAAM,MAAM,KAAK,GAAG,QAAQ,GAAG,mBAAmB,GAAG,kBAAkB,CAAC;AAExE,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;CACd;AAED,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,oDAAoD;IACpD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,sCAAsC;IACtC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,mEAAmE;IACnE,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAgHD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAqDhD;AAED,kFAAkF;AAClF,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAOjD;AAyDD,gCAAgC;AAChC,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAK9D;AAQD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAqC7E;AAED,4CAA4C;AAC5C,wBAAgB,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAepE;AAED,oFAAoF;AACpF,wBAAgB,OAAO,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAE7C"}
@@ -0,0 +1,435 @@
1
+ /**
2
+ * El candado que faltaba: la interfaz de persistencia es ASINCRONICA desde la
3
+ * linea 1.
4
+ *
5
+ * POR QUE EXISTE (Pablo, 13-oct-2026, mirando ADIP-Kikan). El brain construyo
6
+ * Kikan bien en lo estructural: el primer commit dice "nucleo kawa/sazanami +
7
+ * persistencia MariaDB", hay capa de repositorio, y `mysqlStore` hace
8
+ * write-through a MariaDB con hidratacion al arranque -- el dato productivo es
9
+ * durable y siempre lo fue. La decision equivocada fue UNA, y es una FIRMA:
10
+ * la interfaz del repositorio quedo SINCRONICA. De ahi sale todo lo demas, por
11
+ * mecanica pura:
12
+ *
13
+ * 1. un driver SQL real es asincronico, y una interfaz sincronica no lo puede
14
+ * envolver;
15
+ * 2. entonces el store "de MariaDB" tuvo que quedarse el working set en RAM
16
+ * para servir lecturas sincronas -- su propia cabecera lo dice: "lecturas
17
+ * sincronas, interfaz IDENTICA a createMemoryStore -> no reescribe el
18
+ * motor";
19
+ * 3. y como un working set en memoria no necesita columnas, el esquema
20
+ * degenero en UNA tabla generica de JSON (`engine_rows`), con las 57
21
+ * tablas 3NF como read-model DERIVADO en vez de sistema de registro.
22
+ *
23
+ * Una firma de funcion, y de ahi 1.543 puntos de deuda y nueve slices de
24
+ * conversion.
25
+ *
26
+ * LA ASIMETRIA, que es la razon por la que esto no necesita ninguna ronda de
27
+ * dimensionamiento para decidirse:
28
+ *
29
+ * - `await` sobre un valor que no es Promise NO HACE NADA. Declarar el store
30
+ * asincronico desde la linea 1 cuesta CERO cuando el store es de memoria.
31
+ * - El camino inverso -- sincronico a asincronico -- es cada punto de
32
+ * llamada del sistema. En Kikan fueron 1.543.
33
+ *
34
+ * Dos opciones donde una es gratis y reversible y la otra es una reescritura no
35
+ * son dos opciones: una decision asimetrica se toma SIEMPRE del lado
36
+ * recuperable, incluso sin un solo dato de volumetria.
37
+ *
38
+ * POR QUE "DECLARADO async" Y NO "DEVUELVE UNA PROMISE": la segunda es mas
39
+ * precisa y requiere analisis de flujo. La primera es trivial de cumplir
40
+ * (`async` sobre algo que ya devuelve una promesa no cambia nada) y trivial de
41
+ * verificar. Una regla estricta y simple que cualquiera puede satisfacer vale
42
+ * mas que una regla astuta que hay que interpretar.
43
+ *
44
+ * EL MODO DE FALLAR QUE IMPORTA ES EL FALSO NEGATIVO: un store que el detector
45
+ * no reconoce es deuda que el candado no cuenta, y el numero daria verde sin
46
+ * que nadie haya hecho nada. Por eso un archivo que no se puede analizar va a
47
+ * `ilegibles` y el control FALLA, en vez de contar cero. Misma disciplina que
48
+ * el trinquete de Kikan.
49
+ *
50
+ * ASCII-only.
51
+ */
52
+ /** Los verbos que tocan una fila. Si un modulo expone varios de estos, es un
53
+ * store, se llame como se llame. */
54
+ export const VERBOS_DATOS = [
55
+ 'insert', 'bulkInsert', 'insertMany',
56
+ 'update', 'patch', 'upsert', 'save',
57
+ 'remove', 'removeAll', 'delete', 'deleteAll', 'destroy',
58
+ 'get', 'getById', 'find', 'findOne', 'findAll', 'findMany',
59
+ 'all', 'list', 'query', 'select', 'count', 'exists', 'first',
60
+ ];
61
+ const VERBOS = new Set(VERBOS_DATOS);
62
+ /** Cuantos verbos distintos tiene que exponer un modulo sin nombre delator
63
+ * para que lo tratemos como store. */
64
+ export const VERBOS_MINIMOS_POR_FORMA = 4;
65
+ /** El nombre del archivo o su carpeta ya lo delatan. */
66
+ const NOMBRE_DELATOR = /(^|[^a-z])(store|repo|repository|dao|persistence|datastore)([^a-z]|$)/i;
67
+ const CARPETA_DELATORA = /(^|[\\/])(data|stores?|repositor(y|ies)|persistence|dao)([\\/]|$)/i;
68
+ /**
69
+ * Parte camelCase para que el delator se vea: `memoryStore` -> `memory Store`,
70
+ * `userRepository` -> `user Repository`.
71
+ *
72
+ * Sin esto el detector se perdia `userRepository.ts` -- la palabra delatora
73
+ * estaba ahi, pero pegada a la anterior, y el borde que pedia el regex no
74
+ * existia. Es exactamente un FALSO NEGATIVO del detector, la clase de error que
75
+ * hace mentir a un candado, y lo encontro su propia bateria.
76
+ */
77
+ function separarCamel(s) {
78
+ return s.replace(/([a-z0-9])([A-Z])/g, '$1 $2');
79
+ }
80
+ /** La marca para eximir un metodo a mano. Se CUENTA y se reporta: una exencion
81
+ * invisible es un agujero, una exencion contada es una decision. */
82
+ const MARCA_EXENTO = /persistence-async-ok:\s*(.+)$/;
83
+ /**
84
+ * Tapa comentarios y literales de cadena con espacios, conservando los saltos
85
+ * de linea para que los numeros de linea sigan siendo validos.
86
+ *
87
+ * Sin esto, un `insert(` dentro de un comentario o de un template string cuenta
88
+ * como declaracion, y la frase "no uses insert() sin await" en un comentario
89
+ * generaria un hallazgo fantasma.
90
+ */
91
+ /** Fin de una cadena simple (`'` o `"`): el indice DESPUES de la comilla que cierra. */
92
+ function finDeCadena(texto, inicio, cierre) {
93
+ const n = texto.length;
94
+ let j = inicio + 1;
95
+ while (j < n) {
96
+ if (texto[j] === '\\') {
97
+ j += 2;
98
+ continue;
99
+ }
100
+ if (texto[j] === cierre)
101
+ return j + 1;
102
+ if (texto[j] === '\n')
103
+ return j; /* cadena sin cerrar: no arrastra el archivo */
104
+ j++;
105
+ }
106
+ return n;
107
+ }
108
+ /**
109
+ * Fin de un template literal, el indice DESPUES del backtick que cierra.
110
+ *
111
+ * Tiene que entender `${...}` porque la interpolacion es CODIGO y puede
112
+ * contener otro template adentro. El caso real que lo trajo aca, de
113
+ * `sqlStore.js` de Kikan (encontrado calibrando, 13-oct-2026):
114
+ *
115
+ * `UPDATE \`${t}\` SET ${cols.map((c) => `\`${c}\` = ?`).join(', ')} WHERE ...`
116
+ *
117
+ * Un escaner ingenuo cierra el string en el backtick ANIDADO y a partir de ahi
118
+ * lee la mitad del template como codigo: en `sqlStore.js` eso dejaba tres `}`
119
+ * de mas y el archivo entero caia en `ilegibles`. O sea: el defecto no era un
120
+ * falso positivo molesto, era el candado dandose por vencido sobre el store
121
+ * mas importante del proyecto.
122
+ */
123
+ function finDeTemplate(texto, inicio) {
124
+ const n = texto.length;
125
+ let j = inicio + 1;
126
+ while (j < n) {
127
+ const c = texto[j];
128
+ if (c === '\\') {
129
+ j += 2;
130
+ continue;
131
+ }
132
+ if (c === '`')
133
+ return j + 1;
134
+ if (c === '$' && texto[j + 1] === '{') {
135
+ j = finDeInterpolacion(texto, j + 2);
136
+ continue;
137
+ }
138
+ j++;
139
+ }
140
+ return n;
141
+ }
142
+ /** Desde justo despues de `${`, el indice DESPUES del `}` que cierra. */
143
+ function finDeInterpolacion(texto, desde) {
144
+ const n = texto.length;
145
+ let profundidad = 1;
146
+ let j = desde;
147
+ while (j < n && profundidad > 0) {
148
+ const c = texto[j];
149
+ if (c === '\\') {
150
+ j += 2;
151
+ continue;
152
+ }
153
+ if (c === '`') {
154
+ j = finDeTemplate(texto, j);
155
+ continue;
156
+ }
157
+ if (c === '"' || c === "'") {
158
+ j = finDeCadena(texto, j, c);
159
+ continue;
160
+ }
161
+ if (c === '{') {
162
+ profundidad++;
163
+ j++;
164
+ continue;
165
+ }
166
+ if (c === '}') {
167
+ profundidad--;
168
+ j++;
169
+ continue;
170
+ }
171
+ j++;
172
+ }
173
+ return j;
174
+ }
175
+ /* Palabras tras las cuales un `/` abre una expresion regular y no es division.
176
+ * `return /x/.test(s)` es el caso que importa. */
177
+ const ANTES_DE_REGEX = /(^|[^\w$])(return|typeof|case|in|of|new|delete|void|do|else|yield|await|throw)$/;
178
+ /**
179
+ * Abre una expresion regular este `/`, o es una division?
180
+ *
181
+ * La regla: es regex salvo que lo anterior sea algo que PUEDE TERMINAR una
182
+ * expresion -- un identificador, un numero, `)`, `]` o `}`. Mas la excepcion de
183
+ * las palabras clave, porque `return` termina en una letra pero no es un valor.
184
+ *
185
+ * Un `/` mal clasificado como division deja las llaves del regex contadas; mal
186
+ * clasificado como regex se come codigo hasta el proximo `/`. Las dos cosas
187
+ * terminan en `ilegibles`, que es ruidoso pero HONESTO: nunca en un conteo
188
+ * silenciosamente bajo.
189
+ */
190
+ function abreRegex(texto, i) {
191
+ let k = i - 1;
192
+ while (k >= 0 && /\s/.test(texto[k]))
193
+ k--;
194
+ if (k < 0)
195
+ return true;
196
+ const c = texto[k];
197
+ if (/[)\]}]/.test(c))
198
+ return false;
199
+ if (/[\w$]/.test(c))
200
+ return ANTES_DE_REGEX.test(texto.slice(Math.max(0, k - 11), k + 1));
201
+ return true;
202
+ }
203
+ /** Fin de una expresion regular: el indice DESPUES del `/` que cierra. Si no
204
+ * cierra en la misma linea, no era un regex y no se tapa nada. */
205
+ function finDeRegex(texto, inicio) {
206
+ const n = texto.length;
207
+ let j = inicio + 1;
208
+ let enClase = false;
209
+ while (j < n) {
210
+ const c = texto[j];
211
+ if (c === '\\') {
212
+ j += 2;
213
+ continue;
214
+ }
215
+ if (c === '\n')
216
+ return inicio + 1; /* no era un regex */
217
+ if (enClase) {
218
+ if (c === ']')
219
+ enClase = false;
220
+ j++;
221
+ continue;
222
+ }
223
+ if (c === '[') {
224
+ enClase = true;
225
+ j++;
226
+ continue;
227
+ }
228
+ if (c === '/')
229
+ return j + 1;
230
+ j++;
231
+ }
232
+ return inicio + 1;
233
+ }
234
+ export function enmascarar(texto) {
235
+ const out = texto.split('');
236
+ let i = 0;
237
+ const n = texto.length;
238
+ const tapar = (desde, hasta) => {
239
+ for (let k = desde; k < hasta && k < n; k++) {
240
+ if (out[k] !== '\n')
241
+ out[k] = ' ';
242
+ }
243
+ };
244
+ while (i < n) {
245
+ const c = texto[i];
246
+ const d = texto[i + 1];
247
+ if (c === '/' && d === '/') {
248
+ let j = i + 2;
249
+ while (j < n && texto[j] !== '\n')
250
+ j++;
251
+ tapar(i, j);
252
+ i = j;
253
+ continue;
254
+ }
255
+ if (c === '/' && d === '*') {
256
+ let j = i + 2;
257
+ while (j < n && !(texto[j] === '*' && texto[j + 1] === '/'))
258
+ j++;
259
+ tapar(i, Math.min(j + 2, n));
260
+ i = j + 2;
261
+ continue;
262
+ }
263
+ if (c === '"' || c === "'") {
264
+ const fin = finDeCadena(texto, i, c);
265
+ tapar(i, fin);
266
+ i = fin;
267
+ continue;
268
+ }
269
+ if (c === '`') {
270
+ /* Se tapa el template COMPLETO, interpolaciones incluidas. Las llaves de
271
+ * una interpolacion vienen de a pares, asi que taparlas no desbalancea
272
+ * nada -- y el codigo de una interpolacion no declara metodos de store. */
273
+ const fin = finDeTemplate(texto, i);
274
+ tapar(i, fin);
275
+ i = fin;
276
+ continue;
277
+ }
278
+ if (c === '/' && abreRegex(texto, i)) {
279
+ /* Los literales de regex traen llaves: `{0,400}`, `\{`, `[^{}]`. Sin
280
+ * taparlos el balanceo miente -- y lo encontre con el candado corriendo
281
+ * sobre ESTE archivo, que es el que mas regex tiene del repo. */
282
+ const fin = finDeRegex(texto, i);
283
+ tapar(i, fin);
284
+ i = fin;
285
+ continue;
286
+ }
287
+ i++;
288
+ }
289
+ return out.join('');
290
+ }
291
+ /** Las llaves balancean. Si no, el archivo no se puede analizar con confianza. */
292
+ export function balancea(mascara) {
293
+ let n = 0;
294
+ for (const c of mascara) {
295
+ if (c === '{')
296
+ n++;
297
+ else if (c === '}') {
298
+ n--;
299
+ if (n < 0)
300
+ return false;
301
+ }
302
+ }
303
+ return n === 0;
304
+ }
305
+ /** Los verbos distintos que el modulo expone como DECLARACION. */
306
+ function verbosDeclarados(mascara) {
307
+ const vistos = new Set();
308
+ for (const m of declaraciones(mascara)) {
309
+ if (VERBOS.has(m.nombre))
310
+ vistos.add(m.nombre);
311
+ }
312
+ return vistos;
313
+ }
314
+ /**
315
+ * Las declaraciones de metodo del texto enmascarado.
316
+ *
317
+ * Una DECLARACION tiene su lista de parametros seguida de `{` o de `=>`; una
318
+ * LLAMADA termina en `;`, en `)` o en `,`. Eso es lo que separa
319
+ * `insert(table, row) {` de `store.insert(table, row);`. Y el `(?<![.\w$])`
320
+ * de adelante descarta `store.insert(` y `reinsert(`.
321
+ *
322
+ * La lista de parametros puede ocupar varias lineas, asi que se admiten saltos
323
+ * adentro -- acotados, para que un parentesis sin cerrar no arrastre el archivo
324
+ * entero.
325
+ */
326
+ function* declaraciones(mascara) {
327
+ /* metodo de objeto o de clase: `nombre(...) {` con `async` opcional */
328
+ const reMetodo = /(?<![.\w$])(async\s+)?([A-Za-z_$][\w$]*)\s*\(([^()]{0,400})\)\s*\{/g;
329
+ for (let m = reMetodo.exec(mascara); m; m = reMetodo.exec(mascara)) {
330
+ const nombre = m[2];
331
+ /* `if (...) {`, `for (...) {`, `catch (...) {` tienen la misma forma */
332
+ if (CONTROL.has(nombre))
333
+ continue;
334
+ yield { nombre, indice: m.index, esAsync: !!m[1], forma: 'metodo' };
335
+ }
336
+ /* propiedad con funcion: `nombre: async function (...)` / `nombre: function` */
337
+ const reFn = /(?<![.\w$])([A-Za-z_$][\w$]*)\s*:\s*(async\s+)?function\b/g;
338
+ for (let m = reFn.exec(mascara); m; m = reFn.exec(mascara)) {
339
+ yield { nombre: m[1], indice: m.index, esAsync: !!m[2], forma: 'propiedad-funcion' };
340
+ }
341
+ /* propiedad con flecha: `nombre: async (...) =>` / `nombre: (...) =>` */
342
+ const reFlecha = /(?<![.\w$])([A-Za-z_$][\w$]*)\s*:\s*(async\s+)?\(([^()]{0,400})\)\s*=>/g;
343
+ for (let m = reFlecha.exec(mascara); m; m = reFlecha.exec(mascara)) {
344
+ yield { nombre: m[1], indice: m.index, esAsync: !!m[2], forma: 'propiedad-flecha' };
345
+ }
346
+ }
347
+ /* Palabras de control que tienen la misma forma que un metodo. */
348
+ const CONTROL = new Set([
349
+ 'if', 'for', 'while', 'switch', 'catch', 'function', 'return', 'do', 'else',
350
+ 'with', 'typeof', 'await', 'new', 'delete_', 'try', 'finally',
351
+ ]);
352
+ /** Es este archivo un store? */
353
+ export function esStore(ruta, mascara) {
354
+ const base = ruta.split(/[\\/]/).pop() ?? ruta;
355
+ if (NOMBRE_DELATOR.test(separarCamel(base)))
356
+ return true;
357
+ if (CARPETA_DELATORA.test(ruta))
358
+ return true;
359
+ return verbosDeclarados(mascara).size >= VERBOS_MINIMOS_POR_FORMA;
360
+ }
361
+ function lineaDe(texto, indice) {
362
+ let n = 1;
363
+ for (let i = 0; i < indice && i < texto.length; i++)
364
+ if (texto[i] === '\n')
365
+ n++;
366
+ return n;
367
+ }
368
+ /**
369
+ * Analiza un archivo. `fuentes` es [ruta, texto].
370
+ *
371
+ * Devuelve null cuando el archivo NO es un store (nada que decir), y un
372
+ * resultado parcial cuando si lo es.
373
+ */
374
+ export function analizarArchivo(ruta, texto) {
375
+ const mascara = enmascarar(texto);
376
+ if (!esStore(ruta, mascara))
377
+ return null;
378
+ const res = {
379
+ modulos: [ruta], vistos: 0, asincronicos: 0, hallazgos: [], exentos: [], ilegibles: [],
380
+ };
381
+ if (!balancea(mascara)) {
382
+ res.ilegibles.push(ruta);
383
+ return res;
384
+ }
385
+ const lineas = texto.split('\n');
386
+ for (const d of declaraciones(mascara)) {
387
+ if (!VERBOS.has(d.nombre))
388
+ continue;
389
+ res.vistos++;
390
+ const linea = lineaDe(texto, d.indice);
391
+ if (d.esAsync) {
392
+ res.asincronicos++;
393
+ continue;
394
+ }
395
+ /* exencion a mano: en la misma linea o en la de arriba */
396
+ const cerca = (lineas[linea - 1] ?? '') + '\n' + (lineas[linea - 2] ?? '');
397
+ const marca = MARCA_EXENTO.exec(cerca);
398
+ if (marca) {
399
+ res.exentos.push({ archivo: ruta, linea, metodo: d.nombre, motivo: marca[1].trim() });
400
+ continue;
401
+ }
402
+ res.hallazgos.push({ archivo: ruta, linea, metodo: d.nombre, forma: d.forma });
403
+ }
404
+ /* LA CONTRACARA: si la FORMA dijo que es un store porque vio N verbos y el
405
+ * escaner de declaraciones encontro menos, entonces uno de los dos esta mal
406
+ * y el archivo no se puede afirmar. Vale sobre todo para un store con listas
407
+ * de parametros largas, que es justo donde el regex se queda corto. */
408
+ const porForma = verbosDeclarados(mascara).size;
409
+ if (res.vistos < porForma)
410
+ res.ilegibles.push(ruta);
411
+ return res;
412
+ }
413
+ /** Junta el analisis de muchos archivos. */
414
+ export function analizar(fuentes) {
415
+ const total = {
416
+ modulos: [], vistos: 0, asincronicos: 0, hallazgos: [], exentos: [], ilegibles: [],
417
+ };
418
+ for (const [ruta, texto] of fuentes) {
419
+ const r = analizarArchivo(ruta, texto);
420
+ if (!r)
421
+ continue;
422
+ total.modulos.push(...r.modulos);
423
+ total.vistos += r.vistos;
424
+ total.asincronicos += r.asincronicos;
425
+ total.hallazgos.push(...r.hallazgos);
426
+ total.exentos.push(...r.exentos);
427
+ total.ilegibles.push(...r.ilegibles);
428
+ }
429
+ return total;
430
+ }
431
+ /** Pasa el control? Un ilegible lo hace fallar: no se afirma lo que no se midio. */
432
+ export function aprueba(r) {
433
+ return r.hallazgos.length === 0 && r.ilegibles.length === 0;
434
+ }
435
+ //# sourceMappingURL=persistence_async.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence_async.js","sourceRoot":"","sources":["../../src/audit/persistence_async.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"yf.d.ts","sourceRoot":"","sources":["../../src/bin/yf.ts"],"names":[],"mappings":";AAUA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsEpC,wBAAgB,YAAY,IAAI,OAAO,CA6GtC"}
1
+ {"version":3,"file":"yf.d.ts","sourceRoot":"","sources":["../../src/bin/yf.ts"],"names":[],"mappings":";AAUA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuEpC,wBAAgB,YAAY,IAAI,OAAO,CA8GtC"}
package/dist/bin/yf.js CHANGED
@@ -20,6 +20,7 @@ import { registerEmbedCommand } from '../commands/embed.js';
20
20
  import { registerLicenseCommand } from '../commands/license.js';
21
21
  import { registerDoctorCommand } from '../commands/doctor.js';
22
22
  import { registerValidateCommand } from '../commands/validate.js';
23
+ import { registerAuditPersistenceCommand } from '../commands/audit-persistence.js';
23
24
  import { registerPilotCommand } from '../commands/pilot.js';
24
25
  import { registerGenTestsCommand } from '../commands/gen-tests.js';
25
26
  import { registerGenFlowTestsCommand } from '../commands/gen-flow-tests.js';
@@ -106,6 +107,7 @@ export function buildProgram() {
106
107
  registerLicenseCommand(program);
107
108
  registerDoctorCommand(program);
108
109
  registerValidateCommand(program);
110
+ registerAuditPersistenceCommand(program);
109
111
  registerEmbedCommand(program);
110
112
  registerPilotCommand(program);
111
113
  registerGenTestsCommand(program);
@@ -1 +1 @@
1
- {"version":3,"file":"yf.js","sourceRoot":"","sources":["../../src/bin/yf.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"yf.js","sourceRoot":"","sources":["../../src/bin/yf.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"doctrine_digest.d.ts","sourceRoot":"","sources":["../../src/chat/doctrine_digest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,mBAAmB;IAClC,sDAAsD;IACtD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,eAAe,EAAE,mBAAmB,EAoJhD,CAAC;AAEF,6DAA6D;AAC7D,wBAAgB,WAAW,IAAI,MAAM,EAAE,CAEtC;AAED,MAAM,WAAW,qBAAqB;IACpC;4EACwE;IACxE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;uEACuE;AACvE,wBAAgB,wBAAwB,CAAC,IAAI,GAAE,qBAA0B,GAAG,MAAM,EAAE,CAiBnF"}
1
+ {"version":3,"file":"doctrine_digest.d.ts","sourceRoot":"","sources":["../../src/chat/doctrine_digest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,mBAAmB;IAClC,sDAAsD;IACtD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,eAAe,EAAE,mBAAmB,EA4JhD,CAAC;AAEF,6DAA6D;AAC7D,wBAAgB,WAAW,IAAI,MAAM,EAAE,CAEtC;AAED,MAAM,WAAW,qBAAqB;IACpC;4EACwE;IACxE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;uEACuE;AACvE,wBAAgB,wBAAwB,CAAC,IAAI,GAAE,qBAA0B,GAAG,MAAM,EAAE,CAiBnF"}
@@ -96,19 +96,27 @@ export const DOCTRINE_DIGEST = [
96
96
  + 'instruccion precisa, pending o ticket. Full: discover.',
97
97
  },
98
98
  {
99
- slugs: ['sizing'],
99
+ slugs: ['sizing', 'persistence-interface'],
100
100
  /* Deliberately terse: tests/prompt-invariants.test.ts caps the static
101
101
  * prompt, and a longer line here would have to come out of another
102
102
  * doctrine. The verbs carry the detail in their descriptions, and the
103
- * fixed option catalogue lives in docs/doctrine/sizing.md. */
103
+ * fixed option catalogue lives in docs/doctrine/sizing.md.
104
+ *
105
+ * The async-interface clause was compressed INTO this entry rather than
106
+ * added as a new one (13-oct-2026): there were 124 chars of prompt budget
107
+ * left, so the sizing text was tightened to pay for it. It belongs here
108
+ * anyway -- it is the half of the persistence decision that needs NO
109
+ * sizing input, and reading them together is the point. */
104
110
  rule: 'SIZE BEFORE YOU BUILD (G9, hard gate). Volumetry = entities x '
105
- + 'events/year x ROWS PER EVENT (every table it writes) + retention PER '
106
- + 'CLASS (business vs trace; 0 = forever = unbounded) + concurrency + '
107
- + 'HARDWARE (heap_cap_mb is the runtime heap ceiling, NOT machine RAM). '
108
- + 'Ask the owner, never invent it. Pick one option per axis from the '
109
- + 'FIXED catalogue (yujin.sizing.show); yujin.sizing.record REFUSES one '
110
- + 'outside its envelope and construction cannot start without an '
111
- + 'admissible record. Full: discover.',
111
+ + 'events/year x ROWS PER EVENT (every table) + retention PER CLASS '
112
+ + '(0 = forever = unbounded) + concurrency + HARDWARE (heap_cap_mb = '
113
+ + 'heap ceiling, NOT machine RAM). Ask the owner; never invent. One '
114
+ + 'option per axis from the FIXED catalogue (yujin.sizing.show); record '
115
+ + 'REFUSES one outside its envelope and construction cannot start '
116
+ + 'without it. NEEDS NO SIZING: every store/repo method declared async '
117
+ + 'from commit 1 -- await on a non-Promise is free, sync->async later '
118
+ + 'is every call site (Kikan 1543). yf audit persistence. '
119
+ + 'Full: discover.',
112
120
  },
113
121
  {
114
122
  slugs: ['concurrency-scale'],
@@ -1 +1 @@
1
- {"version":3,"file":"doctrine_digest.js","sourceRoot":"","sources":["../../src/chat/doctrine_digest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"doctrine_digest.js","sourceRoot":"","sources":["../../src/chat/doctrine_digest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AASH,MAAM,CAAC,MAAM,eAAe,GAA0B;IACpD;QACE,KAAK,EAAE,CAAC,sBAAsB,CAAC;QAC/B,IAAI,EACF,8DAA8D;cAC5D,6DAA6D;cAC7D,+DAA+D;cAC/D,uDAAuD;cACvD,6DAA6D;cAC7D,yDAAyD;cACzD,gEAAgE;cAChE,4DAA4D;cAC5D,mCAAmC;KACxC;IACD;QACE,KAAK,EAAE,CAAC,gBAAgB,CAAC;QACzB,IAAI,EACF,gEAAgE;cAC9D,0DAA0D;cAC1D,4CAA4C;KACjD;IACD;QACE,KAAK,EAAE,CAAC,YAAY,CAAC;QACrB,IAAI,EAAE,2FAA2F;KAClG;IACD;QACE,KAAK,EAAE,CAAC,eAAe,CAAC;QACxB,IAAI,EAAE,2IAA2I;KAClJ;IACD;QACE,KAAK,EAAE,CAAC,OAAO,CAAC;QAChB,IAAI,EAAE,qFAAqF;KAC5F;IACD;QACE,KAAK,EAAE,CAAC,UAAU,EAAE,iBAAiB,CAAC;QACtC,IAAI,EAAE,2IAA2I;KAClJ;IACD;QACE,KAAK,EAAE,CAAC,gBAAgB,CAAC;QACzB,IAAI,EAAE,uTAAuT;KAC9T;IACD;QACE,KAAK,EAAE,CAAC,OAAO,CAAC;QAChB,IAAI,EAAE,iGAAiG;KACxG;IACD;QACE,KAAK,EAAE,CAAC,iBAAiB,CAAC;QAC1B,IAAI,EAAE,qFAAqF;KAC5F;IACD;QACE,KAAK,EAAE,CAAC,iBAAiB,CAAC;QAC1B,IAAI,EAAE,4GAA4G;KACnH;IACD;QACE,KAAK,EAAE,CAAC,sBAAsB,CAAC;QAC/B,IAAI,EAAE,kJAAkJ;KACzJ;IACD;QACE,KAAK,EAAE,CAAC,uBAAuB,CAAC;QAChC,IAAI,EAAE,mFAAmF;KAC1F;IACD;QACE,KAAK,EAAE,CAAC,iBAAiB,CAAC;QAC1B,IAAI,EACF,+EAA+E;cAC7E,+EAA+E;cAC/E,+EAA+E;cAC/E,yEAAyE;cACzE,2EAA2E;cAC3E,kEAAkE;KACvE;IACD;QACE,KAAK,EAAE,CAAC,cAAc,CAAC;QACvB,IAAI,EACF,8EAA8E;cAC5E,gFAAgF;cAChF,gFAAgF;cAChF,+EAA+E;cAC/E,yEAAyE;cACzE,gFAAgF;cAChF,wEAAwE;cACxE,wDAAwD;KAC7D;IACD;QACE,KAAK,EAAE,CAAC,QAAQ,EAAE,uBAAuB,CAAC;QAC1C;;;;;;;;;mEAS2D;QAC3D,IAAI,EACF,gEAAgE;cAC9D,mEAAmE;cACnE,oEAAoE;cACpE,mEAAmE;cACnE,uEAAuE;cACvE,iEAAiE;cACjE,sEAAsE;cACtE,qEAAqE;cACrE,yDAAyD;cACzD,iBAAiB;KACtB;IACD;QACE,KAAK,EAAE,CAAC,mBAAmB,CAAC;QAC5B,IAAI,EACF,uEAAuE;cACrE,6EAA6E;cAC7E,4EAA4E;cAC5E,mEAAmE;cACnE,gCAAgC;KACrC;IACD;QACE,KAAK,EAAE,CAAC,uBAAuB,CAAC;QAChC,IAAI,EACF,yEAAyE;cACvE,4EAA4E;cAC5E,8EAA8E;cAC9E,2EAA2E;cAC3E,8EAA8E;cAC9E,qEAAqE;cACrE,uEAAuE;cACvE,6DAA6D;KAClE;IACD;QACE,KAAK,EAAE,CAAC,kBAAkB,CAAC;QAC3B,IAAI,EAAE,6XAA6X;KACpY;IACD;QACE,KAAK,EAAE,CAAC,UAAU,CAAC;QACnB,IAAI,EAAE,qeAAqe;KAC5e;IACD;QACE,KAAK,EAAE,CAAC,UAAU,CAAC;QACnB,IAAI,EAAE,iFAAiF;KACxF;IACD;QACE,KAAK,EAAE,CAAC,uBAAuB,CAAC;QAChC,IAAI,EAAE,+UAA+U;KACtV;IACD;QACE,KAAK,EAAE,CAAC,iBAAiB,EAAE,wBAAwB,CAAC;QACpD,IAAI,EAAE,wHAAwH;KAC/H;IACD;QACE,KAAK,EAAE,CAAC,cAAc,CAAC;QACvB,IAAI,EAAE,6RAA6R;KACpS;IACD;QACE,KAAK,EAAE,CAAC,sBAAsB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,aAAa,EAAE,kBAAkB,CAAC;QAC3G,IAAI,EAAE,gLAAgL;KACvL;CACF,CAAC;AAEF,6DAA6D;AAC7D,MAAM,UAAU,WAAW;IACzB,OAAO,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AACjD,CAAC;AAQD;uEACuE;AACvE,MAAM,UAAU,wBAAwB,CAAC,OAA8B,EAAE;IACvE,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC3C,IAAI,CAAC,cAAc,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAC9E,MAAM,KAAK,GAAa;QACtB,mEAAmE;QACnE,2DAA2D;QAC3D,mEAAmE;QACnE,EAAE;QACF,gEAAgE;QAChE,6DAA6D;QAC7D,EAAE;KACH,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IACzD,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * `yf audit persistence [path]` -- la interfaz de persistencia es ASINCRONICA.
3
+ *
4
+ * El candado que le faltaba a Forge, y la razon esta en ADIP-Kikan (Pablo,
5
+ * 13-oct-2026): el brain construyo la capa de repositorio bien y persiste en
6
+ * MariaDB desde el primer commit, pero definio la interfaz SINCRONICA. Eso
7
+ * obligo al store de MariaDB a mantener el working set en RAM para servir
8
+ * lecturas sincronas, y de ahi el esquema degenero en una tabla generica de
9
+ * JSON. Una firma de funcion, 1.543 puntos de deuda y nueve slices de
10
+ * conversion.
11
+ *
12
+ * El analisis vive en `src/audit/persistence_async.ts`, puro y con bateria.
13
+ * Este archivo es solo el recorrido del arbol y el reporte.
14
+ *
15
+ * Corre sobre CUALQUIER proyecto -- recien nacido o heredado -- y no necesita
16
+ * configuracion: el detector reconoce un store por su nombre, por su carpeta o
17
+ * por su forma.
18
+ *
19
+ * ASCII-only.
20
+ */
21
+ import type { Command } from 'commander';
22
+ export interface AuditPersistenceOptions {
23
+ json?: boolean;
24
+ }
25
+ export interface Recolectado {
26
+ fuentes: Array<[string, string]>;
27
+ /** Salteados por generados/minificados. Se REPORTAN: un salteo invisible es
28
+ * un agujero del mismo tipo que un ilegible que cuenta cero. */
29
+ generados: string[];
30
+ }
31
+ export declare function recolectarFuentes(raiz: string): Recolectado;
32
+ export declare function registerAuditPersistenceCommand(program: Command): void;
33
+ //# sourceMappingURL=audit-persistence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-persistence.d.ts","sourceRoot":"","sources":["../../src/commands/audit-persistence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwCzC,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACjC;qEACiE;IACjE,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CA4B3D;AAoED,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyBtE"}
@@ -0,0 +1,173 @@
1
+ import path from 'node:path';
2
+ import { readdirSync, statSync, readFileSync } from 'node:fs';
3
+ import { c, header } from '../ui/colors.js';
4
+ import { analizar, aprueba } from '../audit/persistence_async.js';
5
+ const OMITIR = new Set([
6
+ 'node_modules', 'dist', 'coverage', '.git', '.next', 'build', '.expo',
7
+ '.turbo', 'out', 'vendor', 'third_party', '__pycache__', 'site-packages',
8
+ 'bower_components', '.cache', '.tox', 'target', '.gradle', '.idea',
9
+ ]);
10
+ /* Los entornos virtuales de Python se llaman `.venv`, `venv`, `.venv_test`,
11
+ * `env`... y adentro traen el chromium de Playwright con sus bundles. */
12
+ const OMITIR_PREFIJO = ['.venv', 'venv', '.env-', 'env-'];
13
+ const EXT = /\.(js|mjs|cjs|ts|tsx)$/;
14
+ /* Las baterias quedan afuera: un doble de test SINCRONICO es legitimo -- lo que
15
+ * no puede ser sincronico es el store del que depende el producto. */
16
+ const ES_TEST = /\.(test|spec)\.[jt]sx?$/;
17
+ const ES_MINIFICADO = /\.(min|bundle|chunk)\.[jt]s$/;
18
+ /* Una linea de mas de 1000 caracteres no la escribio una persona: es un bundle,
19
+ * un minificado o un blob generado. Nunca es la capa de persistencia de nadie,
20
+ * y ademas no se puede analizar con sentido.
21
+ *
22
+ * Calibrado contra ADIP-Kikan (13-oct-2026): la primera corrida reporto 26
23
+ * hallazgos dentro de `xtermModule-COQkjINf.js`, un bundle de Playwright
24
+ * metido en un `.venv_harness`. Ese ruido es exactamente lo que hace que un
25
+ * equipo apague un control, y un control apagado no vigila nada. */
26
+ const LARGO_DE_LINEA_GENERADO = 1000;
27
+ function pareceGenerado(texto) {
28
+ let largo = 0;
29
+ for (let i = 0; i < texto.length; i++) {
30
+ if (texto[i] === '\n') {
31
+ largo = 0;
32
+ continue;
33
+ }
34
+ if (++largo > LARGO_DE_LINEA_GENERADO)
35
+ return true;
36
+ }
37
+ return false;
38
+ }
39
+ export function recolectarFuentes(raiz) {
40
+ const fuentes = [];
41
+ const generados = [];
42
+ const omitirDir = (n) => OMITIR.has(n) || OMITIR_PREFIJO.some((p) => n.startsWith(p));
43
+ const rec = (dir) => {
44
+ let items;
45
+ try {
46
+ items = readdirSync(dir);
47
+ }
48
+ catch {
49
+ return;
50
+ }
51
+ for (const nombre of items.sort()) {
52
+ const p = path.join(dir, nombre);
53
+ let st;
54
+ try {
55
+ st = statSync(p);
56
+ }
57
+ catch {
58
+ continue;
59
+ }
60
+ if (st.isDirectory()) {
61
+ if (!omitirDir(nombre))
62
+ rec(p);
63
+ continue;
64
+ }
65
+ if (!EXT.test(nombre) || ES_TEST.test(nombre))
66
+ continue;
67
+ const rel = path.relative(raiz, p).split(path.sep).join('/');
68
+ if (ES_MINIFICADO.test(nombre)) {
69
+ generados.push(rel);
70
+ continue;
71
+ }
72
+ let texto;
73
+ try {
74
+ texto = readFileSync(p, 'utf8');
75
+ }
76
+ catch {
77
+ continue;
78
+ }
79
+ if (pareceGenerado(texto)) {
80
+ generados.push(rel);
81
+ continue;
82
+ }
83
+ fuentes.push([rel, texto]);
84
+ }
85
+ };
86
+ rec(raiz);
87
+ return { fuentes, generados };
88
+ }
89
+ function imprimir(raiz, r, archivos, generados) {
90
+ header('Yujin Forge -- audit persistence');
91
+ console.log('');
92
+ console.log(' Proyecto: ' + c.dim(raiz));
93
+ console.log(' ' + c.dim(archivos + ' archivos leidos, ' + r.modulos.length + ' modulo(s) de persistencia'
94
+ + (generados ? ', ' + generados + ' generado(s)/minificado(s) salteado(s)' : '')));
95
+ console.log('');
96
+ if (r.modulos.length === 0) {
97
+ console.log(c.dim(' No se detecto ninguna capa de persistencia.'));
98
+ console.log('');
99
+ console.log(c.success(' OK') + c.dim(' -- nada que vigilar todavia.'));
100
+ return;
101
+ }
102
+ console.log(' Metodos de acceso a datos: ' + r.vistos
103
+ + c.dim(' (async ' + r.asincronicos + ' / sincronicos ' + r.hallazgos.length + ')'));
104
+ console.log('');
105
+ if (r.hallazgos.length > 0) {
106
+ console.log(c.error(' SINCRONICOS -- cada uno es una interfaz que no puede envolver una base real:'));
107
+ const porArchivo = new Map();
108
+ for (const h of r.hallazgos) {
109
+ const lista = porArchivo.get(h.archivo) ?? [];
110
+ lista.push(h);
111
+ porArchivo.set(h.archivo, lista);
112
+ }
113
+ for (const [archivo, lista] of porArchivo) {
114
+ console.log(' ' + c.dim(archivo));
115
+ for (const h of lista) {
116
+ console.log(' ' + c.error('x') + ' linea ' + String(h.linea).padStart(4)
117
+ + ' ' + h.metodo + '()' + c.dim(' [' + h.forma + ']'));
118
+ }
119
+ }
120
+ console.log('');
121
+ }
122
+ if (r.exentos.length > 0) {
123
+ console.log(c.warn(' Eximidos a mano (' + r.exentos.length + '):'));
124
+ for (const e of r.exentos) {
125
+ console.log(' ' + c.dim(e.archivo + ':' + e.linea) + ' ' + e.metodo + '() -- ' + e.motivo);
126
+ }
127
+ console.log('');
128
+ }
129
+ if (r.ilegibles.length > 0) {
130
+ console.log(c.error(' NO SE PUDIERON ANALIZAR (' + r.ilegibles.length + '):'));
131
+ for (const f of r.ilegibles)
132
+ console.log(' ' + c.error('?') + ' ' + f);
133
+ console.log(c.dim(' Un archivo que no se puede afirmar NO cuenta como cero: el control falla.'));
134
+ console.log('');
135
+ }
136
+ if (aprueba(r)) {
137
+ console.log(c.success(' OK') + ' -- toda la interfaz de persistencia es asincronica.');
138
+ return;
139
+ }
140
+ console.log(c.error(' FALLA'));
141
+ console.log('');
142
+ console.log(c.dim(' Por que esto importa, y por que se arregla AHORA y no despues:'));
143
+ console.log(c.dim(' `await` sobre un valor que no es Promise no hace nada, asi que declarar'));
144
+ console.log(c.dim(' el store async hoy cuesta CERO -- incluso con el store en memoria. El'));
145
+ console.log(c.dim(' camino inverso es cada punto de llamada del sistema: en ADIP-Kikan'));
146
+ console.log(c.dim(' fueron 1.543, en nueve slices. Las dos opciones no son simetricas.'));
147
+ }
148
+ export function registerAuditPersistenceCommand(program) {
149
+ const audit = program.commands.find((cmd) => cmd.name() === 'audit')
150
+ ?? program.command('audit').description('Controles estaticos sobre un proyecto.');
151
+ audit
152
+ .command('persistence [path]')
153
+ .description('Exige que todo metodo de un store/repositorio este declarado async.')
154
+ .option('--json', 'emitir JSON en vez del reporte legible')
155
+ .action(async (where, opts) => {
156
+ const raiz = path.resolve(process.cwd(), where ?? '.');
157
+ const { fuentes, generados } = recolectarFuentes(raiz);
158
+ const r = analizar(fuentes);
159
+ if (opts.json) {
160
+ process.stdout.write(JSON.stringify({
161
+ root: raiz, files: fuentes.length, skipped_generated: generados,
162
+ ok: aprueba(r), ...r,
163
+ }, null, 2) + '\n');
164
+ if (!aprueba(r))
165
+ process.exitCode = 1;
166
+ return;
167
+ }
168
+ imprimir(raiz, r, fuentes.length, generados.length);
169
+ if (!aprueba(r))
170
+ process.exitCode = 1;
171
+ });
172
+ }
173
+ //# sourceMappingURL=audit-persistence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-persistence.js","sourceRoot":"","sources":["../../src/commands/audit-persistence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ # The persistence interface is async from line one
2
+
3
+ A rule with no sizing round, no questions to the owner, and no exceptions
4
+ worth arguing about. It is free to obey and it is the most expensive thing
5
+ in this repo to disobey.
6
+
7
+ ## The rule
8
+
9
+ **Every method of every store, repository or DAO is declared `async`, from
10
+ the first commit, whatever is behind it.** In memory, on disk, over a
11
+ network, a stub that returns `null` -- all of them.
12
+
13
+ Mechanically enforced by `yf audit persistence`. New projects carry it in
14
+ their own CI. The check fails on a synchronous method and it also fails on a
15
+ file it cannot analyse: a store whose signature cannot be asserted is not a
16
+ store that passed.
17
+
18
+ ## Why it needs no information to decide
19
+
20
+ The two directions are not symmetric:
21
+
22
+ | Direction | Cost |
23
+ |---|---|
24
+ | async interface, synchronous implementation behind it | **zero.** `await` on a non-Promise is a no-op |
25
+ | synchronous interface, later made async | **every call site in the system** |
26
+
27
+ An asymmetric decision is always taken on the recoverable side. There is no
28
+ volumetry that makes the sync interface the better bet, because the sync
29
+ interface's only advantage is that it is marginally shorter to type.
30
+
31
+ So this rule does not wait for G9, does not wait for the owner to answer how
32
+ many rows per year, and does not appear in the options catalogue. It is not a
33
+ choice.
34
+
35
+ ## What it actually prevents: ADIP-Kikan
36
+
37
+ Measured, 13-oct-2026. Kikan's first commit reads *"nucleo kawa/sazanami +
38
+ persistencia MariaDB"*. The brain built the repository layer, built two
39
+ implementations, and wired production to MariaDB with write-through and
40
+ boot-time hydration. The data was durable and always had been.
41
+
42
+ One decision was wrong, and it was a **signature**: the repository interface
43
+ was synchronous. Everything else followed mechanically.
44
+
45
+ 1. A real SQL driver is asynchronous, and a synchronous interface cannot
46
+ wrap one.
47
+ 2. So the "MariaDB store" had to keep the working set in RAM to serve reads
48
+ synchronously. Its own header says so: *"lecturas sincronas, interfaz
49
+ IDENTICA a createMemoryStore -> no reescribe el motor"*.
50
+ 3. And because an in-memory working set needs no columns, the schema
51
+ degenerated into **one generic table of JSON rows** (`engine_rows`), with
52
+ the 57 normalised tables demoted to a derived read-model instead of being
53
+ the system of record.
54
+
55
+ The bill: **1.543 call sites**, nine conversion slices, a static ratchet
56
+ built to hold the line, and a reengineering plan of its own.
57
+
58
+ ## Why a brain walks into it
59
+
60
+ Not from ignorance. Every step is locally correct:
61
+
62
+ - When the engine is being written there is **no database yet**. The first
63
+ store you write so the engine is testable is the in-memory one, and its
64
+ natural signature is synchronous -- correct, at that moment.
65
+ - The engine is written against that signature. Now every future store must
66
+ match it or the engine breaks.
67
+ - When the real SQL store finally gets written, that signature is
68
+ load-bearing for hundreds of call sites. Making it async is a repo-wide
69
+ change no single turn can justify and nobody asked for. So the SQL store
70
+ contorts to fit the signature instead.
71
+
72
+ Each step is reasonable. The aggregate is wrong. That is the failure mode of
73
+ incremental construction without an invariant that is checked, and it is why
74
+ this one is a mechanical gate and not a paragraph of advice.
75
+
76
+ Note also what the model never wrote: it never wrote "in-memory
77
+ persistence". It wrote "a repository with a synchronous interface", and that
78
+ shape is everywhere in any training corpus -- every test double, every
79
+ in-process repo, every small app without an ORM. The dangerous default is
80
+ the *common* one, not an exotic one.
81
+
82
+ ## The decision that was never taken
83
+
84
+ There was no turn whose subject was "choose the persistence architecture".
85
+ It accumulated. `docs/doctrine/sizing.md` carries the same finding for
86
+ volumetry; this file carries it for the interface, because the interface is
87
+ the half that costs nothing to get right and everything to get wrong.
88
+
89
+ ## Exemptions
90
+
91
+ A genuinely synchronous accessor that will never cross a process boundary
92
+ can be marked in place:
93
+
94
+ ```js
95
+ // persistence-async-ok: in-RAM index, never touches disk or network
96
+ get(key) { return this.index.get(key); }
97
+ ```
98
+
99
+ The checker **counts and reports** exemptions. An invisible exemption is a
100
+ hole; a counted one is a decision someone can review. Blanket-disabling the
101
+ check is not an exemption, it is the defect.
102
+
103
+ ## What this rule does NOT say
104
+
105
+ - It does not say the store must be SQL. A memory store is fine for a
106
+ prototype; the sizing gate decides that. This rule is only about the
107
+ **signature**.
108
+ - It does not require returning a real Promise. `async` on something that
109
+ already returns one changes nothing; the rule is "declared `async`"
110
+ because that is trivial to satisfy and trivial to verify, and a strict
111
+ simple rule beats a clever one that needs interpreting.
112
+ - It does not apply to test doubles. A synchronous fake inside a battery is
113
+ legitimate; the checker skips `*.test.*` and `*.spec.*` for that reason.
package/dist/version.d.ts CHANGED
@@ -2,5 +2,5 @@
2
2
  * Yujin Forge CLI version. Kept in sync with package.json by the npm
3
3
  * "version" lifecycle (scripts/sync_version.mjs) so the two never drift.
4
4
  */
5
- export declare const VERSION = "1.15.0";
5
+ export declare const VERSION = "1.16.0";
6
6
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -2,5 +2,5 @@
2
2
  * Yujin Forge CLI version. Kept in sync with package.json by the npm
3
3
  * "version" lifecycle (scripts/sync_version.mjs) so the two never drift.
4
4
  */
5
- export const VERSION = '1.15.0';
5
+ export const VERSION = '1.16.0';
6
6
  //# sourceMappingURL=version.js.map
@@ -0,0 +1,113 @@
1
+ # The persistence interface is async from line one
2
+
3
+ A rule with no sizing round, no questions to the owner, and no exceptions
4
+ worth arguing about. It is free to obey and it is the most expensive thing
5
+ in this repo to disobey.
6
+
7
+ ## The rule
8
+
9
+ **Every method of every store, repository or DAO is declared `async`, from
10
+ the first commit, whatever is behind it.** In memory, on disk, over a
11
+ network, a stub that returns `null` -- all of them.
12
+
13
+ Mechanically enforced by `yf audit persistence`. New projects carry it in
14
+ their own CI. The check fails on a synchronous method and it also fails on a
15
+ file it cannot analyse: a store whose signature cannot be asserted is not a
16
+ store that passed.
17
+
18
+ ## Why it needs no information to decide
19
+
20
+ The two directions are not symmetric:
21
+
22
+ | Direction | Cost |
23
+ |---|---|
24
+ | async interface, synchronous implementation behind it | **zero.** `await` on a non-Promise is a no-op |
25
+ | synchronous interface, later made async | **every call site in the system** |
26
+
27
+ An asymmetric decision is always taken on the recoverable side. There is no
28
+ volumetry that makes the sync interface the better bet, because the sync
29
+ interface's only advantage is that it is marginally shorter to type.
30
+
31
+ So this rule does not wait for G9, does not wait for the owner to answer how
32
+ many rows per year, and does not appear in the options catalogue. It is not a
33
+ choice.
34
+
35
+ ## What it actually prevents: ADIP-Kikan
36
+
37
+ Measured, 13-oct-2026. Kikan's first commit reads *"nucleo kawa/sazanami +
38
+ persistencia MariaDB"*. The brain built the repository layer, built two
39
+ implementations, and wired production to MariaDB with write-through and
40
+ boot-time hydration. The data was durable and always had been.
41
+
42
+ One decision was wrong, and it was a **signature**: the repository interface
43
+ was synchronous. Everything else followed mechanically.
44
+
45
+ 1. A real SQL driver is asynchronous, and a synchronous interface cannot
46
+ wrap one.
47
+ 2. So the "MariaDB store" had to keep the working set in RAM to serve reads
48
+ synchronously. Its own header says so: *"lecturas sincronas, interfaz
49
+ IDENTICA a createMemoryStore -> no reescribe el motor"*.
50
+ 3. And because an in-memory working set needs no columns, the schema
51
+ degenerated into **one generic table of JSON rows** (`engine_rows`), with
52
+ the 57 normalised tables demoted to a derived read-model instead of being
53
+ the system of record.
54
+
55
+ The bill: **1.543 call sites**, nine conversion slices, a static ratchet
56
+ built to hold the line, and a reengineering plan of its own.
57
+
58
+ ## Why a brain walks into it
59
+
60
+ Not from ignorance. Every step is locally correct:
61
+
62
+ - When the engine is being written there is **no database yet**. The first
63
+ store you write so the engine is testable is the in-memory one, and its
64
+ natural signature is synchronous -- correct, at that moment.
65
+ - The engine is written against that signature. Now every future store must
66
+ match it or the engine breaks.
67
+ - When the real SQL store finally gets written, that signature is
68
+ load-bearing for hundreds of call sites. Making it async is a repo-wide
69
+ change no single turn can justify and nobody asked for. So the SQL store
70
+ contorts to fit the signature instead.
71
+
72
+ Each step is reasonable. The aggregate is wrong. That is the failure mode of
73
+ incremental construction without an invariant that is checked, and it is why
74
+ this one is a mechanical gate and not a paragraph of advice.
75
+
76
+ Note also what the model never wrote: it never wrote "in-memory
77
+ persistence". It wrote "a repository with a synchronous interface", and that
78
+ shape is everywhere in any training corpus -- every test double, every
79
+ in-process repo, every small app without an ORM. The dangerous default is
80
+ the *common* one, not an exotic one.
81
+
82
+ ## The decision that was never taken
83
+
84
+ There was no turn whose subject was "choose the persistence architecture".
85
+ It accumulated. `docs/doctrine/sizing.md` carries the same finding for
86
+ volumetry; this file carries it for the interface, because the interface is
87
+ the half that costs nothing to get right and everything to get wrong.
88
+
89
+ ## Exemptions
90
+
91
+ A genuinely synchronous accessor that will never cross a process boundary
92
+ can be marked in place:
93
+
94
+ ```js
95
+ // persistence-async-ok: in-RAM index, never touches disk or network
96
+ get(key) { return this.index.get(key); }
97
+ ```
98
+
99
+ The checker **counts and reports** exemptions. An invisible exemption is a
100
+ hole; a counted one is a decision someone can review. Blanket-disabling the
101
+ check is not an exemption, it is the defect.
102
+
103
+ ## What this rule does NOT say
104
+
105
+ - It does not say the store must be SQL. A memory store is fine for a
106
+ prototype; the sizing gate decides that. This rule is only about the
107
+ **signature**.
108
+ - It does not require returning a real Promise. `async` on something that
109
+ already returns one changes nothing; the rule is "declared `async`"
110
+ because that is trivial to satisfy and trivial to verify, and a strict
111
+ simple rule beats a clever one that needs interpreting.
112
+ - It does not apply to test doubles. A synchronous fake inside a battery is
113
+ legitimate; the checker skips `*.test.*` and `*.spec.*` for that reason.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nac3/forge-cli",
3
- "version": "1.15.0",
3
+ "version": "1.16.0",
4
4
  "description": "Yujin Forge -- voice-first NAC-3 React development framework. CLI + chat panel + spec ingest + 10-format document reader + voice loop.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Pablo Kuschnirof <pablo@rpaforce.com>",
@@ -11,7 +11,8 @@
11
11
  "test:watch": "vitest",
12
12
  "test:e2e": "playwright test",
13
13
  "lint": "next lint",
14
- "typecheck": "tsc --noEmit",
14
+ "typecheck": "tsc --noEmit && yf audit persistence",
15
+ "audit:persistence": "yf audit persistence",
15
16
  "yf": "yf"
16
17
  },
17
18
  "dependencies": {
@@ -11,7 +11,8 @@
11
11
  "test": "vitest run",
12
12
  "test:watch": "vitest",
13
13
  "test:e2e": "playwright test",
14
- "lint": "tsc --noEmit",
14
+ "lint": "tsc --noEmit && yf audit persistence",
15
+ "audit:persistence": "yf audit persistence",
15
16
  "yf": "yf"
16
17
  },
17
18
  "dependencies": {