@nac3/forge-cli 1.23.7 → 1.24.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.
- package/dist/chat/claude.d.ts +8 -0
- package/dist/chat/claude.d.ts.map +1 -1
- package/dist/chat/claude.js.map +1 -1
- package/dist/chat/claude_cli.d.ts +23 -0
- package/dist/chat/claude_cli.d.ts.map +1 -1
- package/dist/chat/claude_cli.js +76 -2
- package/dist/chat/claude_cli.js.map +1 -1
- package/dist/chat/doctrine_digest.d.ts.map +1 -1
- package/dist/chat/doctrine_digest.js +2 -1
- package/dist/chat/doctrine_digest.js.map +1 -1
- package/dist/chat/server.d.ts.map +1 -1
- package/dist/chat/server.js +11 -0
- package/dist/chat/server.js.map +1 -1
- package/dist/chat/tools/pending.d.ts +11 -0
- package/dist/chat/tools/pending.d.ts.map +1 -1
- package/dist/chat/tools/pending.js +55 -8
- package/dist/chat/tools/pending.js.map +1 -1
- package/dist/chat/tools/shell.d.ts +39 -4
- package/dist/chat/tools/shell.d.ts.map +1 -1
- package/dist/chat/tools/shell.js +167 -7
- package/dist/chat/tools/shell.js.map +1 -1
- package/dist/chat/tools/urazuke.d.ts.map +1 -1
- package/dist/chat/tools/urazuke.js +8 -5
- package/dist/chat/tools/urazuke.js.map +1 -1
- package/dist/chat/urazuke_section.d.ts +26 -4
- package/dist/chat/urazuke_section.d.ts.map +1 -1
- package/dist/chat/urazuke_section.js +115 -9
- package/dist/chat/urazuke_section.js.map +1 -1
- package/dist/commands/pending.d.ts.map +1 -1
- package/dist/commands/pending.js +116 -12
- package/dist/commands/pending.js.map +1 -1
- package/dist/commands/urazuke.d.ts +3 -0
- package/dist/commands/urazuke.d.ts.map +1 -1
- package/dist/commands/urazuke.js +80 -3
- package/dist/commands/urazuke.js.map +1 -1
- package/dist/core/ascii_purity.d.ts +69 -0
- package/dist/core/ascii_purity.d.ts.map +1 -0
- package/dist/core/ascii_purity.js +141 -0
- package/dist/core/ascii_purity.js.map +1 -0
- package/dist/core/battery_stamp.d.ts +111 -0
- package/dist/core/battery_stamp.d.ts.map +1 -0
- package/dist/core/battery_stamp.js +287 -0
- package/dist/core/battery_stamp.js.map +1 -0
- package/dist/core/ci_gaps.d.ts +130 -0
- package/dist/core/ci_gaps.d.ts.map +1 -0
- package/dist/core/ci_gaps.js +353 -0
- package/dist/core/ci_gaps.js.map +1 -0
- package/dist/core/doc_citations.d.ts +133 -0
- package/dist/core/doc_citations.d.ts.map +1 -0
- package/dist/core/doc_citations.js +271 -0
- package/dist/core/doc_citations.js.map +1 -0
- package/dist/core/hook_budget.d.ts +60 -0
- package/dist/core/hook_budget.d.ts.map +1 -0
- package/dist/core/hook_budget.js +163 -0
- package/dist/core/hook_budget.js.map +1 -0
- package/dist/docs/doctrine/urazuke.md +173 -2
- package/dist/nac3/internal_manifest.d.ts.map +1 -1
- package/dist/nac3/internal_manifest.js +28 -2
- package/dist/nac3/internal_manifest.js.map +1 -1
- package/dist/pending/store.d.ts +29 -0
- package/dist/pending/store.d.ts.map +1 -1
- package/dist/pending/store.js +51 -1
- package/dist/pending/store.js.map +1 -1
- package/dist/pending/types.d.ts +23 -0
- package/dist/pending/types.d.ts.map +1 -1
- package/dist/pending/types.js.map +1 -1
- package/dist/telemetry/usage.d.ts +18 -0
- package/dist/telemetry/usage.d.ts.map +1 -1
- package/dist/telemetry/usage.js +16 -1
- package/dist/telemetry/usage.js.map +1 -1
- package/dist/urazuke/announce.d.ts +7 -0
- package/dist/urazuke/announce.d.ts.map +1 -1
- package/dist/urazuke/announce.js +20 -0
- package/dist/urazuke/announce.js.map +1 -1
- package/dist/urazuke/catalog.d.ts +1 -1
- package/dist/urazuke/catalog.d.ts.map +1 -1
- package/dist/urazuke/catalog.js.map +1 -1
- package/dist/urazuke/close_gate.d.ts +31 -4
- package/dist/urazuke/close_gate.d.ts.map +1 -1
- package/dist/urazuke/close_gate.js +70 -13
- package/dist/urazuke/close_gate.js.map +1 -1
- package/dist/urazuke/current.d.ts +28 -0
- package/dist/urazuke/current.d.ts.map +1 -1
- package/dist/urazuke/current.js +18 -5
- package/dist/urazuke/current.js.map +1 -1
- package/dist/urazuke/cycle.d.ts +3 -0
- package/dist/urazuke/cycle.d.ts.map +1 -1
- package/dist/urazuke/cycle.js +5 -3
- package/dist/urazuke/cycle.js.map +1 -1
- package/dist/urazuke/evidence.d.ts +14 -1
- package/dist/urazuke/evidence.d.ts.map +1 -1
- package/dist/urazuke/evidence.js +88 -2
- package/dist/urazuke/evidence.js.map +1 -1
- package/dist/urazuke/evidence_env.d.ts +78 -0
- package/dist/urazuke/evidence_env.d.ts.map +1 -0
- package/dist/urazuke/evidence_env.js +341 -0
- package/dist/urazuke/evidence_env.js.map +1 -0
- package/dist/urazuke/freeze.d.ts.map +1 -1
- package/dist/urazuke/freeze.js +16 -9
- package/dist/urazuke/freeze.js.map +1 -1
- package/dist/urazuke/gate.d.ts +48 -0
- package/dist/urazuke/gate.d.ts.map +1 -1
- package/dist/urazuke/gate.js +251 -25
- package/dist/urazuke/gate.js.map +1 -1
- package/dist/urazuke/gates_data.d.ts +30 -3
- package/dist/urazuke/gates_data.d.ts.map +1 -1
- package/dist/urazuke/gates_data.js +51 -5
- package/dist/urazuke/gates_data.js.map +1 -1
- package/dist/urazuke/gates_pull.d.ts +40 -0
- package/dist/urazuke/gates_pull.d.ts.map +1 -1
- package/dist/urazuke/gates_pull.js +118 -8
- package/dist/urazuke/gates_pull.js.map +1 -1
- package/dist/urazuke/manual_cases.d.ts +11 -1
- package/dist/urazuke/manual_cases.d.ts.map +1 -1
- package/dist/urazuke/manual_cases.js +1 -0
- package/dist/urazuke/manual_cases.js.map +1 -1
- package/dist/urazuke/overrides.d.ts +107 -0
- package/dist/urazuke/overrides.d.ts.map +1 -0
- package/dist/urazuke/overrides.js +128 -0
- package/dist/urazuke/overrides.js.map +1 -0
- package/dist/urazuke/probes.d.ts.map +1 -1
- package/dist/urazuke/probes.js +51 -0
- package/dist/urazuke/probes.js.map +1 -1
- package/dist/urazuke/profiles.d.ts +135 -0
- package/dist/urazuke/profiles.d.ts.map +1 -0
- package/dist/urazuke/profiles.js +470 -0
- package/dist/urazuke/profiles.js.map +1 -0
- package/dist/urazuke/receipt_audit.d.ts +67 -0
- package/dist/urazuke/receipt_audit.d.ts.map +1 -0
- package/dist/urazuke/receipt_audit.js +103 -0
- package/dist/urazuke/receipt_audit.js.map +1 -0
- package/dist/urazuke/receipts.d.ts +22 -0
- package/dist/urazuke/receipts.d.ts.map +1 -1
- package/dist/urazuke/receipts.js +44 -0
- package/dist/urazuke/receipts.js.map +1 -1
- package/dist/urazuke/report.d.ts +30 -0
- package/dist/urazuke/report.d.ts.map +1 -1
- package/dist/urazuke/report.js +39 -0
- package/dist/urazuke/report.js.map +1 -1
- package/dist/urazuke/reset.d.ts +35 -0
- package/dist/urazuke/reset.d.ts.map +1 -0
- package/dist/urazuke/reset.js +150 -0
- package/dist/urazuke/reset.js.map +1 -0
- package/dist/urazuke/retro.d.ts +5 -1
- package/dist/urazuke/retro.d.ts.map +1 -1
- package/dist/urazuke/retro.js +21 -8
- package/dist/urazuke/retro.js.map +1 -1
- package/dist/urazuke/section.d.ts.map +1 -1
- package/dist/urazuke/section.js +17 -2
- package/dist/urazuke/section.js.map +1 -1
- package/dist/urazuke/semantics.d.ts +173 -0
- package/dist/urazuke/semantics.d.ts.map +1 -0
- package/dist/urazuke/semantics.js +232 -0
- package/dist/urazuke/semantics.js.map +1 -0
- package/dist/urazuke/start.d.ts +8 -0
- package/dist/urazuke/start.d.ts.map +1 -1
- package/dist/urazuke/start.js +10 -2
- package/dist/urazuke/start.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/workflow/orchestrator.d.ts.map +1 -1
- package/dist/workflow/orchestrator.js +6 -7
- package/dist/workflow/orchestrator.js.map +1 -1
- package/docs/doctrine/urazuke.md +173 -2
- package/package.json +9 -2
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LAS CITAS A LA NADA -- la compuerta que el dueno pidio (2026-11-01).
|
|
3
|
+
*
|
|
4
|
+
* EL DEFECTO, en sus palabras: "un documento que afirma una compuerta con
|
|
5
|
+
* confianza es mas convincente que uno que falta. La ausencia se nota; la
|
|
6
|
+
* afirmacion falsa no." Van tres citas a la nada medidas en dos lotes
|
|
7
|
+
* -- `docs/PROGRAMMING_NORMS.md` citado por `.github/workflows/ci.yml` cinco
|
|
8
|
+
* meses sin existir, cuatro jobs y dos crons descritos en
|
|
9
|
+
* `docs/CI_PIPELINE.md` que nunca existieron, y un comentario de
|
|
10
|
+
* `.github/workflows/ci.yml` al que remitia `CLAUDE.md` -- y las tres
|
|
11
|
+
* describian compuertas. Esta compuerta cierra la familia: todo archivo de
|
|
12
|
+
* este repositorio citado en un documento VIGENTE tiene que existir.
|
|
13
|
+
*
|
|
14
|
+
* POR QUE EL DETECTOR ES CONSERVADOR. Una compuerta ruidosa se desactiva, y
|
|
15
|
+
* un gancho desactivado es peor que ninguno porque figura como existente
|
|
16
|
+
* (el mismo argumento con el que el dueno acoto F-15). Asi que esto NO
|
|
17
|
+
* intenta encontrar toda cita: encuentra las que son inequivocamente una
|
|
18
|
+
* afirmacion sobre ESTE repositorio HOY. Las reglas, en orden:
|
|
19
|
+
*
|
|
20
|
+
* 1. Los bloques de codigo cercados no se miran. Un `ls docs/FOO.md` de
|
|
21
|
+
* ejemplo no es una afirmacion sobre el repositorio.
|
|
22
|
+
* 2. Solo cuentan los tramos entre acentos graves y los destinos de los
|
|
23
|
+
* enlaces markdown. Una ruta en prosa suelta no se toca.
|
|
24
|
+
* 3. Con `/`: el primer segmento tiene que ser un directorio que EXISTE en
|
|
25
|
+
* la raiz y no ser generado (`dist/`, `test-results/`, `.forge/`...).
|
|
26
|
+
* La cita afirma una UBICACION, asi que se verifica tal cual.
|
|
27
|
+
* Sin `/`: es un NOMBRE, no una ubicacion, y se verifica como tal --
|
|
28
|
+
* basta que un archivo con ese nombre exista en algun lugar del
|
|
29
|
+
* repositorio. Medido: tratar `claude.ts` como archivo de la raiz daba
|
|
30
|
+
* cientos de falsos positivos, y descartarlo del todo dejaba pasar
|
|
31
|
+
* nombres que ya no existen en ninguna parte (`relay_error.ts`).
|
|
32
|
+
* 4. Nada con comodin (`*`, `?`), hueco (`<x>`, `{x}`, `$x`), dos puntos
|
|
33
|
+
* (rutas de Windows, `repo:ruta`) ni esquema (`http://`). Son formas
|
|
34
|
+
* que no afirman un archivo concreto.
|
|
35
|
+
*
|
|
36
|
+
* Y LOS DOCUMENTOS HISTORICOS NO ENTRAN, por una razon que no es comodidad:
|
|
37
|
+
* un changelog, un traspaso o un informe fechado describen el estado del
|
|
38
|
+
* repositorio EN SU FECHA, y un archivo que existia entonces y se renombro
|
|
39
|
+
* despues es historia correcta, no una cita a la nada. Medido: de 2378 citas
|
|
40
|
+
* verificables, 762 estaban muertas y la enorme mayoria vivia justamente
|
|
41
|
+
* ahi. Meterlas obligaria a una lista de permisos de cientos de entradas sin
|
|
42
|
+
* motivo real, que es la misma afirmacion sin respaldo que esto persigue. La
|
|
43
|
+
* exclusion se DECLARA (`isHistoricalDoc`) y la corrida dice cuantos
|
|
44
|
+
* documentos salteo, nunca en silencio.
|
|
45
|
+
*
|
|
46
|
+
* ASCII-only.
|
|
47
|
+
*/
|
|
48
|
+
/** Directorios de la raiz que existen pero NO son fuente: lo que hay dentro
|
|
49
|
+
* lo genera una corrida o lo escribe un producto en ejecucion, asi que un
|
|
50
|
+
* documento puede nombrarlos legitimamente sin que esten en disco. */
|
|
51
|
+
export const GENERATED_ROOTS = [
|
|
52
|
+
'dist', 'node_modules', 'test-results', 'qa_reports', 'coverage', 'build',
|
|
53
|
+
];
|
|
54
|
+
/** Extensiones que hacen que un token sin `/` cuente como cita de un nombre
|
|
55
|
+
* de archivo. Corta a proposito: un token cualquiera no es una cita. */
|
|
56
|
+
const NAME_EXT = [
|
|
57
|
+
'.md', '.json', '.yml', '.yaml', '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs',
|
|
58
|
+
'.toml', '.sql', '.sh', '.py', '.php',
|
|
59
|
+
];
|
|
60
|
+
/** Sufijos de puntuacion que la prosa deja pegados a una ruta. */
|
|
61
|
+
function trimPunctuation(s) {
|
|
62
|
+
return s.replace(/^[('"`]+/, '').replace(/[)'"`,.;:!?]+$/, '');
|
|
63
|
+
}
|
|
64
|
+
/** La forma de la cita, o el motivo por el que no es una cita verificable. */
|
|
65
|
+
export function classifyToken(token, rootDirs) {
|
|
66
|
+
const t = token.trim();
|
|
67
|
+
if (!t)
|
|
68
|
+
return { reject: 'vacio' };
|
|
69
|
+
if (/\s/.test(t))
|
|
70
|
+
return { reject: 'tiene espacios' };
|
|
71
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(t))
|
|
72
|
+
return { reject: 'es una URL' };
|
|
73
|
+
if (t.startsWith('#') || t.startsWith('mailto:'))
|
|
74
|
+
return { reject: 'es un ancla o un correo' };
|
|
75
|
+
if (/[*?<>{}$|]/.test(t))
|
|
76
|
+
return { reject: 'tiene comodin o hueco' };
|
|
77
|
+
if (t.includes(':'))
|
|
78
|
+
return { reject: 'tiene dos puntos (ruta ajena o de Windows)' };
|
|
79
|
+
if (t.includes('\\'))
|
|
80
|
+
return { reject: 'usa separador de Windows' };
|
|
81
|
+
if (t.includes('..'))
|
|
82
|
+
return { reject: 'sube de directorio' };
|
|
83
|
+
if (t.startsWith('/'))
|
|
84
|
+
return { reject: 'es absoluta' };
|
|
85
|
+
if (t.startsWith('~'))
|
|
86
|
+
return { reject: 'es del home del usuario' };
|
|
87
|
+
const clean = t.replace(/^\.\//, '').replace(/\/+$/, '');
|
|
88
|
+
if (!clean)
|
|
89
|
+
return { reject: 'vacio' };
|
|
90
|
+
const dot = clean.lastIndexOf('.');
|
|
91
|
+
const ext = dot > 0 ? clean.slice(dot).toLowerCase() : '';
|
|
92
|
+
if (clean.includes('/')) {
|
|
93
|
+
const segs = clean.split('/');
|
|
94
|
+
const first = segs[0];
|
|
95
|
+
if (!rootDirs.includes(first))
|
|
96
|
+
return { reject: 'su primer segmento no es un directorio de este repositorio' };
|
|
97
|
+
if (first.startsWith('.') && first !== '.github')
|
|
98
|
+
return { reject: 'vive en un directorio de estado local' };
|
|
99
|
+
/* Generado en CUALQUIER tramo, no solo en el primero: la salida de un
|
|
100
|
+
* build de CI (`apps/x/android/app/build/outputs/...`) la produce la
|
|
101
|
+
* corrida, asi que nombrarla no afirma un archivo en disco. */
|
|
102
|
+
if (segs.some((s) => GENERATED_ROOTS.includes(s)))
|
|
103
|
+
return { reject: 'vive en un directorio generado' };
|
|
104
|
+
return 'path';
|
|
105
|
+
}
|
|
106
|
+
if (!ext)
|
|
107
|
+
return { reject: 'no parece un archivo' };
|
|
108
|
+
if (!NAME_EXT.includes(ext))
|
|
109
|
+
return { reject: 'extension no reconocida' };
|
|
110
|
+
return 'name';
|
|
111
|
+
}
|
|
112
|
+
/** Las citas verificables de un documento markdown. */
|
|
113
|
+
export function extractCitations(md, rootDirs) {
|
|
114
|
+
const out = [];
|
|
115
|
+
const lines = md.split(/\r?\n/);
|
|
116
|
+
let fence = null;
|
|
117
|
+
for (let i = 0; i < lines.length; i++) {
|
|
118
|
+
const line = lines[i];
|
|
119
|
+
const fenceMatch = /^\s*(```+|~~~+)/.exec(line);
|
|
120
|
+
if (fenceMatch) {
|
|
121
|
+
const mark = fenceMatch[1];
|
|
122
|
+
if (fence === null)
|
|
123
|
+
fence = mark[0];
|
|
124
|
+
else if (mark[0] === fence)
|
|
125
|
+
fence = null;
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (fence !== null)
|
|
129
|
+
continue;
|
|
130
|
+
/* Lineas sangradas cuatro espacios: bloque de codigo indentado. */
|
|
131
|
+
if (/^ {4,}\S/.test(line) && !/^ {0,3}[-*+]/.test(line))
|
|
132
|
+
continue;
|
|
133
|
+
const tokens = [];
|
|
134
|
+
for (const m of line.matchAll(/`([^`\n]+)`/g))
|
|
135
|
+
tokens.push(m[1]);
|
|
136
|
+
for (const m of line.matchAll(/\]\(([^)\s]+)\)/g))
|
|
137
|
+
tokens.push(m[1]);
|
|
138
|
+
for (const raw of tokens) {
|
|
139
|
+
/* El ancla (`docs/X.md#seccion`) no es parte del archivo. */
|
|
140
|
+
const target0 = trimPunctuation(raw).split('#')[0];
|
|
141
|
+
const target = target0.replace(/^\.\//, '').replace(/\/+$/, '');
|
|
142
|
+
const shape = classifyToken(target, rootDirs);
|
|
143
|
+
if (typeof shape !== 'string')
|
|
144
|
+
continue;
|
|
145
|
+
if (out.some((c) => c.line === i + 1 && c.target === target))
|
|
146
|
+
continue;
|
|
147
|
+
out.push({ line: i + 1, target, raw, shape });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
/** Un documento que describe el estado del repositorio en su fecha, no hoy.
|
|
153
|
+
* La lista es de FORMAS de nombre, no de rutas: una lista de rutas se
|
|
154
|
+
* desactualiza con cada documento nuevo y acaba siendo una lista de
|
|
155
|
+
* permisos. */
|
|
156
|
+
export function isHistoricalDoc(rel) {
|
|
157
|
+
const p = rel.replace(/\\/g, '/');
|
|
158
|
+
const base = p.split('/').pop();
|
|
159
|
+
if (base === 'CHANGELOG.md')
|
|
160
|
+
return true;
|
|
161
|
+
/* Carpetas de contexto volcado de una sesion. */
|
|
162
|
+
if (/(^|\/)context-from-/.test(p))
|
|
163
|
+
return true;
|
|
164
|
+
if (/(^|\/)handoff\//i.test(p))
|
|
165
|
+
return true;
|
|
166
|
+
/* Nombre con fecha: un documento fechado afirma sobre su fecha. Los dos
|
|
167
|
+
* separadores se mezclan de verdad en este repositorio
|
|
168
|
+
* (`CATCHUP_PRELIMINAR_2026-06-11.md`), asi que la forma los acepta
|
|
169
|
+
* mezclados en vez de pedir uno solo. */
|
|
170
|
+
if (/[_-]\d{4}[_-]\d{2}[_-]\d{2}/.test(base))
|
|
171
|
+
return true;
|
|
172
|
+
/* Generos que son registro, no especificacion vigente. */
|
|
173
|
+
if (/^(HANDOFF|SESSION|SESION|AUTOPILOT|CODE_REVIEW|INFORME|PROMPT|RETRO|SNAPSHOT|PENDING_REGISTRY_SNAPSHOT)[_-]/i.test(base))
|
|
174
|
+
return true;
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
/** Las citas de un archivo de MAQUINARIA (workflow, lefthook, manifiesto):
|
|
178
|
+
* ahi una ruta no viene entre acentos graves, viene en un comentario o en
|
|
179
|
+
* un valor. Se buscan por forma y se pasan por el mismo clasificador.
|
|
180
|
+
*
|
|
181
|
+
* Esto NO se usa sobre fuentes TypeScript a proposito: un especificador de
|
|
182
|
+
* import (`./tools/x.js`) tiene forma de ruta, es relativo al archivo y
|
|
183
|
+
* apunta al transpilado, asi que daria cientos de falsos positivos.
|
|
184
|
+
* Medido antes de acotar: 307.
|
|
185
|
+
*
|
|
186
|
+
* Y aca la cita tiene que llevar EXTENSION. En un archivo de maquinaria no
|
|
187
|
+
* hay acentos graves que delimiten el token, asi que un tramo sin extension
|
|
188
|
+
* suele ser otra cosa con forma de ruta -- medido: `src/version\.ts` dentro
|
|
189
|
+
* de una expresion regular de `lefthook.yml` se lee como `src/version`. Las
|
|
190
|
+
* tres citas a la nada que este repositorio ya pago llevaban extension. */
|
|
191
|
+
export function extractMachineryCitations(text, rootDirs) {
|
|
192
|
+
const out = [];
|
|
193
|
+
const lines = text.split(/\r?\n/);
|
|
194
|
+
const re = /[A-Za-z0-9_.][A-Za-z0-9_./-]*\/[A-Za-z0-9_][A-Za-z0-9_./-]*/g;
|
|
195
|
+
for (let i = 0; i < lines.length; i++) {
|
|
196
|
+
for (const m of lines[i].matchAll(re)) {
|
|
197
|
+
const target = trimPunctuation(m[0]).replace(/^\.\//, '').replace(/\/+$/, '');
|
|
198
|
+
if (!/\.[a-z0-9]{1,6}$/i.test(target))
|
|
199
|
+
continue;
|
|
200
|
+
const shape = classifyToken(target, rootDirs);
|
|
201
|
+
if (shape !== 'path')
|
|
202
|
+
continue;
|
|
203
|
+
if (out.some((c) => c.line === i + 1 && c.target === target))
|
|
204
|
+
continue;
|
|
205
|
+
out.push({ line: i + 1, target, raw: m[0], shape });
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return out;
|
|
209
|
+
}
|
|
210
|
+
/** EL ALCANCE QUE BLOQUEA, y por que es este y no "todos los documentos".
|
|
211
|
+
*
|
|
212
|
+
* Medido en este repositorio: de 1331 citas verificables en documentos
|
|
213
|
+
* vigentes, 206 apuntan a archivos que no existen -- y casi todas son
|
|
214
|
+
* correctas. El espacio `docs/` esta SOBRECARGADO: `docs/SQ.md` exige
|
|
215
|
+
* `docs/USER_MANUAL.md` al proyecto ADOPTANTE, `src/urazuke/catalog.ts`
|
|
216
|
+
* nombra `docs/GATES.md` como artefacto que produce el proyecto que corre
|
|
217
|
+
* el metodo, y `docs/worker/README.md` cita `src/relay.js` relativo a su
|
|
218
|
+
* propio componente. Prescribir rutas para otros proyectos es el negocio
|
|
219
|
+
* de este repositorio, asi que "toda ruta citada existe" es FALSO como
|
|
220
|
+
* regla general y una compuerta que lo exija pide una lista de permisos de
|
|
221
|
+
* cientos de entradas -- que es la misma afirmacion sin respaldo que esto
|
|
222
|
+
* persigue.
|
|
223
|
+
*
|
|
224
|
+
* Lo que si se puede exigir sin excepciones es este conjunto: los archivos
|
|
225
|
+
* que se leen como AUTORIDAD sobre la maquinaria de este repositorio. Es
|
|
226
|
+
* donde vivieron los tres defectos medidos y es chico y verificable. El
|
|
227
|
+
* resto se MIDE y se informa en la misma salida, nunca en silencio.
|
|
228
|
+
*
|
|
229
|
+
* Y dentro de ese conjunto bloquean solo las citas con forma de RUTA. Un
|
|
230
|
+
* nombre suelto (`nac-bridge.js`, `pilot.bundle.js` en el README) no afirma
|
|
231
|
+
* una ubicacion de este repositorio: nombra un artefacto de otro paquete.
|
|
232
|
+
* Una ruta si afirma: dice "esta aca". Esa es la afirmacion que las tres
|
|
233
|
+
* citas a la nada hicieron y la que esto verifica. */
|
|
234
|
+
export const AUTHORITY_SCOPE = [
|
|
235
|
+
'CLAUDE.md',
|
|
236
|
+
'README.md',
|
|
237
|
+
'PROJECT.md',
|
|
238
|
+
'docs/PROGRAMMING_NORMS.md',
|
|
239
|
+
'docs/CI_PIPELINE.md',
|
|
240
|
+
'lefthook.yml',
|
|
241
|
+
'package.json',
|
|
242
|
+
/* mas .github/workflows/*.yml, que el script expande del disco. */
|
|
243
|
+
];
|
|
244
|
+
export function renderCitationReport(r) {
|
|
245
|
+
const out = [];
|
|
246
|
+
out.push('doc-citations [compuerta]: ' + r.authority_files + ' archivos de autoridad, '
|
|
247
|
+
+ r.authority_checked + ' citas verificadas'
|
|
248
|
+
+ (r.allowed ? ', ' + r.allowed + ' permitidas por declaracion' : '')
|
|
249
|
+
+ ', ' + r.violations.length + ' a la nada.');
|
|
250
|
+
out.push('doc-citations [relevamiento, NO bloquea]: ' + r.survey_docs
|
|
251
|
+
+ ' documentos vigentes (' + r.survey_skipped_historical + ' historicos salteados), '
|
|
252
|
+
+ r.survey_checked + ' citas, ' + r.survey_dead + ' sin archivo en disco.');
|
|
253
|
+
out.push(' El relevamiento no bloquea porque este repositorio PRESCRIBE rutas para otros');
|
|
254
|
+
out.push(' proyectos (docs/SQ.md exige docs/USER_MANUAL.md al adoptante), asi que una ruta');
|
|
255
|
+
out.push(' sin archivo no es por si misma un defecto. El numero esta a la vista para que');
|
|
256
|
+
out.push(' nadie lo descubra midiendo de nuevo.');
|
|
257
|
+
if (!r.violations.length)
|
|
258
|
+
return out.join('\n');
|
|
259
|
+
out.push('');
|
|
260
|
+
out.push('CITAS A LA NADA EN EL ALCANCE QUE BLOQUEA (' + r.violations.length + '):');
|
|
261
|
+
for (const v of r.violations) {
|
|
262
|
+
out.push(' ' + v.doc + ':' + v.line + ' -> ' + v.target
|
|
263
|
+
+ (v.shape === 'name' ? ' (no existe con ese nombre en ninguna parte)' : ' (no existe)'));
|
|
264
|
+
}
|
|
265
|
+
out.push('');
|
|
266
|
+
out.push('Un documento que afirma un archivo que no existe es peor que uno que falta:');
|
|
267
|
+
out.push('la ausencia se nota, la afirmacion falsa no. Arregla la cita, crea el archivo,');
|
|
268
|
+
out.push('o declara la excepcion con su motivo en docs/.doc-citations-allow.');
|
|
269
|
+
return out.join('\n');
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=doc_citations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doc_citations.js","sourceRoot":"","sources":["../../src/core/doc_citations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export declare const HOOK_BUDGET_REL = ".forge/hook-budget.json";
|
|
2
|
+
/** Aviso. Medido: la serie ya toco 32,0 / 39,2 / 38,7, asi que esto habla. */
|
|
3
|
+
export declare const WARN_MS = 30000;
|
|
4
|
+
/** Techo declarado por el dueno. Cruzarlo es una decision. */
|
|
5
|
+
export declare const CEILING_MS = 35000;
|
|
6
|
+
/** Cuantas corridas se guardan. Alcanza para ver la tendencia sin que el
|
|
7
|
+
* archivo crezca: lo que decide el rojo son las dos ultimas. */
|
|
8
|
+
export declare const HISTORY_MAX = 10;
|
|
9
|
+
export interface HookRun {
|
|
10
|
+
ended_at: number;
|
|
11
|
+
duration_ms: number;
|
|
12
|
+
/** Para saber si la corrida fue el paquete entero o una parte. */
|
|
13
|
+
commands?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface HookBudgetFile {
|
|
16
|
+
version: 1;
|
|
17
|
+
/** Marca de `--start`. Se borra al medir: una marca vieja no es una
|
|
18
|
+
* medicion, y dejarla permitiria leer como duracion el tiempo entre dos
|
|
19
|
+
* corridas distintas. */
|
|
20
|
+
started_at?: number;
|
|
21
|
+
history: HookRun[];
|
|
22
|
+
}
|
|
23
|
+
export type BudgetLevel = 'ok' | 'warn' | 'over';
|
|
24
|
+
export interface BudgetVerdict {
|
|
25
|
+
level: BudgetLevel;
|
|
26
|
+
duration_ms: number;
|
|
27
|
+
/** Rojo del gancho. Solo con DOS corridas seguidas arriba del techo. */
|
|
28
|
+
blocked: boolean;
|
|
29
|
+
warn_ms: number;
|
|
30
|
+
ceiling_ms: number;
|
|
31
|
+
/** La corrida anterior, cuando hay, para explicar el veredicto. */
|
|
32
|
+
previous_ms?: number;
|
|
33
|
+
}
|
|
34
|
+
export declare function emptyBudgetFile(): HookBudgetFile;
|
|
35
|
+
export declare function readBudgetFile(repo: string): HookBudgetFile;
|
|
36
|
+
export declare function writeBudgetFile(repo: string, data: HookBudgetFile): void;
|
|
37
|
+
/** `--start`: deja la marca y NO toca el historial. */
|
|
38
|
+
export declare function startRun(prev: HookBudgetFile, now: number): HookBudgetFile;
|
|
39
|
+
/**
|
|
40
|
+
* El veredicto, puro: duracion contra los dos umbrales, y el rojo solo
|
|
41
|
+
* cuando la corrida ANTERIOR tambien cruzo el techo.
|
|
42
|
+
*/
|
|
43
|
+
export declare function judgeBudget(duration_ms: number, history: HookRun[], limits?: {
|
|
44
|
+
warn_ms?: number;
|
|
45
|
+
ceiling_ms?: number;
|
|
46
|
+
}): BudgetVerdict;
|
|
47
|
+
/** `--check`: mide, guarda la corrida y devuelve el veredicto. */
|
|
48
|
+
export declare function finishRun(prev: HookBudgetFile, now: number, limits?: {
|
|
49
|
+
warn_ms?: number;
|
|
50
|
+
ceiling_ms?: number;
|
|
51
|
+
commands?: number;
|
|
52
|
+
}): {
|
|
53
|
+
file: HookBudgetFile;
|
|
54
|
+
verdict: BudgetVerdict;
|
|
55
|
+
} | {
|
|
56
|
+
file: HookBudgetFile;
|
|
57
|
+
verdict: null;
|
|
58
|
+
};
|
|
59
|
+
export declare function renderBudget(verdict: BudgetVerdict): string[];
|
|
60
|
+
//# sourceMappingURL=hook_budget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook_budget.d.ts","sourceRoot":"","sources":["../../src/core/hook_budget.ts"],"names":[],"mappings":"AA8CA,eAAO,MAAM,eAAe,4BAA4B,CAAC;AAEzD,8EAA8E;AAC9E,eAAO,MAAM,OAAO,QAAS,CAAC;AAC9B,8DAA8D;AAC9D,eAAO,MAAM,UAAU,QAAS,CAAC;AACjC;iEACiE;AACjE,eAAO,MAAM,WAAW,KAAK,CAAC;AAE9B,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,CAAC,CAAC;IACX;;8BAE0B;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,EAAE,CAAC;CACpB;AAED,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,WAAW,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,eAAe,IAAI,cAAc,CAEhD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAuB3D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAIxE;AAED,uDAAuD;AACvD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,CAE1E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,OAAO,EAAE,EAClB,MAAM,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACrD,aAAa,CAef;AAED,kEAAkE;AAClE,wBAAgB,SAAS,CACvB,IAAI,EAAE,cAAc,EACpB,GAAG,EAAE,MAAM,EACX,MAAM,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GACxE;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,aAAa,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,IAAI,CAAA;CAAE,CAY5F;AAID,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,EAAE,CAmC7D"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EL PRESUPUESTO DEL GANCHO -- 35 s de techo, aviso al pasar de 30 (F-15,
|
|
3
|
+
* decision del dueno 2026-11-01, PROMPT_FIX_FORGE_CIERRE_4).
|
|
4
|
+
*
|
|
5
|
+
* POR QUE UN PRESUPUESTO Y NO UN NUMERO APROBADO. El precio del paquete
|
|
6
|
+
* pre-push se midio ocho veces en una sola jornada y la serie fue
|
|
7
|
+
* 20,8 / 25,1 / 25,8 / 29,6 / 32,0 / 39,2 / 38,7 / 30,5 s. Lo que la mueve
|
|
8
|
+
* es `build`, que crece con el codigo, asi que aprobar "32" seria aprobar
|
|
9
|
+
* un numero que ya se sabe que va a volver a subir. El dueno fijo el techo
|
|
10
|
+
* en su lugar: cruzar los 35 s tiene que ser una DECISION y no una deriva.
|
|
11
|
+
*
|
|
12
|
+
* Y la serie le dio la razon el mismo dia: las dos primeras lecturas del
|
|
13
|
+
* instrumento (39,2 y 38,7 s) cruzaron el techo. Las dos salieron minutos
|
|
14
|
+
* despues de una bateria de 6 min, con la maquina caliente; la tercera, ya
|
|
15
|
+
* libre, dio 30,5 s. Es el caso exacto para el que el rojo pide DOS
|
|
16
|
+
* corridas seguidas y no una.
|
|
17
|
+
*
|
|
18
|
+
* COMO SE MIDE. `scripts/hook_budget.mjs --start` es el PRIMER comando del
|
|
19
|
+
* pre-push y deja la marca de arranque; `--check` es el ULTIMO y mide lo
|
|
20
|
+
* que paso entre las dos. Es el precio del gancho COMPLETO -- la suma de
|
|
21
|
+
* las piezas ya se probo que miente por abajo (las piezas se midieron en
|
|
22
|
+
* 24,8 s y la corrida real dio 32,0, y despues 39,2). Y el sobrecosto de
|
|
23
|
+
* lefthook no es la explicacion: son 0,4 s sobre los diez comandos. Lo que
|
|
24
|
+
* separa la suma de la corrida es `build` bajo carga -- 21,3 s suelto y
|
|
25
|
+
* 26,3 s en la corrida completa, el mismo arbol, un minuto de diferencia.
|
|
26
|
+
*
|
|
27
|
+
* POR QUE EL ROJO PIDE DOS CORRIDAS SEGUIDAS Y NO UNA. `build` vario de
|
|
28
|
+
* 18,1 a 24,6 s en la misma maquina sin que cambiara una linea: lo mueve la
|
|
29
|
+
* carga. Un rojo por un pico aislado seria un falso rojo, y un gancho que
|
|
30
|
+
* tira falsos rojos se desactiva -- que es exactamente el dano que este
|
|
31
|
+
* paquete existe para no causar (un gancho desactivado figura como
|
|
32
|
+
* existente). Dos corridas consecutivas arriba del techo ya no son un pico:
|
|
33
|
+
* son el estado de la maquina, y ahi el cruce es la decision que el dueno
|
|
34
|
+
* pidio que se tome a mano.
|
|
35
|
+
*
|
|
36
|
+
* LO QUE ESTE ARCHIVO NO DECIDE. La salida de fondo -- que `hito4-lint` y
|
|
37
|
+
* `brain-matrix-gate` lean `src/` en vez de `dist/` para que `build` salga
|
|
38
|
+
* del gancho y el paquete baje a unos 8 s -- queda registrada como
|
|
39
|
+
* pendiente. Si eso se hace, el techo deja de ser un problema de raiz
|
|
40
|
+
* porque lo que crece es la compilacion, no las compuertas.
|
|
41
|
+
*
|
|
42
|
+
* ASCII-only.
|
|
43
|
+
*/
|
|
44
|
+
import fs from 'node:fs';
|
|
45
|
+
import path from 'node:path';
|
|
46
|
+
export const HOOK_BUDGET_REL = '.forge/hook-budget.json';
|
|
47
|
+
/** Aviso. Medido: la serie ya toco 32,0 / 39,2 / 38,7, asi que esto habla. */
|
|
48
|
+
export const WARN_MS = 30_000;
|
|
49
|
+
/** Techo declarado por el dueno. Cruzarlo es una decision. */
|
|
50
|
+
export const CEILING_MS = 35_000;
|
|
51
|
+
/** Cuantas corridas se guardan. Alcanza para ver la tendencia sin que el
|
|
52
|
+
* archivo crezca: lo que decide el rojo son las dos ultimas. */
|
|
53
|
+
export const HISTORY_MAX = 10;
|
|
54
|
+
export function emptyBudgetFile() {
|
|
55
|
+
return { version: 1, history: [] };
|
|
56
|
+
}
|
|
57
|
+
export function readBudgetFile(repo) {
|
|
58
|
+
const file = path.join(repo, HOOK_BUDGET_REL);
|
|
59
|
+
let raw;
|
|
60
|
+
try {
|
|
61
|
+
raw = fs.readFileSync(file, 'utf8');
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return emptyBudgetFile();
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const parsed = JSON.parse(raw);
|
|
68
|
+
const history = Array.isArray(parsed.history) ? parsed.history : [];
|
|
69
|
+
return {
|
|
70
|
+
version: 1,
|
|
71
|
+
started_at: typeof parsed.started_at === 'number' ? parsed.started_at : undefined,
|
|
72
|
+
history: history.filter((r) => !!r && typeof r.duration_ms === 'number' && typeof r.ended_at === 'number'),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
/* Un archivo ilegible se reporta como ausente y no tira: el presupuesto
|
|
77
|
+
* no puede ser el motivo de que un push no se pueda hacer. */
|
|
78
|
+
return emptyBudgetFile();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export function writeBudgetFile(repo, data) {
|
|
82
|
+
const file = path.join(repo, HOOK_BUDGET_REL);
|
|
83
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
84
|
+
fs.writeFileSync(file, JSON.stringify(data, null, 2) + '\n', 'utf8');
|
|
85
|
+
}
|
|
86
|
+
/** `--start`: deja la marca y NO toca el historial. */
|
|
87
|
+
export function startRun(prev, now) {
|
|
88
|
+
return { version: 1, started_at: now, history: prev.history.slice(0, HISTORY_MAX) };
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* El veredicto, puro: duracion contra los dos umbrales, y el rojo solo
|
|
92
|
+
* cuando la corrida ANTERIOR tambien cruzo el techo.
|
|
93
|
+
*/
|
|
94
|
+
export function judgeBudget(duration_ms, history, limits = {}) {
|
|
95
|
+
const warn_ms = limits.warn_ms ?? WARN_MS;
|
|
96
|
+
const ceiling_ms = limits.ceiling_ms ?? CEILING_MS;
|
|
97
|
+
const previous = history.length ? history[history.length - 1] : undefined;
|
|
98
|
+
const level = duration_ms > ceiling_ms ? 'over' : duration_ms > warn_ms ? 'warn' : 'ok';
|
|
99
|
+
const blocked = level === 'over' && !!previous && previous.duration_ms > ceiling_ms;
|
|
100
|
+
return {
|
|
101
|
+
level,
|
|
102
|
+
duration_ms,
|
|
103
|
+
blocked,
|
|
104
|
+
warn_ms,
|
|
105
|
+
ceiling_ms,
|
|
106
|
+
previous_ms: previous?.duration_ms,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/** `--check`: mide, guarda la corrida y devuelve el veredicto. */
|
|
110
|
+
export function finishRun(prev, now, limits = {}) {
|
|
111
|
+
if (typeof prev.started_at !== 'number') {
|
|
112
|
+
/* Sin marca de arranque no hay nada que medir. Se dice y no se inventa:
|
|
113
|
+
* una medicion imposible no se reporta como "entro en el presupuesto". */
|
|
114
|
+
return { file: prev, verdict: null };
|
|
115
|
+
}
|
|
116
|
+
const duration_ms = Math.max(0, now - prev.started_at);
|
|
117
|
+
const verdict = judgeBudget(duration_ms, prev.history, limits);
|
|
118
|
+
const run = { ended_at: now, duration_ms };
|
|
119
|
+
if (typeof limits.commands === 'number')
|
|
120
|
+
run.commands = limits.commands;
|
|
121
|
+
const history = [...prev.history, run].slice(-HISTORY_MAX);
|
|
122
|
+
return { file: { version: 1, history }, verdict };
|
|
123
|
+
}
|
|
124
|
+
const secs = (ms) => (ms / 1000).toFixed(1).replace('.', ',') + ' s';
|
|
125
|
+
export function renderBudget(verdict) {
|
|
126
|
+
const lines = [];
|
|
127
|
+
const head = 'hook-budget: el paquete pre-push tardo ' + secs(verdict.duration_ms)
|
|
128
|
+
+ ' (aviso ' + secs(verdict.warn_ms) + ', techo ' + secs(verdict.ceiling_ms) + ').';
|
|
129
|
+
lines.push(head);
|
|
130
|
+
if (verdict.level === 'ok')
|
|
131
|
+
return lines;
|
|
132
|
+
if (verdict.level === 'warn') {
|
|
133
|
+
lines.push('AVISO: paso del aviso y no del techo. Lo que mueve el numero es'
|
|
134
|
+
+ ' `build`, que crece con el codigo.');
|
|
135
|
+
lines.push('La salida de fondo esta registrada: si hito4-lint y'
|
|
136
|
+
+ ' brain-matrix-gate leen src/ en vez de dist/, `build` sale del gancho.');
|
|
137
|
+
return lines;
|
|
138
|
+
}
|
|
139
|
+
lines.push('TECHO CRUZADO: ' + secs(verdict.duration_ms) + ' > '
|
|
140
|
+
+ secs(verdict.ceiling_ms) + '. Cruzar el techo es una DECISION, no una deriva.');
|
|
141
|
+
if (verdict.previous_ms !== undefined) {
|
|
142
|
+
lines.push('Corrida anterior: ' + secs(verdict.previous_ms) + '.');
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
lines.push('Corrida anterior: no hay registro.');
|
|
146
|
+
}
|
|
147
|
+
if (!verdict.blocked) {
|
|
148
|
+
lines.push('No bloquea TODAVIA: una sola corrida arriba del techo puede ser'
|
|
149
|
+
+ ' carga de la maquina (build vario 18,1 a 24,6 s sin cambiar una linea).');
|
|
150
|
+
lines.push('Si la proxima tambien cruza, el gancho sale rojo y hay que'
|
|
151
|
+
+ ' decidir: sacar `build` del paquete, o subir el techo en lefthook.yml'
|
|
152
|
+
+ ' y escribir por que.');
|
|
153
|
+
return lines;
|
|
154
|
+
}
|
|
155
|
+
lines.push('DOS CORRIDAS SEGUIDAS arriba del techo: ya no es un pico, es el'
|
|
156
|
+
+ ' estado. El gancho sale rojo a proposito.');
|
|
157
|
+
lines.push('Las dos salidas, las dos a mano: (1) sacar `build` del pre-push'
|
|
158
|
+
+ ' haciendo que hito4-lint y brain-matrix-gate lean src/; (2) subir'
|
|
159
|
+
+ ' CEILING_MS en src/core/hook_budget.ts y declarar el motivo en'
|
|
160
|
+
+ ' lefthook.yml.');
|
|
161
|
+
return lines;
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=hook_budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook_budget.js","sourceRoot":"","sources":["../../src/core/hook_budget.ts"],"names":[],"mappings":"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"}
|