@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,75 @@
|
|
|
1
|
+
# dev-loop-kit 1.23.0 — rubric layer: el ACCEPTANCE de lo no-testeable (2026-07-03)
|
|
2
|
+
|
|
3
|
+
Origen: evaluación del concepto "rubrics" de Claude Code (Outcomes/graders) contra
|
|
4
|
+
el método. Veredicto: la ARQUITECTURA no aporta nada nuevo (maker≠checker con
|
|
5
|
+
contexto aislado ya existe); el edge real es **el artefacto** — criterio cualitativo
|
|
6
|
+
versionado. Entra con el acople corregido respecto de la propuesta original:
|
|
7
|
+
**advisory-first**, jamás dimensión ponderada del readiness (un grade LLM es guess
|
|
8
|
+
estructurado, no hecho medido — doctrina 1.10.0). Smoke suite: 139/139.
|
|
9
|
+
|
|
10
|
+
## Restricción de diseño: cero dependencia de un agente específico
|
|
11
|
+
|
|
12
|
+
Tres capas de acople decreciente — pedido explícito del humano:
|
|
13
|
+
|
|
14
|
+
1. **Núcleo (engine stdlib, cero LLM)**: `RUBRIC.md` + `spec-check --rubric` +
|
|
15
|
+
`rubric-ingest` + advisory en readiness + doctor. Un humano puede llenar el JSON
|
|
16
|
+
del grader a mano y todo funciona — **el smoke T43 lo prueba ejecutablemente**
|
|
17
|
+
(el grader.json del test se llena a mano, sin ningún LLM).
|
|
18
|
+
2. **Interfaz**: el contrato JSON
|
|
19
|
+
`{"criteria":[{"id","verdict":"pass|fail","evidence","note"}]}` — la ÚNICA
|
|
20
|
+
superficie entre el método y cualquier grader. IDs normalizados por número
|
|
21
|
+
(RB-01 == RB_1 == rb1, mismo criterio que AC-n).
|
|
22
|
+
3. **Graders pluggables**: `templates/rubric-grader-prompt.md` (markdown plano,
|
|
23
|
+
corre pegado en Codex, Gemini CLI, Cursor, un curl, o un humano) + la skill
|
|
24
|
+
`specloop-rubric` como adapter FINO de Claude Code (documentado como adapter).
|
|
25
|
+
|
|
26
|
+
## Qué hace
|
|
27
|
+
|
|
28
|
+
- **`RUBRIC.md`** (template en `templates/`): criterios `- [ ] RB-01 (peso 3) — …`
|
|
29
|
+
con anchor-pass/anchor-fail (calibran al grader, el engine no los parsea),
|
|
30
|
+
criterios negativos `RB-NEG-nn` (si aparecen, restan su peso) y `threshold: 0.NN`.
|
|
31
|
+
- **`spec-check --rubric`**: estructura = HECHO (archivo ausente, cero criterios
|
|
32
|
+
positivos, IDs duplicados normalizados, threshold ausente o fuera de (0,1] →
|
|
33
|
+
exit 1).
|
|
34
|
+
- **`rubric-ingest`** (subcomando 23): valida el contrato (IDs desconocidos =
|
|
35
|
+
error — el grader no inventa criterios), aplica **evidence-or-nothing** (un
|
|
36
|
+
veredicto que afecta el score sin cita `file:line` NO puntúa y se lista como no
|
|
37
|
+
sustentado), computa el score ponderado vs threshold y persiste un registro
|
|
38
|
+
`rubric:grade` en el ledger. **Advisory por default**: BELOW no gatea. Con
|
|
39
|
+
`--gate` o `defaults.rubric.gate: true` (procedencia: declaración humana), un
|
|
40
|
+
BELOW escribe registro gateado → bloquea convergencia y capea readiness ≤65 por
|
|
41
|
+
la maquinaria existente; un grade limpio posterior lo levanta (latest-wins).
|
|
42
|
+
- **readiness**: muestra el último grade por repo como línea advisory — NO es
|
|
43
|
+
dimensión con peso (measured beats narrated).
|
|
44
|
+
- **doctor**: si `defaults.rubric.file` está declarado, chequea existencia y
|
|
45
|
+
estructura (aviso con remedio).
|
|
46
|
+
- **`specloop-rubric`** (7ma skill): el adapter de Claude Code — contexto aislado
|
|
47
|
+
(solo diff + rúbrica, jamás el razonamiento del maker), sesgo a `fail` ante la
|
|
48
|
+
duda, y prohibido declararse el gate a sí misma.
|
|
49
|
+
|
|
50
|
+
## Hardening (review fresco pre-commit, 4 hallazgos aplicados)
|
|
51
|
+
|
|
52
|
+
- `threshold: 0.8.0` (malformado) crasheaba con ValueError cruda → se trata como
|
|
53
|
+
ausente y bloquea con mensaje.
|
|
54
|
+
- Entradas no-dict en `criteria` crasheaban → contrato roto, error explícito.
|
|
55
|
+
- **IDs duplicados en el reporte** (RB-01 y RB-1 del mismo criterio): el último
|
|
56
|
+
pisaba al primero en silencio — vector de gaming del grader → contrato roto,
|
|
57
|
+
un veredicto por criterio.
|
|
58
|
+
- El check de smoke "convergencia bloqueada por el gate" era VACUO (converged ya
|
|
59
|
+
salía 1 en ledger virgen por 'no agent steps') → el fixture ahora converge
|
|
60
|
+
ANTES, y se verifica además que un grade limpio LIBERA la convergencia
|
|
61
|
+
(latest-wins).
|
|
62
|
+
|
|
63
|
+
## La ventaja (por qué entra al método)
|
|
64
|
+
|
|
65
|
+
El criterio cualitativo (convenciones, ergonomía de API, sanidad del error
|
|
66
|
+
handling, calidad de docs) hoy vivía en la cabeza de cada pase de QA. Ahora es
|
|
67
|
+
**versionado, diffeable, auditable** (cada veredicto con evidencia al ledger) y
|
|
68
|
+
**portable** (viaja en el repo; cualquier humano/agente hereda el estándar).
|
|
69
|
+
Anchors + negativos bajan la varianza del grader.
|
|
70
|
+
|
|
71
|
+
## Límite honesto
|
|
72
|
+
|
|
73
|
+
Nicho más chico que en la era en que se evaluó la idea: el acceptance trazable
|
|
74
|
+
(1.10.0) ya cierra lo testeable — esta capa cubre SOLO lo genuinamente cualitativo,
|
|
75
|
+
y siempre como guess estructurado: nunca reemplaza un gate duro.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# dev-loop-kit 1.24.0 — plugin de Claude Code (2026-07-03)
|
|
2
|
+
|
|
3
|
+
El kit ahora se distribuye como **plugin instalable** para Claude Code — el repo es
|
|
4
|
+
su propio marketplace. Los schemas se verificaron contra los docs oficiales
|
|
5
|
+
(code.claude.com/docs: plugins, plugins-reference, plugin-marketplaces,
|
|
6
|
+
discover-plugins) ANTES de escribir una línea — formato de tool real jamás se
|
|
7
|
+
inventa. Smoke suite: 140/140.
|
|
8
|
+
|
|
9
|
+
## Instalación (Opción C, la recomendada para Claude Code)
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
/plugin marketplace add andresmassello/SPEC-LOOP
|
|
13
|
+
/plugin install specloop@specloop
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
- Las 7 skills quedan como `specloop:specloop-*` (el namespace del plugin se suma
|
|
17
|
+
al prefijo propio — mismo patrón que sonarqube:sonar-*).
|
|
18
|
+
- **El hook INV-GOLDEN-01 se auto-registra** (`hooks/hooks.json` con
|
|
19
|
+
`${CLAUDE_PLUGIN_ROOT}`): desaparece la edición manual de settings.json que la
|
|
20
|
+
instalación global requería. Linux: el hook sigue siendo PowerShell — pwsh +
|
|
21
|
+
ajuste del comando (el doctor lo señala con remedio).
|
|
22
|
+
- Updates versionados: el plugin declara `version`, así que `/plugin update`
|
|
23
|
+
solo actualiza con bump de release.
|
|
24
|
+
- **Cero reestructuración**: `plugin.json` soporta path custom de skills
|
|
25
|
+
(`"skills": "./.claude/skills/"`) — el layout canónico del kit no cambió, y
|
|
26
|
+
las Opciones A (por proyecto) y B (global copy/junctions) siguen intactas
|
|
27
|
+
para Codex/Gemini/Cursor. El plugin es EMPAQUETADO, no dependencia: el
|
|
28
|
+
agnosticismo no se negocia.
|
|
29
|
+
|
|
30
|
+
## Qué se agregó
|
|
31
|
+
|
|
32
|
+
- `dev-loop-kit/.claude-plugin/plugin.json` — manifest (name `specloop`,
|
|
33
|
+
skills path custom, hooks auto-registrados, MIT).
|
|
34
|
+
- `dev-loop-kit/hooks/hooks.json` — registro PreToolUse del hook del golden
|
|
35
|
+
vía `${CLAUDE_PLUGIN_ROOT}`.
|
|
36
|
+
- `.claude-plugin/marketplace.json` (root del repo) — el marketplace `specloop`
|
|
37
|
+
con source relativo `./dev-loop-kit`.
|
|
38
|
+
- **doctor**: tercer modo de instalación detectado (`plugin`, path bajo
|
|
39
|
+
`~/.claude/plugins/`); en modo plugin el hook cuenta como registrado si
|
|
40
|
+
`hooks/hooks.json` existe (auto-registro — settings.json ya no participa).
|
|
41
|
+
JSON expone `plugin_install`.
|
|
42
|
+
- **Smoke T44 — el sync de versión ahora es un HECHO**: VERSION =
|
|
43
|
+
config.version = plugin.json.version = marketplace.version, o la suite falla.
|
|
44
|
+
La regla 6 del repo pasa de triple a **quíntuple** (con CHANGELOG).
|
|
45
|
+
|
|
46
|
+
## Nota para la máquina del autor
|
|
47
|
+
|
|
48
|
+
Los junctions de la Opción B y el plugin no deben convivir (skills duplicadas):
|
|
49
|
+
la máquina donde se desarrolla el kit se queda con junctions (siempre al día con
|
|
50
|
+
main); el plugin es el canal para las demás máquinas y terceros.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# dev-loop-kit 1.25.0 — anti-ceremonia: Lean sobre el propio método (2026-07-04)
|
|
2
|
+
|
|
3
|
+
Origen: el kit llegó a 23 subcomandos, 7 skills, hooks y una CONSTITUTION de 7
|
|
4
|
+
invariantes. El riesgo #1 dejó de ser un gate malo — es la **suma** de gates buenos
|
|
5
|
+
volviendo `/dev-loop` una auditoría. Eso es *over-processing*, muda de ceremonia
|
|
6
|
+
(Poppendieck cap. 4). Este release aplica Lean a la herramienta misma: una
|
|
7
|
+
meta-invariante que gobierna qué gate futuro entra, y el cambio de UX que la hace
|
|
8
|
+
real — **un veredicto único**. Smoke suite: 148/148.
|
|
9
|
+
|
|
10
|
+
## Qué hace
|
|
11
|
+
|
|
12
|
+
- **Meta-invariante "Anti-ceremonia"** (`templates/CONSTITUTION.md`): la prueba ácida
|
|
13
|
+
que TODO gate futuro debe pasar antes de entrar — (1) corre sin que el humano tipee
|
|
14
|
+
nada, (2) habla solo cuando importa, (3) colapsa en `readiness`, (4) un cambio
|
|
15
|
+
trivial lo saltea. Es principio + criterio de review, no un check del engine.
|
|
16
|
+
- **Veredicto único en `readiness`** (la regla 3, mecanizada): por default `readiness`
|
|
17
|
+
es UNA pantalla — la línea de veredicto, los warnings condicionales que sí dispararon
|
|
18
|
+
(habla solo cuando importa) y una línea `--- gates:` que **colapsa** cada fact gate
|
|
19
|
+
persistido (`gate:*`, `rubric:grade`, `blocker:*`) en `N ok · M bloqueando
|
|
20
|
+
(repo/gate…)`. `--verbose` abre la tabla de dimensiones, el resumen
|
|
21
|
+
acceptance/coverage/churn y el desglose por repo.
|
|
22
|
+
- **`readiness --json`** gana una sección `"gates"` aditiva (la consume sys-doc/CI).
|
|
23
|
+
|
|
24
|
+
## Decisión de acople: presentación, no re-peso
|
|
25
|
+
|
|
26
|
+
El rollup **lee hechos ya persistidos en el ledger — jamás recomputa el score**. Un
|
|
27
|
+
gate es "bloqueando" sii su último registro gateó ≥1 finding (`gated_reported > 0`),
|
|
28
|
+
que es exactamente la señal que ya alimentaba el cap ≤65. Consecuencia dura: el número
|
|
29
|
+
de readiness es **idéntico** al de 1.24.0 — el smoke lo prueba (las ~30 aserciones de
|
|
30
|
+
readiness previas siguen verdes sin tocarse). No entra como dimensión ponderada: plegar
|
|
31
|
+
sub-scores al peso rompería el anti-Goodhart (la dimensión dominante es measured-
|
|
32
|
+
acceptance a propósito).
|
|
33
|
+
|
|
34
|
+
## Qué NO entra (y por qué)
|
|
35
|
+
|
|
36
|
+
- **Perfiles de riesgo A–E mecanizados**: la regla ácida 4 ("un cambio trivial lo
|
|
37
|
+
saltea") es principio hasta que exista el clasificador. Los perfiles hoy son doctrina
|
|
38
|
+
(CONSTITUTION/SKILL), no máquina — el engine no tiene `--profile`. Mecanizarlos es su
|
|
39
|
+
propio ADR (¿por tamaño de diff? ¿por paths? ¿por declaración?), release aparte.
|
|
40
|
+
- **`rebuild` en el rollup**: es eje de completitud (COVERS/PARTIAL/DIVERGE), no un
|
|
41
|
+
gate pass/fail; no tiene `--kind` en `log-gate` y queda fuera a propósito.
|
|
42
|
+
|
|
43
|
+
## Smoke (T45, 8 checks nuevos)
|
|
44
|
+
|
|
45
|
+
Ledger fresco aislado: default emite el veredicto y **colapsa** dimensiones y by-repo;
|
|
46
|
+
`--verbose` los expande; un `log-gate --kind simplicity --verdict fail` aparece nombrado
|
|
47
|
+
en la línea de gates; un grade limpio posterior (latest-wins) la libera; `--json`
|
|
48
|
+
expone `gates[]` con `blocking` correcto.
|
|
49
|
+
|
|
50
|
+
## Límite honesto
|
|
51
|
+
|
|
52
|
+
El rollup mejora la **legibilidad**, no cambia qué se mide: los mismos hechos, una sola
|
|
53
|
+
pantalla. La meta-invariante es disciplina — su valor depende de que se aplique al
|
|
54
|
+
admitir cada gate futuro (empezando por `waste-check`, que por eso entrará
|
|
55
|
+
advisory-first y default-quiet, no como BLOCKER).
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# dev-loop-kit 1.26.0 — REUSE-FIRST: la muda que el gate no veía (2026-07-04)
|
|
2
|
+
|
|
3
|
+
Origen: el handoff anti-ceremony+reuse+compliance, ítem 2. La muda dominante del
|
|
4
|
+
código IA —**duplicación / reinvención en vez de reuso**— caía en el punto ciego del
|
|
5
|
+
kit: `simplicity-check` puntúa el diff en AISLAMIENTO, nunca contra lo que ya existe.
|
|
6
|
+
Evidencia: GitClear *Maintainability Gap* (2026): +81% de duplicación desde 2023,
|
|
7
|
+
código refactorizado/movido en 3,8%. Entra con el acople corregido respecto del
|
|
8
|
+
handoff original: **advisory-first**, no BLOCKER-por-default. Smoke suite: 157/157.
|
|
9
|
+
|
|
10
|
+
## Qué hace
|
|
11
|
+
|
|
12
|
+
- **`qa_ledger.py waste-check`** (subcomando 24): detección determinística de clones
|
|
13
|
+
Type-1/Type-2 del diff **vs el repo** (stdlib, sin LLM, sin red).
|
|
14
|
+
- Input igual que `simplicity-check` (`--diff` · `--from-git [--base]` · stdin) +
|
|
15
|
+
`--repo-root` para escanear lo existente.
|
|
16
|
+
- Ventana de `W=5` líneas normalizadas (strip + colapso de whitespace, se descartan
|
|
17
|
+
blancas y comment-only; una línea < `min_line_len` u sólo-puntuación no es
|
|
18
|
+
significativa). Métricas: `dup_windows_vs_repo` (la señal dominante),
|
|
19
|
+
`dup_windows_internal`, `dup_ratio`, `call_density` (informativo).
|
|
20
|
+
- Bandas `LEAN ≥85 · ACCEPTABLE ≥65 · WASTEFUL <65`. Flags accionables que nombran
|
|
21
|
+
el `archivo:linea` a reusar. `--json` con el contrato completo.
|
|
22
|
+
- Excluye tests (como simplicity) y **los archivos que el diff toca** (no auto-match):
|
|
23
|
+
captura el caso dominante — clon en archivo nuevo / desde archivos no tocados.
|
|
24
|
+
- **`log-gate --kind waste`**: persiste el veredicto → entra al veredicto único de
|
|
25
|
+
`readiness` (1.25.0) como línea `gate:waste` y, si gateado, capea ≤65 / bloquea
|
|
26
|
+
convergencia por la maquinaria existente.
|
|
27
|
+
- **`defaults.waste`** en config: `window_size`, `max_dup_windows_vs_repo`,
|
|
28
|
+
`max_dup_ratio`, `min_line_len`, `allow_paths` (boilerplate legítimo), `gate`.
|
|
29
|
+
- **CONSTITUTION**: invariante **REUSE-FIRST** framed honesta (ver abajo).
|
|
30
|
+
- **SKILL** Fase 2c: corre `waste-check` junto al simplicity gate; en perfil A (trivial)
|
|
31
|
+
no corre.
|
|
32
|
+
|
|
33
|
+
## Decisión de acople: advisory-first (corrige el handoff)
|
|
34
|
+
|
|
35
|
+
El handoff proponía `WASTEFUL → exit 1` + hard cap POR DEFAULT. Eso viola la
|
|
36
|
+
meta-invariante anti-ceremonia (1.25.0) regla 2: un detector Type-1/2 *habla siempre*
|
|
37
|
+
(boilerplate, DTOs, SQL/JSON embebido) → si bloquea por falsos positivos, se desactiva
|
|
38
|
+
y muere. Split honesto: el **HECHO** (un bloque de 5+ líneas ya existe en `X:linea`) es
|
|
39
|
+
medido; el **VEREDICTO** "wasteful" es heurística. Por eso: **avisa por default** (exit
|
|
40
|
+
0 con flags), gatea SOLO con `defaults.waste.gate: true` o `--gate` (procedencia 1.17.0:
|
|
41
|
+
el config commiteado ES la declaración). Un WASTEFUL declarado-gate persiste registro
|
|
42
|
+
bloqueante; sin declarar, sólo aconseja.
|
|
43
|
+
|
|
44
|
+
Nota: esto ELIMINA la dependencia de los perfiles A–E (que no están mecanizados): un
|
|
45
|
+
advisory default-quiet no necesita el perfil-skip para no ser ceremonia.
|
|
46
|
+
|
|
47
|
+
## Desviaciones honestas del handoff
|
|
48
|
+
|
|
49
|
+
- **`connectivity` NO puntúa** — se reporta informativa (como `new_functions` en
|
|
50
|
+
simplicity). "Densidad de llamadas a símbolos existentes" es un proxy que
|
|
51
|
+
false-positivea entre lenguajes; scorearlo sería ruido. Peso movido a
|
|
52
|
+
`repo_reuse 55 · internal_dup 45`.
|
|
53
|
+
- **`max_dup_windows_vs_repo: 0` por default** es seguro PRECISAMENTE porque es
|
|
54
|
+
advisory: cualquier clon vs repo baja el score y avisa, sin bloquear. Quien gatea
|
|
55
|
+
sube el budget o usa `allow_paths`.
|
|
56
|
+
|
|
57
|
+
## Smoke (T46, 9 checks)
|
|
58
|
+
|
|
59
|
+
Repo sintético `wrepo/` + 4 fixtures: LEAN (código único → 0 clones), clon-vs-repo
|
|
60
|
+
(→ WASTEFUL, advisory exit 0, flag nombra el original; con `--gate` exit 1), clon
|
|
61
|
+
interno (`dup_windows_internal ≥ 1`), clon en archivo de TEST (excluido). Más:
|
|
62
|
+
determinismo (misma entrada → mismo score) y `log-gate --kind waste` visible en el
|
|
63
|
+
veredicto único de readiness.
|
|
64
|
+
|
|
65
|
+
## Límite honesto
|
|
66
|
+
|
|
67
|
+
Proxy Type-1/Type-2 sobre líneas normalizadas, NO detección semántica (Type-3/4:
|
|
68
|
+
renombres/reordenamientos) ni CC por AST. Es la definición operativa de GitClear —
|
|
69
|
+
suficiente para AVISAR, no para probar equivalencia semántica. El escaneo del repo es
|
|
70
|
+
O(archivos·líneas); en un monorepo enorme es un one-shot, no corre en cada pase.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# dev-loop-kit 1.27.0 — First-Time Yield: el KPI Lean que ya estaba en los datos (2026-07-04)
|
|
2
|
+
|
|
3
|
+
Origen: el handoff anti-ceremony+reuse+compliance, ítem 3 (parte pasiva). FTY
|
|
4
|
+
(First-Time Yield) es la métrica Lean clásica de calidad de proceso: qué fracción
|
|
5
|
+
del trabajo salió bien **al primer intento**, sin reprocesos. El ledger ya tenía los
|
|
6
|
+
datos (ciclos, regresiones, escalaciones) — sólo faltaba leerlos. Smoke suite: 161/161.
|
|
7
|
+
|
|
8
|
+
## Qué hace
|
|
9
|
+
|
|
10
|
+
- **`summary` reporta `first_time_yield`**: % de repos que pasaron QA **en el primer
|
|
11
|
+
ciclo** — sin segundo pase, sin regresiones nuevas, sin escalación (resuelta o no: una
|
|
12
|
+
intervención humana significa que NO salió a la primera). Derivado 100% de hechos ya
|
|
13
|
+
en el ledger (`node["iterations"]` con su número de ciclo, `new_regressions`,
|
|
14
|
+
`ledger["escalations"]`).
|
|
15
|
+
- Aparece en `summary` (texto + `--json` con `by_repo` detallado). Va en la
|
|
16
|
+
retrospectiva.
|
|
17
|
+
|
|
18
|
+
## Por qué pasivo e informativo (NO gatea)
|
|
19
|
+
|
|
20
|
+
Cumple la meta-invariante anti-ceremonia (1.25.0): **cero paso humano nuevo** (sale de
|
|
21
|
+
datos ya registrados) y **no es otra pantalla** (una línea en el summary que ya existía).
|
|
22
|
+
Y es explícitamente **informativo, jamás gate ni dimensión del readiness**: FTY mide el
|
|
23
|
+
PROCESO (¿cuánto reproceso hubo?), no el ESTADO del resultado. Meterlo al readiness
|
|
24
|
+
confundiría las dos cosas — readiness reporta si el resultado está listo, FTY reporta
|
|
25
|
+
qué tan limpio fue el camino. Son ejes distintos y se reportan aparte (como churn).
|
|
26
|
+
|
|
27
|
+
## Definición (de hechos del ledger)
|
|
28
|
+
|
|
29
|
+
Un repo cuenta como *first-time yield* sii: entró a QA (tiene iteraciones) **y** su ciclo
|
|
30
|
+
máximo es 1 **y** cero `new_regressions` **y** no tuvo escalación. `pct = first_time /
|
|
31
|
+
repos_que_entraron_a_QA`. Repos que nunca entraron a QA no cuentan en la base.
|
|
32
|
+
|
|
33
|
+
## Smoke (T47, 3 checks)
|
|
34
|
+
|
|
35
|
+
Dos repos: uno limpio al ciclo 1 (first-time), otro que necesitó 2 ciclos → FTY 50%,
|
|
36
|
+
visible en texto y `--json`. Y una escalación sobre el repo limpio lo saca del yield
|
|
37
|
+
(→ 0%), probando que la intervención humana cuenta como reproceso.
|
|
38
|
+
|
|
39
|
+
## Nota: compliance-map DIFERIDO
|
|
40
|
+
|
|
41
|
+
El ítem 3 del handoff traía también `compliance-map` (tabla requisito↔gate para dominios
|
|
42
|
+
auditados). Se DIFIERE: es tooling de auditoría sin consumidor auditado real todavía —
|
|
43
|
+
construirlo ahora sería especulativo (choca con el YAGNI del propio kit). Entra cuando
|
|
44
|
+
haya un consumidor que lo pida; el diseño (proyección del ledger, genérico, "trazabilidad"
|
|
45
|
+
no "compliance") ya está pensado en el handoff.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# dev-loop-kit 1.28.0 — acceptance medido: el "% terminado" que el kit puede firmar (2026-07-05)
|
|
2
|
+
|
|
3
|
+
Origen: la pregunta del humano — "¿se puede computar un % de proyecto terminado?".
|
|
4
|
+
Análisis: un % ponderado por etapa es progreso NARRADO y gameable (choca measured-beats-
|
|
5
|
+
narrated + anti-Goodhart). El único "% terminado" honesto es el **acceptance medido**:
|
|
6
|
+
criterios cerrados por un test verde name-tagged / total. El ledger ya lo tenía; faltaba
|
|
7
|
+
superficiarlo. Smoke suite: 177/177.
|
|
8
|
+
|
|
9
|
+
## Qué hace
|
|
10
|
+
|
|
11
|
+
- **`readiness` reporta `acceptance.measured_pct`**: el % de criterios AC cerrados MEDIDO
|
|
12
|
+
(`measured_closed / total`), NO el ratio de checkboxes. En `--json` (campo aditivo) y en
|
|
13
|
+
la **vista default** como una línea: `acceptance medido: 33.3% (1/3 criterios cerrados
|
|
14
|
+
por test verde — medido, no gatea)`.
|
|
15
|
+
- **Honesto por construcción**: la línea aparece SOLO con trazabilidad AC-n
|
|
16
|
+
(`acc_traceable and total`). Sin AC-IDs no hay % honesto → no se muestra nada (un %
|
|
17
|
+
sobre checkboxes sin test sería narrado, justo lo que el kit rechaza). `measured_pct`
|
|
18
|
+
es `null` en ese caso.
|
|
19
|
+
- **Informativo, jamás gatea**: es una lectura del hecho ya medido, no un gate ni una
|
|
20
|
+
dimensión nueva. Cumple la meta-invariante anti-ceremonia (1.25.0): un número medido
|
|
21
|
+
que "habla cuando importa" (hay criterios trazables), colapsado en readiness.
|
|
22
|
+
|
|
23
|
+
## Por qué NO un % ponderado por etapa
|
|
24
|
+
|
|
25
|
+
Se descartó explícitamente: asignar pesos a discovery/build/QA/… y mostrar una barra es
|
|
26
|
+
un burndown — progreso narrado ("en fase 5 de 8" no dice si lo hecho está correcto) y
|
|
27
|
+
gameable (tildar etapas mueve el número = el "done" prematuro que el método combate). El
|
|
28
|
+
"dónde estamos" ya lo da `phase` (FSM derivada); el "cuánto del spec está probado" lo da
|
|
29
|
+
este acceptance-%. Dos ejes medidos, ninguno narrado.
|
|
30
|
+
|
|
31
|
+
## Smoke (T29 extendido, 3 checks)
|
|
32
|
+
|
|
33
|
+
Sobre el fixture AC-trazable existente (AC-01 verde, AC-02 rojo, AC-03 sin marcar):
|
|
34
|
+
`measured_pct == 33.3` en `--json`; la línea `acceptance medido: 33.3%` visible en la
|
|
35
|
+
vista default; y —clave— con un ACCEPTANCE sin AC-IDs la línea NO aparece (honesto).
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# uscha-kit 1.29.0 — rebrand: spec-loop -> Uscha (2026-07-05)
|
|
2
|
+
|
|
3
|
+
La metodologia se renombra a **Uscha**. Rebrand completo: la marca, las 7 skills
|
|
4
|
+
(specloop-* -> uscha-*, comandos /uscha-discovery etc.), el plugin (specloop -> uscha),
|
|
5
|
+
el kit (dev-loop-kit -> uscha-kit), el config (dev-loop.config.json -> uscha.config.json)
|
|
6
|
+
y el paper (docs/paper/uscha-paper.*). Cambio BREAKING: los slash-commands cambian de
|
|
7
|
+
prefijo.
|
|
8
|
+
|
|
9
|
+
## Que NO cambio
|
|
10
|
+
- Los subcomandos de qa_ledger.py (readiness, waste-check, gate-check, ...) y el propio
|
|
11
|
+
qa_ledger.py: nombres neutros, sin marca.
|
|
12
|
+
- El hook block-approved-writes.ps1: nombre neutro.
|
|
13
|
+
- Los CHANGELOGs historicos y audits/: registro, se dejan verbatim.
|
|
14
|
+
- El remoto GitHub (SPEC-LOOP) y la carpeta local del checkout: fuera de alcance (rename
|
|
15
|
+
de repo/filesystem es otra operacion).
|
|
16
|
+
|
|
17
|
+
## Verificacion
|
|
18
|
+
- Smoke 177/177 (la suite y sus paths se actualizaron al nuevo kit).
|
|
19
|
+
- Sync quintuple 1.29.0 (T44).
|
|
20
|
+
- rg --hidden 'spec.?loop' sin colgados fuera de los historicos protegidos.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# dev-loop-kit 1.3.0 — "facts block, wired" (2026-07-01)
|
|
2
|
+
|
|
3
|
+
Release temático: el kit ahora **cumple su propio principio de cabecera**. Dos auditorías
|
|
4
|
+
adversariales (7 lentes de metodología + fidelidad doc↔código↔idea, 231 agentes) encontraron
|
|
5
|
+
que los fact-gates existían pero no alimentaban ni convergencia ni readiness, mientras que
|
|
6
|
+
los números auto-reportados del agente sí. 1.3.0 invierte eso de vuelta: *under-claim,
|
|
7
|
+
then wire, then re-claim*.
|
|
8
|
+
|
|
9
|
+
## Engine (qa_ledger.py)
|
|
10
|
+
|
|
11
|
+
### Nuevo
|
|
12
|
+
- **`log-gate`** — persiste el veredicto de un fact gate (golden-diff / gate-check /
|
|
13
|
+
pit-check / simplicity) como record static-gate-shaped: `fail` → BLOCKER que capea
|
|
14
|
+
readiness ≤65 y bloquea convergencia; `pass` → limpia el gate (latest-per-tool);
|
|
15
|
+
`not-run` → evento registrado que NUNCA lee como verde (la ausencia no es evidencia).
|
|
16
|
+
- **`flag-blocker [--resolve]`** — violación de CONSTITUTION/invariante como BLOCKER de
|
|
17
|
+
primera clase por la MISMA plomería que un BLOCKER de linter. El enforcement "capea ≤65 y
|
|
18
|
+
bloquea convergencia" ahora es real una vez registrada la violación.
|
|
19
|
+
- **`resolve-escalation`** — cerrar el gate humano es un evento registrado (`resolved_at`),
|
|
20
|
+
no una implicación.
|
|
21
|
+
|
|
22
|
+
### Endurecido
|
|
23
|
+
- **readiness**: un repo linteable cuyo static gate nunca corrió puntúa UNMEASURED (0.0),
|
|
24
|
+
no 1.0 — *el silencio no es éxito*. La dimensión agregada es el promedio per-repo (que ya
|
|
25
|
+
codifica UNMEASURED). El cap de escalación es independiente de converged y se sostiene
|
|
26
|
+
hasta `resolve-escalation`.
|
|
27
|
+
- **converged**: con `qa_tools_order` exige el último step POR HERRAMIENTA (rellenar la
|
|
28
|
+
ventana con steps limpios ya no esconde findings) y un snapshot rojo MEDIDO veta el verde
|
|
29
|
+
narrado del agente (`--tests-passed`).
|
|
30
|
+
- **gate-check**: borrado de archivo de test entero (`+++ /dev/null`) ya no es invisible;
|
|
31
|
+
thresholds bajados O borrados se detectan cross-hunk por keyword; con `--repo` compara los
|
|
32
|
+
totales de tests ejecutados entre snapshots (caída medida → REVIEW).
|
|
33
|
+
- **golden-diff**: cero fixtures = **NOT-RUN (exit 2)**, nunca CLEAN — también en `--json`
|
|
34
|
+
(antes reportaba CLEAN con 0 comparaciones).
|
|
35
|
+
- **simplicity-check**: min-floor en dims pesadas — un diff >1.5× del presupuesto de
|
|
36
|
+
tamaño/crecimiento no se promedia a ACCEPTABLE con dims baratas verdes.
|
|
37
|
+
- **spec-check**: veredictos partidos por la propia regla del kit — los 2 chequeos
|
|
38
|
+
ESTRUCTURALES (falta out-of-scope / sin criterios de aceptación) son HECHOS y bloquean
|
|
39
|
+
(exit 1); la prosa (vagos/EARS/stack) sigue advisory (`--strict` gatea).
|
|
40
|
+
- **oscillation**: detecta por Jaccard ≥0.8 sobre finding_ids (períodos 2-3) — un finding-ID
|
|
41
|
+
corrido ya no esconde el loop; fallback al fingerprint exacto.
|
|
42
|
+
|
|
43
|
+
## Hook (block-approved-writes.ps1)
|
|
44
|
+
- Bloquea CUALQUIER comando Bash que referencie un path `.approved` (la co-ocurrencia de
|
|
45
|
+
keywords era bypasseable vía `python -c "open(p,'w')"` / paths por variable / dd).
|
|
46
|
+
|
|
47
|
+
## Skill dev-loop (SKILL.md)
|
|
48
|
+
- Línea de audiencia arriba de todo: *un operador, un cambio con riesgo, ledger, human gate*
|
|
49
|
+
— y disclaimer NOT-for-trivial.
|
|
50
|
+
- Contrato de dos tiers explícito: medido (puede bloquear) vs auto-reportado (narración).
|
|
51
|
+
- **El golden ahora es alcanzable desde el camino principal**: captura en Phase 1 (perfil E,
|
|
52
|
+
vía `characterize`/`reverse-discovery`), `golden-diff` + `gate-check` persistidos con
|
|
53
|
+
`log-gate` en cada pass de Phase 3 (3b), hook + `.gitattributes` en Setup.
|
|
54
|
+
- Convergencia documentada como es: per-tool + fact gates + snapshot veta narración.
|
|
55
|
+
- CONSTITUTION: se registra con `flag-blocker` (obligación del agente), enforcement del
|
|
56
|
+
engine después del registro — se eliminó el "by construction" sin mecanismo.
|
|
57
|
+
- readiness: sin `--section` en el llamado documentado (un heading mismatch cereaba la
|
|
58
|
+
dimensión más pesada en silencio); UNMEASURED documentado.
|
|
59
|
+
- sys-doc degradado a reporting opcional (era la instancia más clara de scope creep).
|
|
60
|
+
- `improve-deep` → `improve` (la skill real); protocolo tracked-md generalizado.
|
|
61
|
+
|
|
62
|
+
## Kit
|
|
63
|
+
- `dev-loop.config.json`: version 1.3.0, `qa_tools_order` con `improve`, repos de ejemplo
|
|
64
|
+
genéricos (`backend-api`/`mobile-app` — antes traía repos del proyecto del autor).
|
|
65
|
+
- `templates/CONSTITUTION.md`: enforcement honesto (flag-blocker), CWE-1124 para anidación
|
|
66
|
+
(era 1121), tag CWE-1074 removido de YAGNI (no mapea).
|
|
67
|
+
- `README.md`: las SEIS skills (faltaban `characterize` y `reverse-discovery` — justo donde
|
|
68
|
+
vive el flujo golden), on-ramp de migración, subcomandos nuevos, audiencia, generalización.
|
|
69
|
+
- `workbench-doctor.sh`: sonda characterize/reverse-discovery/improve (sin improve-deep).
|
|
70
|
+
- `VERSION`: 1.3.0.
|
|
71
|
+
|
|
72
|
+
## Deferido (consciente, no olvidado)
|
|
73
|
+
- rebuild: densidad de asserts por test-file en la firma (anti tests-preservados-destripados).
|
|
74
|
+
- Perfiles A-E mecanizados en config (`--profile`). Hoy: heurística de proceso, marcada como tal.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# uscha-kit 1.30.0 — gate de dependencias: supply-chain hecho visible (2026-07-05)
|
|
2
|
+
|
|
3
|
+
Origen: intake de research (SLR de agentic-AI arXiv:2605.15245 + survey de seguridad de
|
|
4
|
+
agentes). De los 4 papers, la única mejora genuina y doctrina-pura: el modelo de amenaza
|
|
5
|
+
"el agente mete una dependencia sin vetear (o envenenada)" — que Uscha no cubría. La
|
|
6
|
+
CONSTITUTION ya dice "0 dependencias nuevas sin aprobación", pero como **prosa**. Esto la
|
|
7
|
+
hace visible. Smoke suite: 181/181.
|
|
8
|
+
|
|
9
|
+
## Qué hace (mínimo, sin overengineering)
|
|
10
|
+
|
|
11
|
+
- **`gate-check` flaguea dependencias nuevas** como señal **BLANDA** (avisa; gatea con
|
|
12
|
+
`--strict`), NO como subcomando nuevo: una dep nueva es exactamente la categoría que
|
|
13
|
+
`gate-check` ya cubre ("el cambio hace algo que necesita sign-off humano" — tests
|
|
14
|
+
borrados, thresholds bajados, secretos). Reusa toda la maquinaria: cero config nuevo,
|
|
15
|
+
cero subcomando.
|
|
16
|
+
- Detecta líneas AGREGADAS con forma de dependencia en los manifests de los 9 stacks
|
|
17
|
+
(`package.json`, `requirements*.txt`, `pyproject.toml`, `Cargo.toml`, `go.mod`,
|
|
18
|
+
`pom.xml`, `build.gradle(.kts)`, `Gemfile`, `Podfile`, `*.csproj`). En `--json`:
|
|
19
|
+
campo `new_dependencies`.
|
|
20
|
+
- **Advisory por default**: verdict `REVIEW`, exit 0. Con `--strict`, la señal blanda
|
|
21
|
+
(deps + supresiones + asserts removidos) gatea exit 1.
|
|
22
|
+
|
|
23
|
+
## Por qué así (decisiones de la doctrina)
|
|
24
|
+
|
|
25
|
+
- **NO subcomando nuevo** — hubiera sido fragmentación/ceremonia. Extender `gate-check`
|
|
26
|
+
es el tamaño correcto: mismo concepto (integridad del cambio), misma maquinaria.
|
|
27
|
+
- **Blando, no BLOCKER** — agregar una dependencia suele ser legítimo; solo necesita que
|
|
28
|
+
un humano la vea. Bloquear por default mataría el gate (se desactiva). El humano
|
|
29
|
+
declara `--strict` si su dominio lo exige (procedencia, misma doctrina que 1.17.0).
|
|
30
|
+
- **Heurística honesta** — matcheo de líneas por manifest, no un resolver semántico de
|
|
31
|
+
dependencias. Un falso positivo (bump de versión, key no-dep) es benigno porque es
|
|
32
|
+
advisory. Documentado en el código.
|
|
33
|
+
|
|
34
|
+
## Lo que NO entró del intake (anti-overengineering)
|
|
35
|
+
|
|
36
|
+
- **Ruteo de modelo por perfil de riesgo** (de ALMAS, arXiv:2510.03463): diferido —
|
|
37
|
+
depende de mecanizar los perfiles A–E (que no existen) y vive en la capa de
|
|
38
|
+
orquestación, no en el engine model-agnostic.
|
|
39
|
+
- **Meta-RAG / índice de repo**: diferido — no hay problema de perf medido en el walk del
|
|
40
|
+
waste-check; índice especulativo = YAGNI.
|
|
41
|
+
|
|
42
|
+
## Smoke (T7b, 4 checks)
|
|
43
|
+
|
|
44
|
+
Dep nueva en `package.json` → `REVIEW` + listada en `new_dependencies`; sin `--strict`
|
|
45
|
+
exit 0 (advisory); con `--strict` exit 1; y un diff de código normal NO flaguea dep
|
|
46
|
+
(sin falso positivo).
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# uscha-kit 1.31.0 — freshness de evidencia + gate de doc-version (2026-07-05)
|
|
2
|
+
|
|
3
|
+
Origen: review externo (Codex) que encontró al kit fallando su **propia** regla de
|
|
4
|
+
truth-pass. Dos findings reales, un aprendizaje meta: *lo que no mecanizás, deriva*.
|
|
5
|
+
Smoke suite: 185/185.
|
|
6
|
+
|
|
7
|
+
## #3 — Freshness de evidencia (el que ataca el core)
|
|
8
|
+
|
|
9
|
+
`gate-check`/`readiness` cerraban o vetaban un AC por el testcase JUnit sin chequear si
|
|
10
|
+
el reporte estaba **vigente**. Un `TEST-*.xml` viejo (surefire/gradle no lo limpian sin
|
|
11
|
+
`clean`) podía mantener un AC en falso-verde o vetarlo en falso-rojo. Evidencia stale
|
|
12
|
+
no es evidencia — atacaba directo "la evidencia decide".
|
|
13
|
+
|
|
14
|
+
- **`_ac_tags` descarta reportes STALE**: un reporte más viejo que el código fuente del
|
|
15
|
+
repo (correlación `mtime(fuente) > mtime(reporte)`) se DESCARTA. Un AC respaldado solo
|
|
16
|
+
por reportes stale queda **UNMEASURED** — el mismo patrón honesto que el engine ya usa
|
|
17
|
+
para coverage/static que no corrió, nunca falso-verde ni falso-rojo.
|
|
18
|
+
- **Por qué correlación con la fuente y no advisory** (a diferencia de waste/deps): acá
|
|
19
|
+
honrar evidencia stale rompería el núcleo del método. La correlación no tiene falso
|
|
20
|
+
positivo en el flujo real (editar → testear deja el reporte como lo más nuevo) y sí
|
|
21
|
+
detecta el caso peligroso (tests no re-corridos). Sin fuente que correlacionar (repo
|
|
22
|
+
sin código) → nunca marca stale (evita falso positivo).
|
|
23
|
+
- Campo `stale_reports` en `readiness --json` + advisory en la vista default.
|
|
24
|
+
- **Scope honesto**: `junit_test_count` (el conteo *aproximado*) mantiene el límite —
|
|
25
|
+
su blast radius es menor (no cierra ACs). Diferido, documentado en el código.
|
|
26
|
+
|
|
27
|
+
## #1/#2 — Doc drift + gate de doc-version (el meta-fix)
|
|
28
|
+
|
|
29
|
+
El README raíz declaraba v1.24.0 / 23 subcomandos / 139 smoke mientras el engine estaba
|
|
30
|
+
en 1.30.0 / 24 / 181; el README del kit copiaba un `uscha-devloop.config.json` inexistente
|
|
31
|
+
y decía "6 skills" (son 7). El sync era QUÍNTUPLE pero solo cubría 5 archivos-máquina;
|
|
32
|
+
los README se truth-passeaban por **disciplina, no por máquina** — y la disciplina derivó.
|
|
33
|
+
|
|
34
|
+
- **READMEs corregidos** (raíz + kit): versión, conteo de subcomandos, cadena de
|
|
35
|
+
changelog, filename del config, conteo de skills, y el título `# dev-loop kit` →
|
|
36
|
+
`# uscha-kit` (miss del rebrand).
|
|
37
|
+
- **`gate de doc-version` mecanizado** (smoke T52): un marcador invisible
|
|
38
|
+
`<!-- uscha:version -->` en la línea canónica de versión de cada README; el smoke
|
|
39
|
+
verifica que coincida con `VERSION`. Robusto sin falso positivo: la cadena de changelog
|
|
40
|
+
lista todas las versiones históricas legítimamente, así que solo se gatea la línea
|
|
41
|
+
marcada. Esto extiende el T44 (sync quíntuple) a los docs.
|
|
42
|
+
|
|
43
|
+
## Lo que NO entró del review (con criterio)
|
|
44
|
+
|
|
45
|
+
- **#4 CONSTITUTION detección-por-agente**: by-design y documentado; muchos invariantes ya
|
|
46
|
+
se mecanizan (simplicity/waste/gate/golden/pit). Un evento "constitution reviewed" es
|
|
47
|
+
candidato futuro, no urgente.
|
|
48
|
+
- **#5 contrato de QA vendor-neutral** + **#8 acoplar cierre de AC ↔ pit-check**: válidos,
|
|
49
|
+
doctrina-consistentes; van al backlog (el mecanismo #8 ya existe — falta el acople).
|
|
50
|
+
- **#6 separar spec canónica del adapter Claude**: higiene de docs, no defecto.
|
|
51
|
+
- **#7 partir `qa_ledger.py`**: NO. Partir un archivo estable con 185 smoke checks es el
|
|
52
|
+
"refactor de lo que no está roto" que el propio CLAUDE.md prohíbe; YAGNI hasta que la
|
|
53
|
+
concentración cause un bug real.
|
|
54
|
+
|
|
55
|
+
## Smoke (T51 + T52, 4 checks)
|
|
56
|
+
|
|
57
|
+
T51: reporte fresco → AC-1 cierra medido, `stale_reports` vacío (sin falso positivo);
|
|
58
|
+
código más nuevo → reporte STALE descartado, AC-1 UNMEASURED; advisory visible.
|
|
59
|
+
T52: los dos READMEs declaran la versión actual (drift de docs = exit 1).
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# uscha-kit 1.32.0 — /mirador: vista bird's-eye + `dashboard --json` (2026-07-05)
|
|
2
|
+
|
|
3
|
+
La 8va skill (`uscha-mirador`) y un subcomando nuevo (`dashboard`, el 25º) que pinta el
|
|
4
|
+
estado del proyecto de un vistazo. **Read-only, determinista, cero narración del LLM.**
|
|
5
|
+
Smoke suite: 189/189.
|
|
6
|
+
|
|
7
|
+
## Pieza 1 — `qa_ledger.py dashboard [--json]`
|
|
8
|
+
|
|
9
|
+
Agrega SOLO estado que el ledger YA tiene al contrato `DATA` del template mirador
|
|
10
|
+
(readiness, subscores, phases, specs, adrs, inv, capas, loops, snapshots, evidence).
|
|
11
|
+
`--json` imprime el objeto; sin flags, un veredicto de una línea.
|
|
12
|
+
|
|
13
|
+
**Truth-pass estricto — under-claim, then wire.** Un campo sin fuente en el ledger sale
|
|
14
|
+
`null`/`[]` (el template degrada), **nunca se inventa**. La honestidad primero:
|
|
15
|
+
|
|
16
|
+
- **Real hoy**: `readiness` (score/band, reusando `readiness --json` VERBATIM — mismo KPI,
|
|
17
|
+
sin drift), `subscores.coverage`, `subscores.{simplicity,waste,rebuild,golden}` desde
|
|
18
|
+
los gates persistidos (`_gate_rollup`; `val` = null porque el ledger guarda pass/fail,
|
|
19
|
+
no un score 0-100), `loops` (iters + estado por repo), `inv` (7 nombres fijos; status
|
|
20
|
+
del gate donde mapea, si no null), `project`, `phases` (proyección determinista del
|
|
21
|
+
readiness sobre los 8 nodos).
|
|
22
|
+
- **`null`/`[]` por diseño** (el engine no lo trackea): `specs` (trackea `AC-nn`, no
|
|
23
|
+
`SPEC-nnn`), `capas` (no puntúa las 6 capas de verdad), `evidence` (steps[] es log
|
|
24
|
+
plano). Cada uno destraba un panel el día que exista la fuente — quedan en el backlog.
|
|
25
|
+
|
|
26
|
+
## Add-ons aprobados (baratos y honestos)
|
|
27
|
+
|
|
28
|
+
- **ADRs** (`adrs`): glob read-only de `docs/adr/*.md` (`--adr-dir` configurable) — id de
|
|
29
|
+
un token `ADR-<n>`, título del primer heading, status de una línea `Status:`. `[]` si no
|
|
30
|
+
hay dir.
|
|
31
|
+
- **Time-lapse prospectivo** (`snapshots`): `readiness --record` (opt-in) persiste el
|
|
32
|
+
readiness del momento en `ledger.readiness_history`. `readiness` sigue **read-only por
|
|
33
|
+
default**; el historial se llena **solo hacia adelante** (no se backfillea). El dashboard
|
|
34
|
+
lo consume, nunca escribe. `reached` = proyección determinista del score (como la band).
|
|
35
|
+
|
|
36
|
+
## Pieza 2 — skill `uscha-mirador`
|
|
37
|
+
|
|
38
|
+
`SKILL.md` + `mirador.template.html`. Flujo: corre `dashboard --json` → inyecta ese JSON
|
|
39
|
+
en el template reemplazando la región entre `/*MIRADOR_DATA_START*/` y
|
|
40
|
+
`/*MIRADOR_DATA_END*/` → escribe `mirador.html` en la raíz del proyecto → lo abre
|
|
41
|
+
best-effort (`start`/`open`/`xdg-open`), sin fallar en headless/CI. El demo del template
|
|
42
|
+
queda como **fallback offline**. El skill cablea, no calcula: los números vienen del ledger.
|
|
43
|
+
|
|
44
|
+
## Smoke (T53, 4 checks)
|
|
45
|
+
|
|
46
|
+
Contrato completo con las 12 claves; `specs`/`capas` `[]` (truth-pass); `adrs` del glob
|
|
47
|
+
(accepted→done, proposed→prog); `readiness` del dashboard == `readiness --json` (sin
|
|
48
|
+
drift); `snapshots` vacío hasta `readiness --record`, luego poblado (add-on prospectivo);
|
|
49
|
+
`inv` mapea el gate persistido por su kind REAL (`pit-check`→Tests efectivos, no un typo
|
|
50
|
+
mudo — hallazgo del review fresco).
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# uscha-kit 1.33.0 — mirador session telemetry (tokens / time / model, per-model) (2026-07-05)
|
|
2
|
+
|
|
3
|
+
The mirador gains a **session-telemetry** strip: how many tokens, how much wall time, which
|
|
4
|
+
model(s), at what effort — with a **per-model breakdown** (so you can see if the expensive
|
|
5
|
+
model is being burned on cheap work). Smoke suite: 190/190.
|
|
6
|
+
|
|
7
|
+
**The engine is UNTOUCHED.** `qa_ledger.py` stays model-agnostic and never sees a token —
|
|
8
|
+
this is vendor telemetry (Claude Code), and it enters ONLY through the mirador skill (the
|
|
9
|
+
vendor adapter). No new subcommand; 25 stays 25.
|
|
10
|
+
|
|
11
|
+
## What ships (all in the `uscha-mirador` skill)
|
|
12
|
+
|
|
13
|
+
- **Segregated strip in `mirador.template.html`**: labeled *"Claude Code · session telemetry —
|
|
14
|
+
vendor-reported, narrated not measured"*, dashed border, at the foot — **visually apart** from
|
|
15
|
+
the measured panels. Shows totals (tokens in/out, wall time, effort, sessions) and, when more
|
|
16
|
+
than one model was used, a **per-model row** (`opus-4-8 240k → 41k · 1.3h`).
|
|
17
|
+
- **`telemetry-extract.py`** (shipped in the skill folder, stdlib, standalone): parses a Claude
|
|
18
|
+
Code session transcript (`*.jsonl`) — each assistant turn's `usage` (`input_tokens` +
|
|
19
|
+
`cache_*` + `output_tokens`) and `model` — sums per model, computes wall time from the
|
|
20
|
+
timestamps, and appends ONE line to the sidecar. Best-effort: bad/old schemas degrade, never
|
|
21
|
+
crash; no usage → nothing appended.
|
|
22
|
+
- **Sidecar contract** `.uscha/telemetry.jsonl` (append-only, one JSON object per session, with a
|
|
23
|
+
`by_model` breakdown). Portable, greppable, git-ignorable. Chosen over `localStorage` because a
|
|
24
|
+
real inspectable artifact is coherent with the doctrine — you can audit where the number came
|
|
25
|
+
from. The skill reads it, aggregates across lines (merging `by_model` per model), and merges a
|
|
26
|
+
`telemetry` object into `DATA` before injection.
|
|
27
|
+
|
|
28
|
+
## The doctrinal boundary (non-negotiable)
|
|
29
|
+
|
|
30
|
+
Telemetry is **narrated by the vendor, not measured by the engine**. It is neither a fact-gate
|
|
31
|
+
nor a guess-advisor — so it is **shown, never gated, never fed into readiness**, and rendered in
|
|
32
|
+
a strip kept apart from the measured panels. Telemetry answers *"what did it cost"*; the measured
|
|
33
|
+
panels answer *"is it correct"*. Mixing them would dilute *measured beats narrated* — so they stay
|
|
34
|
+
apart. The mirador template also degrades: no sidecar → no strip (verified running the page's JS
|
|
35
|
+
under Node, with and without telemetry).
|
|
36
|
+
|
|
37
|
+
## Also
|
|
38
|
+
|
|
39
|
+
- The `mirador.template.html` UI is now in **English** (it was the last Spanish-only product HTML;
|
|
40
|
+
the ES/EN decks stay bilingual by design).
|
|
41
|
+
|
|
42
|
+
## Smoke (T54)
|
|
43
|
+
|
|
44
|
+
A synthetic 2-model transcript → `telemetry-extract.py` → the sidecar line sums tokens
|
|
45
|
+
(input + cache) and output correctly, computes wall time from the timestamps, and carries a
|
|
46
|
+
2-entry `by_model` breakdown; a corrupt line is skipped, not fatal.
|