@andresmassello/uscha 1.40.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/LICENSE +21 -0
- package/README.md +104 -0
- package/bin/README.md +6 -0
- package/bin/uscha.js +28 -0
- package/package.json +38 -0
- package/uscha-kit/.claude/skills/uscha-adr-refine/SKILL.md +161 -0
- package/uscha-kit/.claude/skills/uscha-characterize/SKILL.md +124 -0
- package/uscha-kit/.claude/skills/uscha-devloop/SKILL.md +490 -0
- package/uscha-kit/.claude/skills/uscha-devloop/qa_ledger.py +5602 -0
- package/uscha-kit/.claude/skills/uscha-discovery/SKILL.md +161 -0
- package/uscha-kit/.claude/skills/uscha-mirador/SKILL.md +145 -0
- package/uscha-kit/.claude/skills/uscha-mirador/mirador-render.py +112 -0
- package/uscha-kit/.claude/skills/uscha-mirador/mirador-watch.ps1 +22 -0
- package/uscha-kit/.claude/skills/uscha-mirador/mirador-watch.sh +26 -0
- package/uscha-kit/.claude/skills/uscha-mirador/mirador.template.html +586 -0
- package/uscha-kit/.claude/skills/uscha-mirador/telemetry-extract.py +130 -0
- package/uscha-kit/.claude/skills/uscha-reverse-discovery/SKILL.md +116 -0
- package/uscha-kit/.claude/skills/uscha-rubric/SKILL.md +79 -0
- package/uscha-kit/.claude/skills/uscha-sysdoc/SKILL.md +88 -0
- package/uscha-kit/.claude-plugin/plugin.json +24 -0
- package/uscha-kit/.codex-plugin/plugin.json +37 -0
- package/uscha-kit/CHANGELOG-1.10.0.md +84 -0
- package/uscha-kit/CHANGELOG-1.11.0.md +67 -0
- package/uscha-kit/CHANGELOG-1.12.0.md +46 -0
- package/uscha-kit/CHANGELOG-1.13.0.md +33 -0
- package/uscha-kit/CHANGELOG-1.14.0.md +42 -0
- package/uscha-kit/CHANGELOG-1.15.0.md +58 -0
- package/uscha-kit/CHANGELOG-1.16.0.md +55 -0
- package/uscha-kit/CHANGELOG-1.17.0.md +44 -0
- package/uscha-kit/CHANGELOG-1.18.0.md +42 -0
- package/uscha-kit/CHANGELOG-1.19.0.md +41 -0
- package/uscha-kit/CHANGELOG-1.2.2.md +16 -0
- package/uscha-kit/CHANGELOG-1.2.3.md +20 -0
- package/uscha-kit/CHANGELOG-1.2.4.md +10 -0
- package/uscha-kit/CHANGELOG-1.2.5.md +23 -0
- package/uscha-kit/CHANGELOG-1.2.6.md +11 -0
- package/uscha-kit/CHANGELOG-1.2.7.md +15 -0
- package/uscha-kit/CHANGELOG-1.2.8.md +24 -0
- package/uscha-kit/CHANGELOG-1.2.9.md +4 -0
- package/uscha-kit/CHANGELOG-1.20.0.md +29 -0
- package/uscha-kit/CHANGELOG-1.21.0.md +33 -0
- package/uscha-kit/CHANGELOG-1.22.0.md +60 -0
- package/uscha-kit/CHANGELOG-1.23.0.md +75 -0
- package/uscha-kit/CHANGELOG-1.24.0.md +50 -0
- package/uscha-kit/CHANGELOG-1.25.0.md +55 -0
- package/uscha-kit/CHANGELOG-1.26.0.md +70 -0
- package/uscha-kit/CHANGELOG-1.27.0.md +45 -0
- package/uscha-kit/CHANGELOG-1.28.0.md +35 -0
- package/uscha-kit/CHANGELOG-1.29.0.md +20 -0
- package/uscha-kit/CHANGELOG-1.3.0.md +74 -0
- package/uscha-kit/CHANGELOG-1.30.0.md +46 -0
- package/uscha-kit/CHANGELOG-1.31.0.md +59 -0
- package/uscha-kit/CHANGELOG-1.32.0.md +50 -0
- package/uscha-kit/CHANGELOG-1.33.0.md +46 -0
- package/uscha-kit/CHANGELOG-1.34.0.md +55 -0
- package/uscha-kit/CHANGELOG-1.35.0.md +30 -0
- package/uscha-kit/CHANGELOG-1.36.0.md +33 -0
- package/uscha-kit/CHANGELOG-1.37.0.md +41 -0
- package/uscha-kit/CHANGELOG-1.38.0.md +11 -0
- package/uscha-kit/CHANGELOG-1.39.0.md +14 -0
- package/uscha-kit/CHANGELOG-1.4.0.md +68 -0
- package/uscha-kit/CHANGELOG-1.40.0.md +16 -0
- package/uscha-kit/CHANGELOG-1.40.1.md +11 -0
- package/uscha-kit/CHANGELOG-1.5.0.md +64 -0
- package/uscha-kit/CHANGELOG-1.6.0.md +57 -0
- package/uscha-kit/CHANGELOG-1.7.0.md +74 -0
- package/uscha-kit/CHANGELOG-1.8.0.md +46 -0
- package/uscha-kit/CHANGELOG-1.9.0.md +112 -0
- package/uscha-kit/LICENSE +21 -0
- package/uscha-kit/README.md +497 -0
- package/uscha-kit/VERSION +1 -0
- package/uscha-kit/WORKBENCH.md +178 -0
- package/uscha-kit/hooks/block-approved-writes.ps1 +46 -0
- package/uscha-kit/hooks/hooks.json +15 -0
- package/uscha-kit/install-uscha.py +344 -0
- package/uscha-kit/skills/uscha-adr-refine/SKILL.md +161 -0
- package/uscha-kit/skills/uscha-characterize/SKILL.md +124 -0
- package/uscha-kit/skills/uscha-devloop/SKILL.md +490 -0
- package/uscha-kit/skills/uscha-devloop/qa_ledger.py +5602 -0
- package/uscha-kit/skills/uscha-discovery/SKILL.md +161 -0
- package/uscha-kit/skills/uscha-mirador/SKILL.md +145 -0
- package/uscha-kit/skills/uscha-mirador/mirador-render.py +112 -0
- package/uscha-kit/skills/uscha-mirador/mirador-watch.ps1 +22 -0
- package/uscha-kit/skills/uscha-mirador/mirador-watch.sh +26 -0
- package/uscha-kit/skills/uscha-mirador/mirador.template.html +586 -0
- package/uscha-kit/skills/uscha-mirador/telemetry-extract.py +130 -0
- package/uscha-kit/skills/uscha-reverse-discovery/SKILL.md +116 -0
- package/uscha-kit/skills/uscha-rubric/SKILL.md +79 -0
- package/uscha-kit/skills/uscha-sysdoc/SKILL.md +88 -0
- package/uscha-kit/templates/.gitattributes +6 -0
- package/uscha-kit/templates/CLAUDE.md +56 -0
- package/uscha-kit/templates/CONSTITUTION.md +149 -0
- package/uscha-kit/templates/RUBRIC.md +38 -0
- package/uscha-kit/templates/docs/adr/README.md +19 -0
- package/uscha-kit/templates/rubric-grader-prompt.md +63 -0
- package/uscha-kit/tests/smoke-engine.sh +1739 -0
- package/uscha-kit/uscha.config.json +181 -0
- package/uscha-kit/workbench-doctor.sh +45 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# dev-loop-kit 1.12.0 — secret-scan en gate-check (2026-07-03)
|
|
2
|
+
|
|
3
|
+
Tercera mejora del backlog PragProg (M8 de `docs/analisis-pragmatic-programmer.md`;
|
|
4
|
+
Topic 43 *"Stay Safe Out There — nunca commitear secretos, API keys ni
|
|
5
|
+
credenciales"*). Un secreto agregado al diff bloquea como HECHO, exactamente
|
|
6
|
+
igual que hoy bloquea borrar tests o bajar thresholds. Python stdlib puro.
|
|
7
|
+
Smoke suite: 79/79.
|
|
8
|
+
|
|
9
|
+
## La idea (facts block, guesses advise — aplicado a secretos)
|
|
10
|
+
|
|
11
|
+
- **Alta precisión = BLOCKER**: clave privada PEM, AWS access key (`AKIA…`),
|
|
12
|
+
GitHub token (`ghp_`/`github_pat_`), Slack (`xox?-`), Google API key
|
|
13
|
+
(`AIza…`), y archivos contenedores de claves (`.p12/.pfx/.jks/.keystore/.key`)
|
|
14
|
+
agregados o modificados — también en modo binario (línea `Binary files`,
|
|
15
|
+
que no trae `+++`).
|
|
16
|
+
- **Genérico = advisory**: literales tipo `password = "…"` y JWTs — en
|
|
17
|
+
fixtures de test abundan placeholders y bloquearlos castigaría escribir
|
|
18
|
+
tests. `--strict` los gatea.
|
|
19
|
+
- Solo se escanean líneas **agregadas**: sacar un secreto del código es bueno
|
|
20
|
+
y el diff que lo saca no debe frenarse. Borrar un `.p12` tampoco bloquea
|
|
21
|
+
(el lado `b/` del diff es `/dev/null` y no matchea).
|
|
22
|
+
|
|
23
|
+
## Engine (qa_ledger.py)
|
|
24
|
+
|
|
25
|
+
- `_GC_SECRETS_HARD` (lista etiquetada de patrones) + `_GC_SECRET_SOFT` +
|
|
26
|
+
`_GC_KEYFILE`, cableados al loop de `cmd_gate_check`: `secrets_added` suma
|
|
27
|
+
al veredicto hard, `secret_literals` al soft. JSON expone ambos.
|
|
28
|
+
- Los patrones no se auto-matchean como source (verificado): después de
|
|
29
|
+
`-----BEGIN ` en el código viene `(?:RSA`, no `PRIVATE KEY`.
|
|
30
|
+
- Límite conocido (corner self-hosting): los fixtures del smoke contienen la
|
|
31
|
+
AKIA de ejemplo canónica de AWS — un gate-check del diff del PROPIO kit
|
|
32
|
+
la flaggea. Correcto: el gate no exime archivos de test a propósito
|
|
33
|
+
(un secreto en un test sigue siendo un secreto).
|
|
34
|
+
|
|
35
|
+
## Smoke
|
|
36
|
+
|
|
37
|
+
- **T34**: AKIA agregada → BLOCKER · PEM privado → BLOCKER · `.p12` binario
|
|
38
|
+
agregado → BLOCKER · borrado de `.p12` → CLEAN · literal password →
|
|
39
|
+
REVIEW exit 0 / `--strict` exit 1.
|
|
40
|
+
|
|
41
|
+
## Diferido consciente
|
|
42
|
+
|
|
43
|
+
- Entropía/base64 genérico (detectores adivinos) NO entra: violaría
|
|
44
|
+
"facts block, guesses advise" — solo patrones con lectura inequívoca
|
|
45
|
+
bloquean. El resto del backlog PragProg sigue en
|
|
46
|
+
`docs/analisis-pragmatic-programmer.md`.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# dev-loop-kit 1.13.0 — ledger atómico: checksum de integridad (2026-07-03)
|
|
2
|
+
|
|
3
|
+
Cuarta mejora del backlog PragProg (M3 de `docs/analisis-pragmatic-programmer.md`;
|
|
4
|
+
Topic 34 *"los recursos compartidos mutables incluyen ARCHIVOS"*). Todo el
|
|
5
|
+
edificio "measured beats narrated" se apoya en `QA-LEDGER.json` — y hasta hoy
|
|
6
|
+
ese JSON podía corromperse o mutarse en silencio. Smoke suite: 85/85.
|
|
7
|
+
|
|
8
|
+
## La idea
|
|
9
|
+
|
|
10
|
+
- La **escritura ya era atómica** (write-temp + `os.replace`, desde antes) —
|
|
11
|
+
lo que faltaba era el otro lado: detectar al CARGAR que el archivo quedó
|
|
12
|
+
inconsistente.
|
|
13
|
+
- `_save` ahora escribe un campo `integrity` con **sha256 canónico** del
|
|
14
|
+
contenido (claves ordenadas — el hash no depende del orden del dict).
|
|
15
|
+
- `_load` **verifica** el checksum cuando el campo existe: una mutación externa
|
|
16
|
+
(edición a mano, merge accidental) o una escritura parcial **bloquea** con
|
|
17
|
+
mensaje de recuperación (`git checkout -- QA-LEDGER.json`). Aceptar una
|
|
18
|
+
edición externa deliberada = borrar el campo `integrity` (acto humano
|
|
19
|
+
explícito, mismo espíritu que INV-GOLDEN-01).
|
|
20
|
+
- JSON corrupto/truncado = hecho bloqueante con mensaje claro, **no un
|
|
21
|
+
traceback crudo**.
|
|
22
|
+
- **Legacy**: ledgers pre-1.13.0 sin `integrity` cargan sin verificar
|
|
23
|
+
(adopción incremental, no rotura retroactiva). `init` re-inicializa sobre
|
|
24
|
+
un ledger corrupto sin leerlo.
|
|
25
|
+
|
|
26
|
+
## Diferido consciente
|
|
27
|
+
|
|
28
|
+
- File-lock inter-proceso (la parte "opcional" de M3): omitido — stdlib
|
|
29
|
+
portable Windows/Linux no lo da barato (`fcntl` no existe en Windows) y el
|
|
30
|
+
loop es single-writer por diseño. Si aparece un caso real de escritura
|
|
31
|
+
concurrente, se re-evalúa.
|
|
32
|
+
- El baseline de `rebuild` (artefacto aparte) no lleva checksum — mismo
|
|
33
|
+
candidato si el rebuild gana peso.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# dev-loop-kit 1.14.0 — plateau y stop-signal en readiness (2026-07-03)
|
|
2
|
+
|
|
3
|
+
Quinta mejora del backlog PragProg (M6 de `docs/analisis-pragmatic-programmer.md`;
|
|
4
|
+
Topic 37 *"Listen to Your Lizard Brain"* + Topic 5 *"Know When to Stop"*).
|
|
5
|
+
La convergencia per-tool existía, pero el engine nunca decía las dos cosas que
|
|
6
|
+
un senior sí dice: "esto no está convergiendo — el problema es de diseño" y
|
|
7
|
+
"esto ya está — cortá". **ADVISORY puro: recomienda, jamás gatea.**
|
|
8
|
+
Smoke suite: 89/89.
|
|
9
|
+
|
|
10
|
+
## La idea
|
|
11
|
+
|
|
12
|
+
- **stall-check**: findings gateados por CICLO de agente (suma sobre las tools
|
|
13
|
+
del ciclo). Si los últimos 3 ciclos muestran la serie plana o SUBIENDO — y
|
|
14
|
+
todavía hay findings — iterar más no está acercando la solución: el engine
|
|
15
|
+
deja de sugerir implícitamente "seguí iterando" y recomienda **volver a
|
|
16
|
+
ADR / re-planear con el humano**. Una serie bajando es progreso y no dispara.
|
|
17
|
+
Con `qa_tools_order` configurado solo cuentan ciclos **COMPLETOS** (todas las
|
|
18
|
+
tools logueadas) — un ciclo a medio correr suma parcial y podría enmascarar
|
|
19
|
+
o inventar el stall (hallazgo del review fresco, aplicado).
|
|
20
|
+
- **stop-signal**: todos los repos convergieron, cero caps activos y cero
|
|
21
|
+
findings gateados abiertos — no queda ningún fact bloqueante. Lo que falte
|
|
22
|
+
es deuda medible (coverage/acceptance), no findings: **candidato a cortar e
|
|
23
|
+
ir a PR**, decisión del humano.
|
|
24
|
+
|
|
25
|
+
## Engine (qa_ledger.py)
|
|
26
|
+
|
|
27
|
+
- `_stall_series()` / `_is_stalled()` (ventana `STALL_WINDOW = 3`, constante:
|
|
28
|
+
es un advisory, no un gate parametrizable — cf. tensión ETC/M5, deliberado).
|
|
29
|
+
- `readiness`: JSON expone `advice: {stalled_repos, stop_signal}`; el texto
|
|
30
|
+
imprime ambos avisos marcados "(advisory)".
|
|
31
|
+
|
|
32
|
+
## Smoke
|
|
33
|
+
|
|
34
|
+
- **T36**: serie 4→5→6 dispara stall · un ciclo 4 PARCIAL no contamina la
|
|
35
|
+
serie · serie 5→3→1 (progreso) NO dispara · repo único convergido con cero
|
|
36
|
+
facts bloqueantes emite `stop_signal: true`.
|
|
37
|
+
|
|
38
|
+
## Diferido consciente
|
|
39
|
+
|
|
40
|
+
- El stall mide findings gateados por ciclo, no el score de readiness
|
|
41
|
+
persistido por iteración (el ledger no guarda score histórico — si algún
|
|
42
|
+
día lo guarda, el detector puede leer el KPI directo).
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# dev-loop-kit 1.15.0 — scrub del golden master (2026-07-03)
|
|
2
|
+
|
|
3
|
+
Sexta mejora del backlog PragProg (M7 de `docs/analisis-pragmatic-programmer.md`;
|
|
4
|
+
Topic 41 *"no apoyar tests en cosas no confiables"* — timestamps exactos,
|
|
5
|
+
ids, posiciones absolutas). Sin esto, cualquier salida del código original con
|
|
6
|
+
volátiles vuelve el golden master perma-rojo — y un golden perma-rojo mata la
|
|
7
|
+
credibilidad de todo el gate. Smoke suite: 97/97.
|
|
8
|
+
|
|
9
|
+
## La idea
|
|
10
|
+
|
|
11
|
+
- `golden.scrub.json` en el root de fixtures declara los volátiles:
|
|
12
|
+
`{"rules": [{"pattern": "<regex>", "replace": "<placeholder>"}]}`.
|
|
13
|
+
- `golden-diff` enmascara AMBOS lados (received y approved) antes de comparar —
|
|
14
|
+
solo texto; el binario sigue byte a byte. El match vía scrub se reporta
|
|
15
|
+
**APARTE** (`N via scrub` + conteo de sustituciones por regla): el masking
|
|
16
|
+
jamás es invisible.
|
|
17
|
+
- **Cadena de custodia**: las reglas se declaran en characterize (paso nuevo,
|
|
18
|
+
ANTES de la aprobación) y el humano las aprueba junto con los `.approved` —
|
|
19
|
+
son contrato. gate-check flaggea cualquier edición posterior a
|
|
20
|
+
`golden.scrub.json` como señal blanda SIEMPRE visible (`--strict` la gatea):
|
|
21
|
+
una regla ensanchada puede enmascarar divergencia real.
|
|
22
|
+
- Archivo de scrub inválido (JSON roto, regex rota) = **exit 2 explícito** —
|
|
23
|
+
el scrub nunca se saltea en silencio.
|
|
24
|
+
- Preferencia documentada: arreglar el determinismo EN LA FUENTE (checklist de
|
|
25
|
+
Phase 2 de characterize); el scrub es para lo que genuinamente no se controla.
|
|
26
|
+
|
|
27
|
+
## Engine (qa_ledger.py)
|
|
28
|
+
|
|
29
|
+
- `_load_scrub_rules()` / `_scrub()` + integración en `cmd_golden_diff`
|
|
30
|
+
(`matched_scrubbed`, `scrub_rules`, `scrub_substitutions` en el JSON —
|
|
31
|
+
el conteo es del lado RECEIVED; sumar ambos lados duplicaría cada volátil).
|
|
32
|
+
- gate-check: lista `scrub_rules_touched` (soft) en veredicto y JSON — cubre
|
|
33
|
+
agregar, modificar y BORRAR el archivo (borrar reglas también es editarlas).
|
|
34
|
+
- Shape estricta del archivo: top-level lista, key `rules` ausente o typo =
|
|
35
|
+
exit 2 — un error de forma no puede degradar a "cero reglas" en silencio.
|
|
36
|
+
|
|
37
|
+
## Hardening (review fresco pre-commit, 4 hallazgos aplicados)
|
|
38
|
+
|
|
39
|
+
- AttributeError cruda con lista top-level en el scrub file → exit 2 limpio.
|
|
40
|
+
- `{}` sin key `rules` cargaba cero reglas en silencio → exit 2.
|
|
41
|
+
- Doble conteo de sustituciones (received + approved al mismo dict) → solo
|
|
42
|
+
received.
|
|
43
|
+
- Borrado de `golden.scrub.json` no se flaggeaba (el check vivía solo en
|
|
44
|
+
líneas `+`) → también en `-`.
|
|
45
|
+
|
|
46
|
+
## Smoke
|
|
47
|
+
|
|
48
|
+
- **T37** — respetando INV-GOLDEN-01: crear un `.approved` es un acto HUMANO
|
|
49
|
+
incluso en tests, así que el path CLEAN-vía-scrub NO se auto-testea (misma
|
|
50
|
+
disciplina que el path CLEAN byte-a-byte desde 1.3.0). Se prueba la mecánica
|
|
51
|
+
a nivel función (enmascara, cuenta, binario intacto, divergencia real no se
|
|
52
|
+
tapa) + los paths CLI sin `.approved`: scrub no fabrica aprobación (DIVERGE
|
|
53
|
+
se mantiene), scrub inválido exit 2, gate-check flaggea ediciones.
|
|
54
|
+
|
|
55
|
+
## Diferido consciente
|
|
56
|
+
|
|
57
|
+
- Reglas por-fixture (hoy son por root de fixtures) — si un corpus real lo
|
|
58
|
+
pide, se agrega `"glob"` opcional por regla.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# dev-loop-kit 1.16.0 — regression-capture: Find Bugs Once (2026-07-03)
|
|
2
|
+
|
|
3
|
+
Séptima mejora del backlog PragProg (M1 de `docs/analisis-pragmatic-programmer.md`;
|
|
4
|
+
Topic 51 / Tip 94 *"Find Bugs Once"* + Tip 31 *"Failing Test Before Fixing
|
|
5
|
+
Code"*). Ataca el cierre narrado de findings: el agente reporta `fixed` y nadie
|
|
6
|
+
pregunta **qué test reproduce el bug que dice haber arreglado**.
|
|
7
|
+
Smoke suite: 106/106.
|
|
8
|
+
|
|
9
|
+
## La idea (measured beats narrated, ahora sobre el CIERRE)
|
|
10
|
+
|
|
11
|
+
- `regression-check --repo X [--fixed N] --diff/--from-git`: cruza los findings
|
|
12
|
+
cerrados con el diff que los arregla. Verdicts:
|
|
13
|
+
- **N/A** — nada cerrado, nada que exigir.
|
|
14
|
+
- **MEASURED** — el diff agrega/modifica líneas en el árbol de test
|
|
15
|
+
(clasificador compartido de los 9 stacks).
|
|
16
|
+
- **NARRATED** — desaparecieron findings sin tocar UN solo test. Aconseja
|
|
17
|
+
por default (exit 0 con warning); `--strict` gatea; `log-gate --kind
|
|
18
|
+
regression --verdict fail` lo persiste si el equipo decide bloquear.
|
|
19
|
+
- Sin `--fixed` explícito lee la suma de `fixed` de la iteración más reciente
|
|
20
|
+
del repo en el ledger — el dato ya estaba, ahora se interroga.
|
|
21
|
+
- **escape_analysis obligatoria**: resolver un `flag-blocker` ahora EXIGE
|
|
22
|
+
`--escape-analysis "<qué gate/test debió atraparlo y qué se hizo>"` —
|
|
23
|
+
la reflexión es parte del cierre, no opcional (cerrar un BLOCKER sin ella
|
|
24
|
+
es garantía de encontrarlo dos veces). Se persiste en el registro del gate.
|
|
25
|
+
|
|
26
|
+
## Decisiones de diseño (documentadas, no implícitas)
|
|
27
|
+
|
|
28
|
+
- La evidencia es a nivel **DIFF** y es mecánica: ¿el diff que arregla agrega
|
|
29
|
+
líneas NO VACÍAS en el árbol de test? — un hecho. El mapeo finding→test
|
|
30
|
+
específico sería adivinanza sin una convención de naming
|
|
31
|
+
(¿`test_regr_<fingerprint>`?): **diferido consciente**, el gate mide lo que
|
|
32
|
+
se puede medir sin inventar.
|
|
33
|
+
- **Límite disclosed (hallazgo del review fresco, aplicado)**: es un tripwire,
|
|
34
|
+
no un juez de calidad — una línea de comentario en un test file cuenta como
|
|
35
|
+
evidencia (juzgar contenido entre 9 lenguajes sería adivinanza). Mitigación
|
|
36
|
+
honesta: las líneas en blanco NO cuentan, y las señales
|
|
37
|
+
`has_test_definition`/`has_assertion` se exponen como hechos en el JSON —
|
|
38
|
+
un MEASURED sin ninguna de las dos imprime "evidencia DÉBIL" para el ojo
|
|
39
|
+
humano. La calidad de los tests la juzga pit-check (mutation testing), no
|
|
40
|
+
este gate.
|
|
41
|
+
- Advisory-first: NARRATED no bloquea por default — mismo patrón de adopción
|
|
42
|
+
incremental que acceptance trazable (1.10.0) y los advisories de 1.14.0.
|
|
43
|
+
|
|
44
|
+
## Skills
|
|
45
|
+
|
|
46
|
+
- `dev-loop`: tras loguear un pass con `--fixed > 0`, correr `regression-check`;
|
|
47
|
+
cierre NARRATED = escribir el test de regresión (el test que falla va ANTES
|
|
48
|
+
del fix).
|
|
49
|
+
|
|
50
|
+
## Smoke
|
|
51
|
+
|
|
52
|
+
- **T38**: fix sin tests → NARRATED (exit 0 advisory / `--strict` exit 1) ·
|
|
53
|
+
fix con test nuevo → MEASURED (pasa aun con `--strict`) · `--fixed 0` → N/A ·
|
|
54
|
+
lookup del `fixed` de la última iteración del ledger sin `--fixed`.
|
|
55
|
+
- **T4 endurecido**: resolver un blocker sin `--escape-analysis` → rechazado.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# dev-loop-kit 1.17.0 — procedencia visible de umbrales (2026-07-03)
|
|
2
|
+
|
|
3
|
+
Octava mejora del backlog PragProg (M5 de `docs/analisis-pragmatic-programmer.md`;
|
|
4
|
+
Tip 8 *"Make Quality a Requirements Issue"* + Topic 8 *"ETC es un valor, no una
|
|
5
|
+
regla"*). Resolución elegida por el humano entre tres opciones: **procedencia
|
|
6
|
+
visible** — ni fiel-al-libro (advisory por default hubiera desarmado el
|
|
7
|
+
anti-Goodhart) ni rechazo. Smoke suite: 111/111.
|
|
8
|
+
|
|
9
|
+
## La idea (el conteo es hecho · el umbral es opinión · salvo que lo declares)
|
|
10
|
+
|
|
11
|
+
- **Que el cap EXISTA es principio, no opinión**: "tests rojos ⇒ no estás
|
|
12
|
+
ready" es una definición. Los caps siguen mordiendo por default — nada se
|
|
13
|
+
afloja, ningún usuario existente ve su score subir en silencio.
|
|
14
|
+
- **El NÚMERO es opinión del kit SALVO que el humano lo declare.** El acto de
|
|
15
|
+
declaración ya existía: el `dev-loop.config.json` commiteado es humano-owned.
|
|
16
|
+
Valor explícito en `config.defaults` = requerimiento; fallback a la
|
|
17
|
+
constante del engine = default del kit. Cero schema nuevo.
|
|
18
|
+
- Lo que faltaba era la **etiqueta**: ahora cada umbral que muerde dice de
|
|
19
|
+
dónde vino.
|
|
20
|
+
|
|
21
|
+
## Engine (qa_ledger.py)
|
|
22
|
+
|
|
23
|
+
- `readiness`: el cap que muerde se etiqueta — `capped at 35: tests red —
|
|
24
|
+
umbral default del kit` vs `— umbral requerimiento (config)`. El threshold
|
|
25
|
+
de coverage se etiqueta en la línea resumen (`thr 60, declarado` /
|
|
26
|
+
`default del kit`). JSON expone `cap_source` y `thresholds_declared`.
|
|
27
|
+
- `simplicity-check`: los presupuestos declarados (config o CLI) llevan `*`
|
|
28
|
+
en la tabla; sin ninguno declarado imprime el aviso "todos los presupuestos
|
|
29
|
+
son defaults del kit — opinión, no requerimiento". JSON expone
|
|
30
|
+
`budgets_declared`.
|
|
31
|
+
|
|
32
|
+
## Skills
|
|
33
|
+
|
|
34
|
+
- `discovery`: paso 9 nuevo en la agenda — **quality bar**: "¿qué nivel de
|
|
35
|
+
calidad BASTA acá y qué dimensiones son negociables?" con propuesta acorde
|
|
36
|
+
al perfil de riesgo (un core de pagos no es un dashboard interno). Lo que el
|
|
37
|
+
humano declara va al config — declarar ES commitear el config.
|
|
38
|
+
|
|
39
|
+
## Smoke
|
|
40
|
+
|
|
41
|
+
- **T39**: cap declarado (`readiness_caps.tests_red` en config) → etiqueta
|
|
42
|
+
`requerimiento (config)` en JSON y texto · sandbox sin caps declarados →
|
|
43
|
+
lista vacía · simplicity sin declarar → aviso de opinión · presupuesto por
|
|
44
|
+
CLI → listado en `budgets_declared`.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# dev-loop-kit 1.18.0 — phase: la FSM derivada del workflow (2026-07-03)
|
|
2
|
+
|
|
3
|
+
Novena mejora del backlog PragProg (M4 de `docs/analisis-pragmatic-programmer.md`;
|
|
4
|
+
Topic 29 *"Juggling the Real World"* — FSM como tabla de datos). Resuelta con
|
|
5
|
+
decisión humana explícita entre tres opciones: **FSM derivada** (ni la FSM
|
|
6
|
+
declarada del análisis original, ni solo-pr-gate, ni diferir).
|
|
7
|
+
Smoke suite: 117/117.
|
|
8
|
+
|
|
9
|
+
## La idea (measured beats narrated, aplicado a la FSM misma)
|
|
10
|
+
|
|
11
|
+
- El reframe clave: una FSM donde el agente DECLARA "entro a build/qa" es
|
|
12
|
+
**estado narrado** — exactamente lo que el kit combate. Acá el estado se
|
|
13
|
+
**COMPUTA** de los hechos del ledger; no existen transiciones ilegales que
|
|
14
|
+
validar porque no hay nada que declarar.
|
|
15
|
+
- Reglas de derivación (precedencia): **escalated** (escalación abierta — el
|
|
16
|
+
acto humano pendiente pisa todo) → **pr-ready** (convergencia + tests verdes
|
|
17
|
+
medidos + 0 BLOCKER/CRITICAL) → **qa** (pasos registrados sin converger) →
|
|
18
|
+
**build** (snapshots medidos, sin QA) → **plan** (ledger virgen).
|
|
19
|
+
- La "tabla de estados × eventos" del análisis original se convierte en estas
|
|
20
|
+
reglas de derivación — documentadas en el código como datos, no prosa.
|
|
21
|
+
|
|
22
|
+
## Engine (qa_ledger.py)
|
|
23
|
+
|
|
24
|
+
- `phase --repo X` (subcomando 21): imprime el estado derivado CON su
|
|
25
|
+
evidencia. `--require pr-ready` sale 1 si los hechos no alcanzan, listando
|
|
26
|
+
exactamente qué falta ("el estado no se negocia, se construye"). JSON:
|
|
27
|
+
`{phase, evidence, required, satisfied}`.
|
|
28
|
+
- `dev-loop` Phase 6: el PR se gatea con `phase --require pr-ready` ANTES de
|
|
29
|
+
abrirse — la transición ilegal "PR sin convergencia" del análisis original
|
|
30
|
+
ahora es un hecho bloqueante mecánico, que era todo el punto de M4.
|
|
31
|
+
|
|
32
|
+
## Smoke
|
|
33
|
+
|
|
34
|
+
- **T40**: ciclo de vida completo derivado — virgen→plan · snapshot→build ·
|
|
35
|
+
QA sin converger→qa · pr-ready con findings abiertos→exit 1 · escalación
|
|
36
|
+
abierta→escalated (pisa todo) · convergido+limpio→pr-ready.
|
|
37
|
+
|
|
38
|
+
## Diferido consciente
|
|
39
|
+
|
|
40
|
+
- El estado es per-repo; un estado agregado feature-level (todos los repos
|
|
41
|
+
pr-ready + integración verde) se deriva componiendo — si el dogfooding lo
|
|
42
|
+
pide como comando propio, se agrega.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# dev-loop-kit 1.19.0 — spikes formales: descartable por contrato (2026-07-03)
|
|
2
|
+
|
|
3
|
+
Décima y ÚLTIMA mejora del backlog PragProg (M10 de
|
|
4
|
+
`docs/analisis-pragmatic-programmer.md`; Tip 21 *"Prototype to Learn"* +
|
|
5
|
+
Topic 37 *"It's Playtime!"*). Con esta release, **las 10 mejoras del cruce con
|
|
6
|
+
The Pragmatic Programmer están resueltas** — 8 implementadas directas y 2
|
|
7
|
+
resueltas con decisión humana explícita entre opciones (M5 procedencia, M4 FSM
|
|
8
|
+
derivada). Convención elegida por el humano: prefijo **`spike/*`**.
|
|
9
|
+
Smoke suite: 121/121.
|
|
10
|
+
|
|
11
|
+
## La idea (la versión ejecutable de "make it clear this code is disposable")
|
|
12
|
+
|
|
13
|
+
- Un riesgo de incertidumbre ALTA en discovery dispara la pregunta: "¿amerita
|
|
14
|
+
un spike time-boxed antes de congelar la SPEC?" (paso 10 de la agenda).
|
|
15
|
+
- El spike corre en una rama `spike/*` y su ÚNICO output legítimo es un
|
|
16
|
+
**ADR con lecciones** — hechos que alimentan la SPEC, jamás código mergeable.
|
|
17
|
+
- El contrato es ejecutable, estilo INV-GOLDEN-01: `phase --require pr-ready`
|
|
18
|
+
**rechaza cualquier rama `spike/*`** aunque los hechos del ledger den
|
|
19
|
+
pr-ready — "escribí el ADR y arrancá limpio en una rama normal". Sin
|
|
20
|
+
`--require` solo informa (consultar no gatea). Resuelve la tensión con
|
|
21
|
+
Stone Soup sin romper spec-first.
|
|
22
|
+
|
|
23
|
+
## Engine (qa_ledger.py)
|
|
24
|
+
|
|
25
|
+
- `_spike_branch()`: `git symbolic-ref --short -q HEAD` (funciona antes del
|
|
26
|
+
primer commit; detached HEAD o directorio sin git = sin veto, disclosed).
|
|
27
|
+
- `phase --require pr-ready`: veto de spike ANTES del veredicto; JSON expone
|
|
28
|
+
`spike_branch`.
|
|
29
|
+
|
|
30
|
+
## Smoke
|
|
31
|
+
|
|
32
|
+
- **T41**: repo pr-ready por hechos PERO en `spike/*` → exit 1 con el mensaje
|
|
33
|
+
del contrato · consulta sin `--require` → informa sin gatear · rama normal
|
|
34
|
+
→ pr-ready vuelve a pasar.
|
|
35
|
+
|
|
36
|
+
## El backlog PragProg, cerrado
|
|
37
|
+
|
|
38
|
+
M2 (1.10.0) · M9 (1.11.0) · M8 (1.12.0) · M3 (1.13.0) · M6 (1.14.0) ·
|
|
39
|
+
M7 (1.15.0) · M1 (1.16.0) · M5 (1.17.0) · M4 (1.18.0) · M10 (1.19.0).
|
|
40
|
+
Cada release: smoke verde → review fresco → hallazgos aplicados → triple
|
|
41
|
+
sync → commit único. Lo diferido consciente de cada una vive en su CHANGELOG.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# dev-loop-kit 1.2.2
|
|
2
|
+
|
|
3
|
+
## Fixes (simplicity-check)
|
|
4
|
+
- **[BLOCKER] `--from-git` crasheaba en Windows** — `subprocess.run` sin `encoding`
|
|
5
|
+
decodificaba el diff con cp1252 y reventaba (UnicodeDecodeError → None.splitlines).
|
|
6
|
+
Fix: `encoding="utf-8", errors="replace"`.
|
|
7
|
+
- **Salida en mojibake en consola Windows** — `main()` fuerza `stdout/stderr` a UTF-8.
|
|
8
|
+
- **No filtraba por tipo de archivo** — medía docs/config/resources como código
|
|
9
|
+
(inflaba lines/nesting; falsos OVERBUILT). Ahora solo cuenta código
|
|
10
|
+
(`_SIMPLICITY_CODE_EXT` + `SKIP_DIRS`), y reporta cuántos archivos salteó.
|
|
11
|
+
|
|
12
|
+
## Nuevo: `pit-check` (mutation testing)
|
|
13
|
+
- Gate de EFECTIVIDAD de tests (coverage miente): ingesta el `mutations.xml` de PIT,
|
|
14
|
+
reporta mutation score + **test-strength** (matados/cubiertos) + hotspots.
|
|
15
|
+
- Invariante **Tests efectivos** agregada a `templates/CONSTITUTION.md`.
|
|
16
|
+
- Tier scheduled/incremental (PIT es caro), no inner loop.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# dev-loop-kit 1.2.3
|
|
2
|
+
|
|
3
|
+
## Fixes (qa_ledger.py) — verificados por doble review adversarial (judgment-day, 2 rondas, 0 critical)
|
|
4
|
+
- pit-check: NON_VIABLE + RUN_ERROR excluidos del denominador (antes inflaban el score y
|
|
5
|
+
podían tirar un BELOW-GATE falso). Nuevo campo `excluded`.
|
|
6
|
+
- simplicity-check: parser robusto con máquina de estados `in_hunk` — una línea agregada
|
|
7
|
+
`++ x` (que en el diff aparece como `+++ x`) ya no se confunde con un header y deja de
|
|
8
|
+
perder el conteo del resto del hunk.
|
|
9
|
+
- simplicity-check: skip-set más angosto (`_SIMPLICITY_SKIP`) — código en paquetes
|
|
10
|
+
`generated`/`out`/`bin`/`dist` ya no se descarta del budget.
|
|
11
|
+
|
|
12
|
+
## Nuevo (CONSTITUTION.md)
|
|
13
|
+
- Invariante "Integridad del gate — no gamear al que mide": un diff que debilita el aparato
|
|
14
|
+
de medición (tests/lint/thresholds) o reescribe una masa de asserts = BLOCKER; checker
|
|
15
|
+
no-correlacionado para alto blast-radius. (Osmani, "Agentic Code Review".)
|
|
16
|
+
|
|
17
|
+
## Limitación conocida (documentada)
|
|
18
|
+
- simplicity-check espera diffs formato git (`diff --git` por archivo, como `git diff` y
|
|
19
|
+
`--from-git`). Un `diff -u` plano de POSIX sin esos headers miscuenta archivos después
|
|
20
|
+
del primero. Usar `--from-git` o `git diff > file`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# dev-loop-kit 1.2.4
|
|
2
|
+
|
|
3
|
+
## Nuevo: gate-check (integridad del gate — "no gamear al que mide")
|
|
4
|
+
- Comando `qa_ledger.py gate-check`: detecta si un diff DEBILITA el aparato de medición.
|
|
5
|
+
- **BLOCKER (exit 1):** tests borrados o deshabilitados, thresholds de coverage/mutation bajados.
|
|
6
|
+
- **Revisar (soft):** supresiones de lint agregadas, asserts removidos en tests. `--strict` los gatea.
|
|
7
|
+
- Lee diffs formato git (`--from-git` / `--diff` / stdin). stdlib pura.
|
|
8
|
+
- Implementa en CÓDIGO la invariante "Integridad del gate" de la CONSTITUTION (antes solo texto).
|
|
9
|
+
- (Osmani, "Agentic Code Review": los red-flags para revisores humanos; el detector automático
|
|
10
|
+
y el principio "el aparato no lo modifica el cambio que mide" son síntesis del kit.)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# dev-loop-kit 1.2.5 — destilación ("gates de hechos bloquean, adivinadores de prosa avisan")
|
|
2
|
+
|
|
3
|
+
## Nuevo: golden-diff + INV-GOLDEN-01 (golden/approval testing)
|
|
4
|
+
- `qa_ledger.py golden-diff`: byte-compara `*.received.*` vs `*.approved.*`. Cualquier no-match
|
|
5
|
+
o `.received` sin `.approved` = DIVERGE (exit 1). Es un HECHO, no un juicio. Nunca toca `.approved`.
|
|
6
|
+
- Invariante `INV-GOLDEN-01` (CWE-440) en CONSTITUTION: en migraciones, golden capturado ANTES de
|
|
7
|
+
tocar el módulo; el golden lo captura un script sobre el código ORIGINAL, el agente no lo authorea.
|
|
8
|
+
- (Del HANDOFF de golden testing — pendiente a mano: skill `characterize`, hook PreToolUse que bloquee
|
|
9
|
+
escrituras a `.approved`, `.gitattributes *.approved.* binary`, y decisión de stack del harness.)
|
|
10
|
+
|
|
11
|
+
## Destilación (distinción hechos vs adivinanza)
|
|
12
|
+
- `spec-check` → **ADVISORY** por defecto (heurística sobre prosa): reporta, NO bloquea. `--strict` gatea.
|
|
13
|
+
- `simplicity-check` → el regex de "abstracciones" (falsos positivos con records/DTOs) sale del score y
|
|
14
|
+
del hard-cap; queda como métrica/flag informativa. Los caps numéricos (líneas/archivos/anidación) siguen gateando.
|
|
15
|
+
|
|
16
|
+
## Fixes de spec-check (judgment-day Ronda 1, 2 jueces, 2 critical + 4 warnings, todos resueltos)
|
|
17
|
+
- Code-fence tracking (un `# Exclusions` dentro de ```` ``` ```` ya no cuenta), setext headings,
|
|
18
|
+
checkbox vacío no cuenta como criterio, `_SC_ACCEPT` anclado (no "Success/Exit criteria"),
|
|
19
|
+
`\d` suelto ya no exime vago, stack ambiguo podado + scopeado a criterios, vagos en español sumados.
|
|
20
|
+
|
|
21
|
+
## Gates: hechos (bloquean) vs prosa (avisan)
|
|
22
|
+
- BLOQUEAN (leen hechos): golden-diff, pit-check, gate-check, readiness/rebuild, caps de simplicity.
|
|
23
|
+
- AVISAN (heurística): spec-check, abstracciones de simplicity.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# dev-loop-kit 1.2.6 — fix golden-diff (judgment-day, 2 jueces, coincidencia)
|
|
2
|
+
|
|
3
|
+
## Fix (cmd_golden_diff) — verificado contra los casos reproducidos por los jueces
|
|
4
|
+
- **[CRITICAL] `str.replace` global** reemplazaba TODAS las ocurrencias de `.received.`:
|
|
5
|
+
con el marcador en una carpeta padre (snapshots por fecha) o dos veces en el nombre,
|
|
6
|
+
derivaba el `.approved` mal → DIVERGE falso, y en el peor caso un **FALSE CLEAN** (dejaba
|
|
7
|
+
pasar una divergencia, exit 0). Fix: `_golden_approved_path()` deriva solo del BASENAME,
|
|
8
|
+
última ocurrencia (rpartition), nunca del path del directorio.
|
|
9
|
+
- **[real] directorios `*.received.*`** se escaneaban como fixtures → filtro `os.path.isfile`.
|
|
10
|
+
- **[gap] `Foo.received` sin extensión** se salteaba (false CLEAN) → segundo glob `*.received`.
|
|
11
|
+
- Read-only confirmado por ambos jueces: cero write/rename; el agente no puede authorear el golden.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# dev-loop-kit 1.2.7 — skill reverse-discovery (front brownfield)
|
|
2
|
+
|
|
3
|
+
## Nuevo skill: reverse-discovery
|
|
4
|
+
- Hermano brownfield de `discovery`, para migrar/modernizar un sistema EXISTENTE.
|
|
5
|
+
- El inverso de discovery: el sistema ya existe y su comportamiento ES la verdad → se
|
|
6
|
+
EXTRAEN hechos, no se propone forma.
|
|
7
|
+
- **Facts-only por diseño:** produce SOLO (1) un mapa del sistema (endpoints, contratos,
|
|
8
|
+
grafo de dependencias, candidatos de módulo vía análisis estático) y (2) un golden suite
|
|
9
|
+
capturado mecánicamente en los bordes. NO authorea SPEC/ADR inferidos — eso lo escribe el
|
|
10
|
+
humano leyendo los hechos; las decisiones forward de módulos van a `/adr-refine`.
|
|
11
|
+
- Hereda INV-GOLDEN-01: el agente nunca toca los `.approved`.
|
|
12
|
+
- Cae limpio del lado "hechos" de la línea hechos-vs-prosa: análisis estático + byte-captura,
|
|
13
|
+
cero heurística sobre prosa → nada frágil que se rompa.
|
|
14
|
+
- Flujo migración: reverse-discovery → humano escribe SPEC + /adr-refine → /dev-loop
|
|
15
|
+
(golden-diff + ApplicationModules.verify() verdes) → readiness + human gate.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# dev-loop-kit 1.2.8 — golden testing completo (characterize + hook + gitattributes)
|
|
2
|
+
|
|
3
|
+
## Nuevo skill: characterize (golden-capture)
|
|
4
|
+
- Captura el golden del código ORIGINAL con inputs reales, por un harness determinístico.
|
|
5
|
+
- 4 fases: harness → checklist de no-determinismo (locale es-AR obligatorio) → captura
|
|
6
|
+
(.received) → STOP para aprobación humana. NUNCA crea/edita un .approved.
|
|
7
|
+
- Lo orquesta reverse-discovery en su fase 2.
|
|
8
|
+
|
|
9
|
+
## Nuevo hook: hooks/block-approved-writes.ps1 (PreToolUse, INV-GOLDEN-01)
|
|
10
|
+
- Bloquea mecánicamente que el agente escriba/renombre cualquier *.approved.* (Write/Edit/
|
|
11
|
+
Bash-write → exit 2). Deja pasar lecturas. Probado.
|
|
12
|
+
- WIRING (pegar en settings.json — no lo puede hacer el agente por el guardrail de self-mod):
|
|
13
|
+
"hooks": { "PreToolUse": [ { "matcher": "*", "hooks": [
|
|
14
|
+
{ "type": "command",
|
|
15
|
+
"command": "powershell -NoProfile -ExecutionPolicy Bypass -File \"<KIT>/hooks/block-approved-writes.ps1\"" }
|
|
16
|
+
] } ] }
|
|
17
|
+
|
|
18
|
+
## Nuevo: templates/.gitattributes
|
|
19
|
+
- `*.approved.* binary` + `*.received.* binary` — line endings no generan diffs falsos
|
|
20
|
+
(crítico Windows/SQL Server). Copiar a la raíz del repo de migración.
|
|
21
|
+
|
|
22
|
+
## Estado del golden testing (del HANDOFF) — AHORA completo en el kit
|
|
23
|
+
- golden-diff (gate, byte-compare) ✓ · characterize (captura) ✓ · reverse-discovery (front
|
|
24
|
+
brownfield) ✓ · INV-GOLDEN-01 (CONSTITUTION) ✓ · hook PreToolUse ✓ · .gitattributes ✓
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# dev-loop-kit 1.2.9 — documentación generalizada
|
|
2
|
+
- Removidas todas las referencias a proyecto/dominio específico del CONSTITUTION template
|
|
3
|
+
y de los skills characterize/reverse-discovery (ejemplos fiscales → genéricos; locale es-AR
|
|
4
|
+
→ "target locale"; money-path → "camino crítico"). El kit queda dominio-agnóstico.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# dev-loop-kit 1.20.0 — instalación global (2026-07-03)
|
|
2
|
+
|
|
3
|
+
Release chica de instalabilidad: el kit ahora puede instalarse UNA vez en
|
|
4
|
+
`~/.claude/` y quedar disponible para todos los proyectos, existentes y nuevos.
|
|
5
|
+
Sin cambios de engine. Smoke suite: 121/121.
|
|
6
|
+
|
|
7
|
+
## Qué cambia
|
|
8
|
+
|
|
9
|
+
- **Resolución portable del engine**: `dev-loop` y `sys-doc` resuelven
|
|
10
|
+
`qa_ledger.py` primero en el proyecto (`./.claude/skills/dev-loop/`) y caen a
|
|
11
|
+
la instalación global (`~/.claude/skills/dev-loop/`) si no hay local. La
|
|
12
|
+
instalación por proyecto sigue teniendo precedencia (un proyecto puede pinnear
|
|
13
|
+
su versión del kit copiándolo local).
|
|
14
|
+
- **Instalación global documentada completa** (README § Instalación, Opción B):
|
|
15
|
+
las SEIS skills (antes el snippet copiaba solo dev-loop y sys-doc — quedó de
|
|
16
|
+
cuando eran las únicas dos) + el hook `block-approved-writes.ps1` a
|
|
17
|
+
`~/.claude/hooks/` con registro en `~/.claude/settings.json`, para que
|
|
18
|
+
INV-GOLDEN-01 rija en todos los proyectos.
|
|
19
|
+
- **Qué sigue siendo por-proyecto** (estado, no instalable — ahora explícito):
|
|
20
|
+
`dev-loop.config.json` (los `path` son relativos a la raíz de la run, y la
|
|
21
|
+
quality bar declarada del humano vive ahí — 1.17.0), `QA-LEDGER.json`,
|
|
22
|
+
`ACCEPTANCE.md`, y el `.gitattributes` de templates para migración.
|
|
23
|
+
- Nota para la máquina donde se DESARROLLA el kit: junction/symlink por skill al
|
|
24
|
+
repo canónico en vez de copia — global siempre al día con main.
|
|
25
|
+
|
|
26
|
+
## Diferido consciente
|
|
27
|
+
|
|
28
|
+
- Un comando `install.sh`/`install.ps1` empaquetado: hoy son dos líneas de shell
|
|
29
|
+
documentadas; si el on-ramp real (dogfooding) muestra fricción, se mecaniza.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# dev-loop-kit 1.21.0 — namespace specloop-* (2026-07-03)
|
|
2
|
+
|
|
3
|
+
Release de naming, decidida por el humano entre tres opciones (prefijo largo /
|
|
4
|
+
prefijo corto / dejar como está): las seis skills pasan de nombres genéricos a
|
|
5
|
+
**namespace `specloop-*`**. Nombres como `discovery` o `characterize` eran
|
|
6
|
+
squatting del namespace global — cualquier otro kit podía pisarlos (evidencia:
|
|
7
|
+
el harness ya desambiguaba proyecto-vs-global con los genéricos). Se hace AHORA
|
|
8
|
+
porque es el momento más barato: antes de publicar, renombrar no rompe a nadie.
|
|
9
|
+
Sin cambios de engine. Smoke suite: 121/121.
|
|
10
|
+
|
|
11
|
+
## El mapa de renombres
|
|
12
|
+
|
|
13
|
+
| Antes | Ahora |
|
|
14
|
+
|---|---|
|
|
15
|
+
| `/discovery` | `/specloop-discovery` |
|
|
16
|
+
| `/adr-refine` | `/specloop-adr-refine` |
|
|
17
|
+
| `/reverse-discovery` | `/specloop-reverse-discovery` |
|
|
18
|
+
| `/characterize` | `/specloop-characterize` |
|
|
19
|
+
| `/dev-loop` | `/specloop-devloop` |
|
|
20
|
+
| `/sys-doc` | `/specloop-sysdoc` |
|
|
21
|
+
|
|
22
|
+
- **El path del engine cambia** (breaking para scripts que lo hardcodeaban):
|
|
23
|
+
`.claude/skills/dev-loop/qa_ledger.py` → `.claude/skills/specloop-devloop/qa_ledger.py`.
|
|
24
|
+
El fallback global (1.20.0) apunta ahora a `~/.claude/skills/specloop-devloop/`.
|
|
25
|
+
- **NO cambian**: `dev-loop-kit` (el nombre del kit), `dev-loop.config.json`
|
|
26
|
+
(el archivo de config), los subcomandos del engine, ni el schema del ledger.
|
|
27
|
+
- Instalación global: re-crear los junctions/copias con los nombres nuevos
|
|
28
|
+
(los viejos quedan rotos tras el rename de directorios).
|
|
29
|
+
- Sweep completo con truth-pass: SKILL.md (frontmatter + referencias cruzadas),
|
|
30
|
+
READMEs, templates/CLAUDE.md, decks ES/EN, playbooks ES/EN, onepagers,
|
|
31
|
+
pitches, skills-referencia, smoke. Los artefactos HISTÓRICOS (audits/*.json,
|
|
32
|
+
changelogs viejos, HANDOFFs de releases pasadas) NO se retro-editan —
|
|
33
|
+
documentan el estado de su época.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# dev-loop-kit 1.22.0 — doctor: diagnóstico de la instalación (2026-07-03)
|
|
2
|
+
|
|
3
|
+
`qa_ledger.py doctor` (subcomando 22) — espíritu flutter doctor: verifica que
|
|
4
|
+
spec-loop esté instalado y sano en la máquina de trabajo, Windows y Linux.
|
|
5
|
+
Smoke suite: 124/124.
|
|
6
|
+
|
|
7
|
+
## La idea
|
|
8
|
+
|
|
9
|
+
- **El engine verifica su PROPIA instalación**: las skills viven al lado de
|
|
10
|
+
`qa_ledger.py` (sea `~/.claude/skills/` global o `.claude/skills/` del
|
|
11
|
+
proyecto), así que doctor inspecciona a sus hermanos y reporta qué modo de
|
|
12
|
+
instalación detectó.
|
|
13
|
+
- **Output ASCII puro** (`[OK]` / `[ !]` / `[ X]`): es la herramienta de primer
|
|
14
|
+
contacto en máquinas vírgenes — no puede depender del encoding de la consola.
|
|
15
|
+
- **Exit 1 SOLO con errores**; los avisos no fallan (un toolchain ausente en la
|
|
16
|
+
máquina puede vivir en CI). `--json` para consumo programático.
|
|
17
|
+
|
|
18
|
+
## Qué chequea
|
|
19
|
+
|
|
20
|
+
| Check | Nivel si falla |
|
|
21
|
+
|---|---|
|
|
22
|
+
| Python ≥ 3.8 · git en PATH | error |
|
|
23
|
+
| Las 6 skills junto al engine, con frontmatter `name:` verificado | error |
|
|
24
|
+
| Hook INV-GOLDEN-01: archivo presente · registrado en `settings.json` (PreToolUse) · intérprete powershell/pwsh disponible | aviso (cada capa faltante, con el remedio) |
|
|
25
|
+
| `dev-loop.config.json` del cwd: parseable, versión, repos | error si inválido · aviso si ausente |
|
|
26
|
+
| ACCEPTANCE del config: criterios + AC-IDs trazables | aviso |
|
|
27
|
+
| Skills de QA de `qa_tools_order` (default code-review/judgment-day/improve) presentes en `.claude/skills` del proyecto o del usuario — el loop las orquesta sin traerlas | aviso (las built-in del harness no son detectables por filesystem, y lo dice) |
|
|
28
|
+
| Ledger: carga + checksum de integridad (1.13.0) | **error** si corrupto/mutado |
|
|
29
|
+
| Toolchain primario por repo type (`mvn`/`pytest`/`npm`/`go`/`cargo`/`dotnet`/`ctest`/`gradlew` del repo/`swift`/`flutter`) | aviso |
|
|
30
|
+
|
|
31
|
+
## El doctor no solo diagnostica: cura
|
|
32
|
+
|
|
33
|
+
Cada aviso/error lleva su **remedio accionable** — el comando o el link de
|
|
34
|
+
instalación (python.org, git-scm, maven/flutter/nodejs/go/rustup/dotnet/cmake/
|
|
35
|
+
gradle/swift, pwsh para el hook en Linux, y los pasos del propio kit para
|
|
36
|
+
skills/hook/config faltantes). Espíritu flutter doctor completo: corrés
|
|
37
|
+
`doctor`, instalás lo listado, re-corrés hasta verde.
|
|
38
|
+
|
|
39
|
+
## Hardening (review fresco pre-commit, aplicado)
|
|
40
|
+
|
|
41
|
+
- `startswith` sin separador final clasificaba `~/.claude/skills-evil/` como
|
|
42
|
+
instalación global → separador + `normcase` (case de drive en Windows).
|
|
43
|
+
- El header humano usaba em-dash y el JSON `ensure_ascii=False` — violaba la
|
|
44
|
+
promesa ASCII → header ASCII y `ensure_ascii=True` (el doctor promete bytes
|
|
45
|
+
ASCII SIEMPRE, es la herramienta de primer contacto).
|
|
46
|
+
- Detección de registro del hook por substring en la rama PreToolUse: límite
|
|
47
|
+
disclosed en el docstring (falso positivo rebuscado, dirección benigna).
|
|
48
|
+
|
|
49
|
+
## Notas de plataforma
|
|
50
|
+
|
|
51
|
+
- Linux: el hook es PowerShell — doctor avisa si no hay `pwsh` (instalarlo o
|
|
52
|
+
portar el twin bash, diferido consciente desde el header del .ps1).
|
|
53
|
+
- Windows: junctions de instalación global se atraviesan con normalidad
|
|
54
|
+
(doctor clasifica global vs por-proyecto por el path real del engine).
|
|
55
|
+
|
|
56
|
+
## Smoke
|
|
57
|
+
|
|
58
|
+
- **T42**: doctor en sandbox → exit 0 con config y ACCEPTANCE leídos, 6/6
|
|
59
|
+
skills, install clasificada por-proyecto · ledger corrupto → exit 1 (la
|
|
60
|
+
integridad del ledger es error, no aviso).
|