@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,55 @@
|
|
|
1
|
+
# uscha-kit 1.34.0 — mirador: project name + live second-screen view (2026-07-05)
|
|
2
|
+
|
|
3
|
+
Two operator asks: (1) the project name, clear at the top; (2) a mirador you can **watch on a
|
|
4
|
+
second screen** while you keep coding in the terminal with the agent. Smoke suite: 195/195.
|
|
5
|
+
|
|
6
|
+
## Project name (from config, shown at the top)
|
|
7
|
+
|
|
8
|
+
- `dashboard` emits `project` from `uscha.config.json`'s `"project"` (or `"name"`); if unset, it
|
|
9
|
+
falls back to the joined repo names (truth-pass — no invented name). This is the ONE engine
|
|
10
|
+
touch this release: a project name is human-set config metadata, not vendor/LLM data, so the
|
|
11
|
+
engine stays model-agnostic.
|
|
12
|
+
- `uscha-discovery` asks the project name **first** and writes it to the config.
|
|
13
|
+
- The mirador template shows it as a **prominent title** at the top.
|
|
14
|
+
|
|
15
|
+
## Live second-screen view
|
|
16
|
+
|
|
17
|
+
- **`mirador-render.py`** (standalone, in the skill folder): runs `dashboard --json`, merges the
|
|
18
|
+
sidecar telemetry (in the adapter, NEVER the engine), injects `const DATA`, writes
|
|
19
|
+
`mirador.html`. `--refresh N` injects a `<meta http-equiv="refresh">`.
|
|
20
|
+
- **`mirador-watch.sh` / `.ps1`**: re-render every N seconds (default 30) from the current
|
|
21
|
+
ledger. Open `mirador.html` on a second monitor; it reloads on its own. **No server.**
|
|
22
|
+
- Honest limit: as live as the **ledger** — the picture changes at the dev-loop's measured
|
|
23
|
+
checkpoints (snapshots, gates, `readiness --record`), not per keystroke.
|
|
24
|
+
|
|
25
|
+
## Watch-safe telemetry (gotcha fix)
|
|
26
|
+
|
|
27
|
+
`telemetry-extract.py` now **upserts by session** (default key = transcript basename): a refresh
|
|
28
|
+
loop re-runs the extractor without duplicating the session's line, so the aggregated totals
|
|
29
|
+
never inflate. (Without this, watch mode would over-count tokens every tick.)
|
|
30
|
+
|
|
31
|
+
## Boundary intact
|
|
32
|
+
|
|
33
|
+
Telemetry is still vendor-narrated, merged ONLY by the adapter (`mirador-render.py`), never by
|
|
34
|
+
`qa_ledger.py`; shown, never gated, never fed into readiness. The template still degrades (no
|
|
35
|
+
sidecar → no strip).
|
|
36
|
+
|
|
37
|
+
## Truth-pass fix: skill-count drift (doctor + plugin)
|
|
38
|
+
|
|
39
|
+
When `uscha-mirador` shipped (1.32.0), two registries were not updated (caught here):
|
|
40
|
+
- `doctor`'s `USCHA_SKILLS` list was missing `uscha-mirador` → it reported `7/7` for 8 skills.
|
|
41
|
+
- `plugin.json` / `marketplace.json` **descriptions** said "7 skills / 24 subcommands" (the
|
|
42
|
+
plugin *install* was fine — it points at the skills directory — but the prose was stale).
|
|
43
|
+
Both fixed (8 skills / 25 subcommands), and **mechanized** so it can't drift again: smoke
|
|
44
|
+
**T57** asserts `USCHA_SKILLS` equals the `uscha-*` skill directories on disk. (The doc-version
|
|
45
|
+
gate T52 covers versions; T57 now covers the skill roster.)
|
|
46
|
+
|
|
47
|
+
## Smoke (T54 upsert + T55 project + T56 render + T57 skill-roster)
|
|
48
|
+
|
|
49
|
+
Extractor re-run → still ONE line (upsert); config `project` → dashboard emits it, absent →
|
|
50
|
+
repo-name fallback; `mirador-render.py` → `mirador.html` carrying the project name, merged
|
|
51
|
+
telemetry, and the meta-refresh; the doctor's skill list matches the skills on disk.
|
|
52
|
+
|
|
53
|
+
The fresh review also caught two robustness gaps in `mirador-render.py` (unguarded `json.loads`
|
|
54
|
+
and template read) — now they return a clean error instead of a traceback (it runs in a watch
|
|
55
|
+
loop, so a clean non-zero is what the loop expects).
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# CHANGELOG 1.35.0 — execution policy routing
|
|
2
|
+
|
|
3
|
+
## La idea
|
|
4
|
+
|
|
5
|
+
Uscha ya medía el estado, y Mirador ya mostraba telemetría observada de modelo/tiempo/tokens. Faltaba una capa distinta: **la política de ejecución** que le dice al operador qué está haciendo el método en cada fase y qué tier/modelo/effort conviene usar.
|
|
6
|
+
|
|
7
|
+
## Nuevo
|
|
8
|
+
|
|
9
|
+
- `defaults.execution_policy` en `uscha.config.json`:
|
|
10
|
+
- `default`: tier/model/effort base.
|
|
11
|
+
- `phases.<idea|disc|spec|adr|build|qa|verify|prod>`: `method`, `tier`, `model`, `effort`, `uncorrelated`.
|
|
12
|
+
- Nuevo subcomando read-only:
|
|
13
|
+
- `qa_ledger.py execution-policy --phase qa`
|
|
14
|
+
- `qa_ledger.py execution-policy --json`
|
|
15
|
+
- `dashboard --json` agrega:
|
|
16
|
+
- `execution_policy` top-level.
|
|
17
|
+
- `phase.execution` en cada nodo del trail.
|
|
18
|
+
- Mirador renderiza un panel **Execution policy** con metodología/tier/model/effort por fase.
|
|
19
|
+
- `uscha-devloop` ahora exige imprimir una línea antes de arrancar cada fase para que el humano vea la intención del método y la selección de modelo/effort.
|
|
20
|
+
|
|
21
|
+
## Doctrina
|
|
22
|
+
|
|
23
|
+
Esto **no** es un gate y **no** entra al score de readiness. Es metadata de orquestación/costo/riesgo. La regla sigue intacta: facts block, guesses advise; la política guía la ejecución, la evidencia decide.
|
|
24
|
+
|
|
25
|
+
## Smoke
|
|
26
|
+
|
|
27
|
+
- `bash uscha-kit/tests/smoke-engine.sh`: 199 ok / 0 fail.
|
|
28
|
+
- Nuevos checks:
|
|
29
|
+
- T58: `execution-policy` devuelve metodología/model/effort y `dashboard` lo expone sin contaminar readiness.
|
|
30
|
+
- T59: `mirador-render` preserva el panel bird's-eye de execution_policy.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# CHANGELOG 1.36.0 — discovery intake: production findings + spec-doubt
|
|
2
|
+
|
|
3
|
+
## La idea
|
|
4
|
+
|
|
5
|
+
Uscha no puede terminar en el merge si la realidad vuelve con evidencia. Dos señales antes quedaban fuera del ledger: un bug encontrado en producción y una SPEC que el builder descubre dudosa o equivocada. Este release les da una entrada formal al siguiente ciclo de discovery.
|
|
6
|
+
|
|
7
|
+
## Nuevo
|
|
8
|
+
|
|
9
|
+
- `qa_ledger.py production-finding`:
|
|
10
|
+
- crea `PF-001`, `PF-002`, ... con `repo`, `severity`, `source`, `title`, `evidence`.
|
|
11
|
+
- `--resolve --id PF-001 --note "..."` registra que el hallazgo entró al próximo ciclo.
|
|
12
|
+
- `qa_ledger.py spec-doubt`:
|
|
13
|
+
- crea `SD-001`, `SD-002`, ... con `kind` (`spec-doubt`, `spec-wrong`, `ambiguous`, `missing-acceptance`), `repo`, `severity`, `note`, `evidence`.
|
|
14
|
+
- `--resolve --id SD-001 --decision "SPEC amended"` registra la revisión humana.
|
|
15
|
+
- `readiness --json` agrega `discovery_intake` y facts:
|
|
16
|
+
- `production_findings_open`
|
|
17
|
+
- `spec_doubts_open`
|
|
18
|
+
- La vista default de `readiness` habla solo cuando importa: imprime una línea si hay production findings o spec-doubts abiertos.
|
|
19
|
+
- `phase` deriva `escalated` si hay `spec-doubt` abierto o production finding gateado abierto; no hay `pr-ready` mientras la SPEC esté dudosa o la producción haya devuelto una señal severa.
|
|
20
|
+
- `dashboard --json` transporta `discovery_intake` para Mirador/adapters.
|
|
21
|
+
|
|
22
|
+
## Doctrina
|
|
23
|
+
|
|
24
|
+
- Production finding = hecho de campo. Entra al ledger, no a una nota perdida.
|
|
25
|
+
- SPEC-WRONG/spec-doubt = escape hatch legítimo del builder. El agente NO decide silenciosamente entre desviarse de la SPEC o transcribir una mentira.
|
|
26
|
+
- Resolver exige un acto registrado: feedback incorporado, SPEC amendada, o revisión humana explícita.
|
|
27
|
+
|
|
28
|
+
## Smoke
|
|
29
|
+
|
|
30
|
+
- `bash uscha-kit/tests/smoke-engine.sh`: 207 ok / 0 fail.
|
|
31
|
+
- Nuevos checks:
|
|
32
|
+
- T60: production finding crea PF-001, aparece en `discovery_intake`, avisa en readiness default, y se limpia al resolver.
|
|
33
|
+
- T61: spec-doubt crea SD-001, aparece en `discovery_intake`, `phase` deriva `escalated`, y se limpia al resolver.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# CHANGELOG 1.37.0 ? ADR experiments: visible hypotheses
|
|
2
|
+
|
|
3
|
+
Decision #10 from the deferred analysis is implemented narrowly: an ADR can now say
|
|
4
|
+
`Status: Experiment` when the decision is a bounded hypothesis that needs real feedback.
|
|
5
|
+
|
|
6
|
+
## What changed
|
|
7
|
+
|
|
8
|
+
- `dashboard --json` now preserves both ADR layers:
|
|
9
|
+
- legacy `status` remains the coarse Mirador bucket (`done` / `prog` / `todo`);
|
|
10
|
+
- `adr_status` preserves the authored ADR status (`accepted`, `proposed`, `experiment`, etc.).
|
|
11
|
+
- Experimental ADRs carry advisory metadata:
|
|
12
|
+
- `experiment_valid`
|
|
13
|
+
- `experiment_missing`
|
|
14
|
+
- `review_by`
|
|
15
|
+
- `review_trigger`
|
|
16
|
+
- `feedback_signal`
|
|
17
|
+
- `expired`
|
|
18
|
+
- Top-level `adr_experiments` summarizes `open`, `malformed`, `expired`, and `ids`.
|
|
19
|
+
- Mirador renders experiment ADRs as `experiment`, `experiment invalid`, or `experiment overdue`.
|
|
20
|
+
- `Status: Experiment` is intentionally **not** readiness scoring and **not** a hard PR gate.
|
|
21
|
+
|
|
22
|
+
## Required sections for `Status: Experiment`
|
|
23
|
+
|
|
24
|
+
An experiment ADR must include:
|
|
25
|
+
|
|
26
|
+
- `Hypothesis`
|
|
27
|
+
- `Feedback Signal`
|
|
28
|
+
- `Review By` or `Review Trigger`
|
|
29
|
+
- `Promote Criteria`
|
|
30
|
+
- `Rollback / Supersede Criteria`
|
|
31
|
+
|
|
32
|
+
Missing/expired metadata is visible/advisory so the operator does not confuse a hypothesis with
|
|
33
|
+
an accepted decision.
|
|
34
|
+
|
|
35
|
+
## Smoke
|
|
36
|
+
|
|
37
|
+
- Full smoke: `209 ok ? 0 fail`.
|
|
38
|
+
- New T62 covers:
|
|
39
|
+
- valid experiment ADR exposed in `dashboard --json`;
|
|
40
|
+
- malformed/expired experiment counted as advisory;
|
|
41
|
+
- Mirador renders `experiment` without changing readiness.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# uscha-kit 1.38.0 ? contract closure loop
|
|
2
|
+
|
|
3
|
+
## Added
|
|
4
|
+
|
|
5
|
+
- `spec-change-request`: records a human contract-change bridge from evidence/doubt to SPEC/ADR amendment, surfaces it in `readiness --json`, and derives `phase=escalated` while open.
|
|
6
|
+
- `golden-diff --labels golden-labels.json --json`: reports approved fixture intent as `intended`, `observed-accidental`, or `unknown` without weakening byte comparison.
|
|
7
|
+
- `summary --json` now includes `post_merge_calibration` counts for production findings, SPEC doubts, and SPEC change requests so retros can calibrate the method from real reopen signals.
|
|
8
|
+
|
|
9
|
+
## Verification
|
|
10
|
+
|
|
11
|
+
- Smoke target: 216/216 green.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# uscha-kit 1.39.0 ? universal machine installer
|
|
2
|
+
|
|
3
|
+
## Added
|
|
4
|
+
|
|
5
|
+
- `install-uscha.py`: one stdlib machine installer for Codex and Claude.
|
|
6
|
+
- Codex target creates a personal local plugin at `~/plugins/uscha` and updates `~/.agents/plugins/marketplace.json`.
|
|
7
|
+
- Claude target installs global skills/hooks under `~/.claude`.
|
|
8
|
+
- Supports `install`, `doctor`, `version`, `init`, `--dry-run`, testable `--home`, and `--mode copy|link`.
|
|
9
|
+
- Codex plugin manifest at `.codex-plugin/plugin.json` for plugin-first adoption.
|
|
10
|
+
- Skill fallback examples now include Codex plugin/raw-skill install paths, not only `~/.claude`.
|
|
11
|
+
|
|
12
|
+
## Verification
|
|
13
|
+
|
|
14
|
+
- Smoke target: 222/222 green.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# dev-loop-kit 1.4.0 — adapter `type: python` (2026-07-02)
|
|
2
|
+
|
|
3
|
+
El desbloqueante del dogfooding: el engine ahora mide repos Python (pytest + ruff +
|
|
4
|
+
mypy + coverage.py). Diseño: `docs/HANDOFF_python-adapter_dev-loop-kit.md` +
|
|
5
|
+
`docs/HANDOFF_python-adapter_ADDENDUM.md` (los 2 bugs A1/A2 de la revisión están
|
|
6
|
+
incorporados). Smoke suite: 24/24 (17 existentes maven/flutter intactos + 7 python).
|
|
7
|
+
|
|
8
|
+
## Engine (qa_ledger.py)
|
|
9
|
+
|
|
10
|
+
- **`python_coverage()`** — Cobertura `coverage.xml` (`pytest --cov --cov-report=xml`),
|
|
11
|
+
atributos `lines-covered`/`lines-valid`; primer match gana (`coverage.xml`,
|
|
12
|
+
`reports/coverage.xml`). Reporte ausente o ilegible ⇒ `report_found: False`
|
|
13
|
+
(UNMEASURED — jamás un número inventado).
|
|
14
|
+
- **`python_test_count()`** — JUnit XML de `pytest --junitxml`. **Maneja el root
|
|
15
|
+
ENVUELTO** (`<testsuites><testsuite …>`, familia xunit2 del pytest moderno) además
|
|
16
|
+
del root plano — leer atributos del wrapper contaría 0 en silencio (ADDENDUM A2).
|
|
17
|
+
- **`parse_ruff()`** — `ruff check --output-format=json`; severidades: `S<dígito>`
|
|
18
|
+
(bandit/security, anclado para no pisar SIM/SLF/SLOT) y `E9*`/`F82*` (errores
|
|
19
|
+
reales) → HIGH, `B<dígito>` (bugbear) → MEDIUM, resto → LOW. **`code: null`**
|
|
20
|
+
(syntax error del ruff moderno ≥0.5) → HIGH siempre — sin esto, la rotura real
|
|
21
|
+
pasaba el gate como LOW en silencio (hallazgo del review de contexto fresco).
|
|
22
|
+
- **`parse_mypy()`** — salida de texto (`file:line: error: msg [code]`);
|
|
23
|
+
error → HIGH, warning → MEDIUM, note → INFO.
|
|
24
|
+
- **`ingest-gate`** — branch por `type` del repo: python busca `reports/ruff.json` /
|
|
25
|
+
`reports/mypy.txt` (o `--ruff`/`--mypy` explícitos); combinado se loguea como
|
|
26
|
+
`python-qa-gate`. Mismo contrato de ausencia que Java.
|
|
27
|
+
- **Guard UNMEASURED ampliado** (ADDENDUM A1): `static_unmeasured` ahora aplica a
|
|
28
|
+
`maven` Y `python` — un repo python cuyos linters nunca corrieron puntúa 0.0 en la
|
|
29
|
+
dimensión static, no 1.0 (habría reintroducido "el silencio es éxito" justo en el
|
|
30
|
+
repo del dogfooding).
|
|
31
|
+
- **LOC python**: test = `tests/`/`test/` en el path o `test_*.py`/`*_test.py`;
|
|
32
|
+
prod = el resto de los `.py` (src layout o paquete raíz). `SKIP_DIRS` suma
|
|
33
|
+
`.venv`, `venv`, `.tox`, `__pycache__`, `.mypy_cache`, `.ruff_cache`,
|
|
34
|
+
`.pytest_cache` (sin esto, el LOC contaría el virtualenv entero).
|
|
35
|
+
- `_rel_src()` reconoce paths repo-relativos `src/...` (como los emiten ruff/mypy)
|
|
36
|
+
para IDs de finding estables. **Nota de migración**: si un linter Java emitía paths
|
|
37
|
+
relativos `src/...` (poco común — checkstyle/PMD suelen emitir absolutos), sus
|
|
38
|
+
finding-IDs cambian en 1.4.0; un ledger no debería cruzar el upgrade — re-baselinear
|
|
39
|
+
con un ingest fresco después de actualizar.
|
|
40
|
+
- `SOURCE_EXT`: `"python": {".py"}`; `.py` también en `generic`.
|
|
41
|
+
|
|
42
|
+
## Ya cubierto sin cambios (ADDENDUM A3)
|
|
43
|
+
|
|
44
|
+
- simplicity-check: `.py` ya estaba en `_SIMPLICITY_CODE_EXT`.
|
|
45
|
+
- gate-check: ya reconocía `test_*.py`, `def test_`, `# noqa`, `# type: ignore`.
|
|
46
|
+
|
|
47
|
+
## Config / docs
|
|
48
|
+
|
|
49
|
+
- `dev-loop.config.json`: `test_command_python` + repo de ejemplo `data-lib`; version 1.4.0.
|
|
50
|
+
- Kit README: tabla de reportes Python; SKILL.md y docs actualizan
|
|
51
|
+
`maven|flutter` → `maven|flutter|python`; refs de versión vigente → 1.4.0 (ES+EN).
|
|
52
|
+
|
|
53
|
+
## Smoke (tests/smoke-engine.sh)
|
|
54
|
+
|
|
55
|
+
- `repo-c` (`type: python`) con fixtures sintéticos: Cobertura 8/10 → 80.0%,
|
|
56
|
+
junit ENVUELTO → 5 tests, LOC prod=3/test=2, ruff 2 findings (1 gateado),
|
|
57
|
+
mypy 1 error (gateado), UNMEASURED pre-ingest → medido post-ingest.
|
|
58
|
+
|
|
59
|
+
## Criterio pendiente (fase piloto)
|
|
60
|
+
|
|
61
|
+
Criterio 2 del HANDOFF — dry-run de solo lectura contra el repo piloto real
|
|
62
|
+
(coverage ±0.1 vs pytest-cov, test count exacto, ruff/mypy en 0 sin UNMEASURED).
|
|
63
|
+
Se corre desde la sesión del proyecto piloto consumiendo este kit.
|
|
64
|
+
|
|
65
|
+
## Diferido consciente (sin cambios desde 1.3.0)
|
|
66
|
+
|
|
67
|
+
- rebuild: densidad de asserts por test-file en la firma.
|
|
68
|
+
- Perfiles A-E mecanizados (`--profile`).
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# uscha-kit 1.40.0
|
|
2
|
+
|
|
3
|
+
## Added
|
|
4
|
+
|
|
5
|
+
- Added npm/npx package router (`@andresmassello/uscha`) with `uscha` and `uscha-kit` CLI bins.
|
|
6
|
+
- Added smoke coverage for the Node router delegating to the canonical Python installer.
|
|
7
|
+
|
|
8
|
+
## Changed
|
|
9
|
+
|
|
10
|
+
- Documented npm-first install commands for public adoption while keeping `install-uscha.py` as the source of truth.
|
|
11
|
+
|
|
12
|
+
## Verification
|
|
13
|
+
|
|
14
|
+
- `node bin/uscha.js version --json`
|
|
15
|
+
- `npm pack --dry-run --json`
|
|
16
|
+
- `bash uscha-kit/tests/smoke-engine.sh`
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# uscha-kit 1.40.1
|
|
2
|
+
|
|
3
|
+
## Fixed
|
|
4
|
+
|
|
5
|
+
- Exclude Python bytecode artifacts (`__pycache__`, `*.pyc`, `*.pyo`) from the npm package tarball.
|
|
6
|
+
- Strengthen the npm smoke check so package dry-run fails if Python bytecode artifacts would be published.
|
|
7
|
+
|
|
8
|
+
## Verification
|
|
9
|
+
|
|
10
|
+
- `npm publish --dry-run --access public`
|
|
11
|
+
- `bash uscha-kit/tests/smoke-engine.sh`
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# dev-loop-kit 1.5.0 — adapter `type: node` (TypeScript/JS) (2026-07-02)
|
|
2
|
+
|
|
3
|
+
El adapter más barato del roadmap: reusa el parser lcov (Flutter) para coverage y el
|
|
4
|
+
parser JUnit-envuelto (Python) para tests; lo único nuevo son los parsers de ESLint y
|
|
5
|
+
tsc. Smoke suite: 31/31 (24 previos intactos + 7 node).
|
|
6
|
+
|
|
7
|
+
## Engine (qa_ledger.py)
|
|
8
|
+
|
|
9
|
+
- **`type: node`** — TypeScript/JS (jest o vitest sobre Node).
|
|
10
|
+
- Coverage: `coverage/lcov.info` — **mismo parser que Flutter** (`flutter_coverage`,
|
|
11
|
+
docstring generalizado).
|
|
12
|
+
- Test count: **`junit_test_count()`** (renombrado desde `python_test_count` — es de
|
|
13
|
+
familia JUnit, no de lenguaje): jest-junit / `vitest --reporter=junit`, root envuelto
|
|
14
|
+
`<testsuites>` soportado, first-location-wins.
|
|
15
|
+
- **`parse_eslint()`** — `eslint --format json`: severity 2 (error) → HIGH,
|
|
16
|
+
1 (warn) → MEDIUM; reglas `security/*` con floor HIGH (como findsecbugs);
|
|
17
|
+
**`fatal: true`** (error de parseo) → HIGH siempre — la lección del `code: null`
|
|
18
|
+
de ruff (1.4.0). `ruleId: null` SIN fatal (directivas eslint-disable sin usar,
|
|
19
|
+
default de ESLint 9) sigue la severidad del mensaje — nunca un falso blocker.
|
|
20
|
+
- **`parse_tsc()`** — `tsc --noEmit` texto (`file(line,col): error TSxxxx`):
|
|
21
|
+
error → HIGH (un type error es rotura real); paths Windows con drive soportados.
|
|
22
|
+
**Errores GLOBALES sin archivo** (TS18003/TS5023 — tsconfig roto) → HIGH con
|
|
23
|
+
ubicación `?`: un tsc que no chequeó NADA jamás lee como gate limpio.
|
|
24
|
+
- IDs de finding node preservan el path repo-relativo (`_mk_id_rel`): los layouts
|
|
25
|
+
sin `src/` (app/pages con decenas de `page.tsx`/`index.ts`) no colisionan por
|
|
26
|
+
basename; los paths absolutos de eslint se relativizan a la base del repo.
|
|
27
|
+
- `ingest-gate`: branch node (`reports/eslint.json` / `reports/tsc.txt`, o
|
|
28
|
+
`--eslint/--tsc`); combinado = `node-qa-gate`. Mismo contrato de ausencia.
|
|
29
|
+
- Guard UNMEASURED ampliado: `maven`/`python`/`node`.
|
|
30
|
+
- LOC node: test = `__tests__`/`tests`/`test` en el path o `*.test.*`/`*.spec.*`;
|
|
31
|
+
prod = el resto. `SOURCE_EXT` node: `.ts .tsx .js .jsx .mjs .cjs`.
|
|
32
|
+
- `SKIP_DIRS` += `coverage` (el lcov-report HTML de jest contiene .js que
|
|
33
|
+
contaminaría el LOC), `.next`, `.turbo`. **Trade-off documentado**: el set es
|
|
34
|
+
global — un paquete fuente legítimamente llamado `coverage/` en cualquier type
|
|
35
|
+
queda fuera del LOC (métrica advisory; la detección de lcov es por glob y no
|
|
36
|
+
se afecta).
|
|
37
|
+
- `LICENSE` (MIT) agregada al repo y copiada dentro de `dev-loop-kit/` para que
|
|
38
|
+
el zip la lleve.
|
|
39
|
+
|
|
40
|
+
## Config / docs
|
|
41
|
+
|
|
42
|
+
- `test_command_node` + repo de ejemplo `web-app`; version 1.5.0 (triple sync).
|
|
43
|
+
- Kit README: tabla TypeScript/JS; SKILL.md types + `npm test`; docs ES/EN
|
|
44
|
+
actualizan tipos y versión vigente.
|
|
45
|
+
|
|
46
|
+
## Smoke (tests/smoke-engine.sh)
|
|
47
|
+
|
|
48
|
+
- `repo-d` (`type: node`): lcov 9/10 → 90.0%, junit envuelto → 7 tests,
|
|
49
|
+
LOC prod=4/test=2 (.ts vs .test.ts), eslint (security floor + null fatal HIGH,
|
|
50
|
+
prefer-const MEDIUM → reported=3 gated=2), tsc error → HIGH,
|
|
51
|
+
UNMEASURED pre-ingest → medido post-ingest.
|
|
52
|
+
|
|
53
|
+
## Criterio pendiente (mismo contrato que el adapter python)
|
|
54
|
+
|
|
55
|
+
El adapter node NO tiene todavía un repo real de dogfooding detrás — entra por decisión
|
|
56
|
+
del autor pensando en el release público (audiencia TS/JS). El dry-run de solo lectura
|
|
57
|
+
contra un repo TS/JS real (coverage vs jest, test count exacto, eslint/tsc) queda como
|
|
58
|
+
criterio abierto — igual que el dry-run pendiente del adapter python (1.4.0).
|
|
59
|
+
|
|
60
|
+
## Diferido consciente (sin cambios)
|
|
61
|
+
|
|
62
|
+
- rebuild: densidad de asserts por test-file. Perfiles A-E mecanizados (`--profile`).
|
|
63
|
+
- Roadmap de adapters: Go (golangci-lint emite formato checkstyle — reusable),
|
|
64
|
+
Rust (cargo-llvm-cov emite Cobertura — reusable). Entran cuando haya repo real.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# dev-loop-kit 1.6.0 — adapter `type: go` (2026-07-02)
|
|
2
|
+
|
|
3
|
+
Tercer adapter consecutivo donde el costo baja porque el engine habla FORMATOS, no
|
|
4
|
+
lenguajes: el linter reusa `parse_checkstyle` (golangci-lint emite checkstyle) y los
|
|
5
|
+
tests reusan `junit_test_count` (gotestsum emite JUnit). Lo único nuevo: el parser del
|
|
6
|
+
cover profile nativo de Go. Smoke suite: 37/37 (31 previos intactos + 6 go).
|
|
7
|
+
|
|
8
|
+
## Engine (qa_ledger.py)
|
|
9
|
+
|
|
10
|
+
- **`type: go`**.
|
|
11
|
+
- **`go_coverage()`** — cover profile nativo (`go test -coverprofile=coverage.out`):
|
|
12
|
+
formato `import/path/file.go:S.C,E.C numStatements hitCount`; cobertura por
|
|
13
|
+
**SENTENCIAS** (la convención Go, no líneas). First match: `coverage.out`,
|
|
14
|
+
`cover.out`, `reports/coverage.out`. Profile vacío (solo línea `mode:`) → 0.0
|
|
15
|
+
fail-closed, nunca un verde inventado.
|
|
16
|
+
- Test count: **reusa `junit_test_count`** vía `gotestsum --junitfile` (root envuelto
|
|
17
|
+
ya soportado).
|
|
18
|
+
- Linter: **reusa `parse_checkstyle` parametrizado** (`tool="golangci"`) — golangci-lint
|
|
19
|
+
`--out-format checkstyle`; error→HIGH, warning→MEDIUM; gosec entra por el mismo
|
|
20
|
+
reporte si está habilitado en la config del linter. Los IDs de finding llevan
|
|
21
|
+
`golangci:` (los de Java siguen `checkstyle:` — sin migración de IDs).
|
|
22
|
+
- `ingest-gate`: branch go (`reports/golangci.xml` / `golangci.xml`, o `--golangci`);
|
|
23
|
+
combinado = `go-qa-gate`. Mismo contrato de ausencia.
|
|
24
|
+
- Guard UNMEASURED: `maven`/`python`/`node`/`go`.
|
|
25
|
+
- LOC go: test = sufijo `_test.go` (la convención — los tests viven junto al código);
|
|
26
|
+
prod = el resto. `SKIP_DIRS` += `vendor` (dependencias vendorizadas explotarían el
|
|
27
|
+
LOC) y `testdata` (fixtures no compilables).
|
|
28
|
+
|
|
29
|
+
## Config / docs
|
|
30
|
+
|
|
31
|
+
- `test_command_go` (gotestsum + coverprofile) + repo de ejemplo `api-svc`;
|
|
32
|
+
version 1.6.0 (triple sync).
|
|
33
|
+
- Kit README: tabla Go; SKILL.md types + `go test`; docs ES/EN tipos y versión.
|
|
34
|
+
|
|
35
|
+
## Smoke (tests/smoke-engine.sh)
|
|
36
|
+
|
|
37
|
+
- `repo-e` (`type: go`): cover profile 3/5 sentencias → 60.0%, gotestsum junit → 4
|
|
38
|
+
tests, LOC prod=4/test=2 (`_test.go` junto al código), golangci checkstyle
|
|
39
|
+
(error gateado HIGH + warning MEDIUM), UNMEASURED pre-ingest → medido post-ingest.
|
|
40
|
+
|
|
41
|
+
## Nota estructural (regla de tres cumplida)
|
|
42
|
+
|
|
43
|
+
Con 5 types, los dispatchers siguen siendo ifs de 3 ramas y cada adapter nuevo reusó
|
|
44
|
+
parsers existentes — la presión para refactorizar `type` → perfiles de reporte
|
|
45
|
+
(cobertura+junit+linters como config, no código) existe pero todavía no duele. Si
|
|
46
|
+
entra un 6º type o un type necesita MEZCLAR formatos, ese es el momento.
|
|
47
|
+
|
|
48
|
+
## Criterio pendiente (mismo contrato que python/node)
|
|
49
|
+
|
|
50
|
+
Dry-run de solo lectura contra un repo Go real — el adapter entra sin repo de
|
|
51
|
+
dogfooding detrás, mismo criterio abierto que 1.4.0/1.5.0.
|
|
52
|
+
|
|
53
|
+
## Diferido consciente (sin cambios)
|
|
54
|
+
|
|
55
|
+
- rebuild: densidad de asserts por test-file. Perfiles A-E mecanizados (`--profile`).
|
|
56
|
+
- Rust: cargo-llvm-cov emite Cobertura (reusa `python_coverage`) + cargo-nextest emite
|
|
57
|
+
JUnit — entra cuando haya repo real.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# dev-loop-kit 1.7.0 — adapters `type: rust` y `type: dotnet` (2026-07-02)
|
|
2
|
+
|
|
3
|
+
> Publicado junto con 1.8.0 y 1.9.0 en un único commit (no existe commit
|
|
4
|
+
> standalone de 1.7.0); la suite final de ese commit es 63/63. Los fixes que
|
|
5
|
+
> el review fresco de este adapter encontró (blocker de clippy incluido)
|
|
6
|
+
> están aplicados y documentados en CHANGELOG-1.9.0.
|
|
7
|
+
|
|
8
|
+
Dos adapters en un release porque ambos REUSAN la infraestructura existente:
|
|
9
|
+
coverage vía Cobertura (`cobertura_coverage`, renombrado desde `python_coverage`) y
|
|
10
|
+
tests vía `junit_test_count`. Nuevo de verdad: `parse_clippy` (JSONL de cargo) y
|
|
11
|
+
`parse_sarif` (SARIF v2 — el formato universal de análisis estático). Incluye los
|
|
12
|
+
fixes del review fresco de 1.6.0.
|
|
13
|
+
|
|
14
|
+
## Rust (`type: rust`)
|
|
15
|
+
|
|
16
|
+
- Coverage: `cargo llvm-cov --cobertura --output-path reports/coverage.xml` —
|
|
17
|
+
**reusa `cobertura_coverage`** sin cambios.
|
|
18
|
+
- Tests: cargo-nextest con reporter junit — **reusa `junit_test_count`**.
|
|
19
|
+
- **`parse_clippy()`** — `cargo clippy --message-format=json` (JSON Lines):
|
|
20
|
+
`error`→HIGH, `warning`→MEDIUM; **`code: null`** (error de compilación de rustc,
|
|
21
|
+
no un lint) → HIGH siempre — la lección del ruff/tsc, tercera aplicación.
|
|
22
|
+
Los IDs preservan el path del span primario (`_mk_id_rel`).
|
|
23
|
+
- LOC: `tests/` = integración; los tests inline `#[cfg(test)]` cuentan como prod
|
|
24
|
+
(limitación documentada de la clasificación por path). `target/` ya estaba en
|
|
25
|
+
SKIP_DIRS (cargo y maven comparten el nombre).
|
|
26
|
+
|
|
27
|
+
## C#/.NET (`type: dotnet`)
|
|
28
|
+
|
|
29
|
+
- Coverage: coverlet.msbuild → Cobertura — **reusa `cobertura_coverage`**.
|
|
30
|
+
- Tests: `dotnet test --logger "junit;LogFilePath=reports/junit.xml"`
|
|
31
|
+
(JUnitXml.TestLogger) — **reusa `junit_test_count`**.
|
|
32
|
+
- **`parse_sarif()`** — SARIF v2 (Roslyn vía `dotnet build /p:ErrorLog=...`):
|
|
33
|
+
`error`→HIGH, `warning`→MEDIUM, `note`→INFO. El parser sirve para CUALQUIER
|
|
34
|
+
herramienta que emita SARIF (semgrep, CodeQL, etc.) — inversión, no solo .NET.
|
|
35
|
+
- LOC: proyectos `*.Tests/` y archivos `*Test(s).cs` = test. SKIP_DIRS += `obj`,
|
|
36
|
+
`TestResults`.
|
|
37
|
+
|
|
38
|
+
## Fixes del review fresco de 1.6.0 (incluidos acá)
|
|
39
|
+
|
|
40
|
+
- **BLOCKER**: la tabla Go del kit README había pisado el heading `## Instalación`
|
|
41
|
+
— restaurado.
|
|
42
|
+
- **HIGH**: el comando documentado de golangci-lint usaba el flag v1
|
|
43
|
+
(`--out-format`), **eliminado en golangci-lint v2** (2025) — documentado el flag
|
|
44
|
+
v2 (`--output.checkstyle.path=...`) con fallback v1.
|
|
45
|
+
- **MEDIUM**: gotestsum pone `errors` SOLO en el root `<testsuites>` (un paquete
|
|
46
|
+
que no compila tenía errors>0 invisibles) — `junit_test_count` ahora toma
|
|
47
|
+
`max(root, suma de hijos)` por contador.
|
|
48
|
+
- **LOW**: `go_coverage` dedupea bloques repetidos (perfiles `-coverpkg` merged);
|
|
49
|
+
IDs de golangci preservan el path repo-relativo (basename colisionaba en repos
|
|
50
|
+
Go idiomáticos); nota de severidades de golangci en README.
|
|
51
|
+
|
|
52
|
+
## Trade-off documentado (global, igual que `coverage/` en 1.5.0)
|
|
53
|
+
|
|
54
|
+
`vendor/`, `testdata/`, `obj/`, `TestResults/` en SKIP_DIRS son globales: un paquete
|
|
55
|
+
fuente legítimamente llamado así en OTRO type queda fuera del LOC (métrica advisory;
|
|
56
|
+
la detección de reportes es por glob/paths y no se afecta).
|
|
57
|
+
|
|
58
|
+
## Nota estructural (regla de tres, re-evaluada en el 7º type)
|
|
59
|
+
|
|
60
|
+
Siete types y los dispatchers siguen siendo ifs por FORMATO (jacoco / cobertura /
|
|
61
|
+
lcov / cover-profile · surefire / junit / aproximado). El refactor a perfiles
|
|
62
|
+
declarativos sigue sin pagar: no eliminaría los parsers (el costo real) y agregaría
|
|
63
|
+
indirección. Se re-evalúa si un type necesita MEZCLAR formatos por config.
|
|
64
|
+
|
|
65
|
+
## Criterio pendiente (mismo contrato que python/node/go)
|
|
66
|
+
|
|
67
|
+
Dry-run de solo lectura contra repos Rust/.NET reales — ambos adapters entran sin
|
|
68
|
+
repo de dogfooding detrás.
|
|
69
|
+
|
|
70
|
+
## Diferido consciente (sin cambios)
|
|
71
|
+
|
|
72
|
+
- rebuild: densidad de asserts. Perfiles A-E mecanizados.
|
|
73
|
+
- C++: viable (gcovr emite Cobertura/lcov — parsers existentes; gtest/catch2 emiten
|
|
74
|
+
JUnit; clang-tidy necesitaría un parser tipo mypy) — entra cuando haya repo real.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# dev-loop-kit 1.8.0 — adapter `type: cpp` (2026-07-02)
|
|
2
|
+
|
|
3
|
+
> Publicado junto con 1.7.0 y 1.9.0 en un único commit (no existe commit
|
|
4
|
+
> standalone de 1.8.0); la suite final de ese commit es 63/63. Los fixes que el
|
|
5
|
+
> review fresco de este adapter encontró están aplicados y documentados en
|
|
6
|
+
> CHANGELOG-1.9.0.
|
|
7
|
+
|
|
8
|
+
Séptimo lenguaje, UN parser nuevo: clang-tidy. Coverage vía gcovr→Cobertura (reusa
|
|
9
|
+
`cobertura_coverage`) y tests vía ctest `--output-junit`/GoogleTest (reusa
|
|
10
|
+
`junit_test_count` — el fixture de smoke usa el root PLANO `<testsuite>` para
|
|
11
|
+
ejercitar la rama que los demás types no tocan).
|
|
12
|
+
|
|
13
|
+
## Engine (qa_ledger.py)
|
|
14
|
+
|
|
15
|
+
- **`type: cpp`** — extensiones `.cpp .cc .cxx .c .h .hpp .hh .hxx`.
|
|
16
|
+
- Coverage: `gcovr --cobertura reports/coverage.xml` — **reusa `cobertura_coverage`**.
|
|
17
|
+
- Tests: `ctest --test-dir build --output-junit ../reports/junit.xml` (CMake ≥3.21;
|
|
18
|
+
root plano) o `--gtest_output=xml:` (root envuelto) — **reusa `junit_test_count`**,
|
|
19
|
+
ambas formas de root ya soportadas.
|
|
20
|
+
- **`parse_clang_tidy()`** — texto (`file:line:col: warning: msg [check-a,check-b]`):
|
|
21
|
+
error→HIGH, warning→MEDIUM; checks de seguridad (`cert-*`, o que contengan
|
|
22
|
+
`security`) con floor HIGH — misma disciplina que findsecbugs/eslint-security.
|
|
23
|
+
Líneas sin `[check]` (diagnósticos crudos del compilador) → rule `diagnostic`.
|
|
24
|
+
IDs con path preservado (`_mk_id_rel`).
|
|
25
|
+
- `ingest-gate`: branch cpp (`reports/clang-tidy.txt`, o `--clang-tidy`);
|
|
26
|
+
combinado = `cpp-qa-gate`. Mismo contrato de ausencia.
|
|
27
|
+
- Guard UNMEASURED: los 7 types linteables.
|
|
28
|
+
- LOC: `test`/`tests` en el path, prefijo `test_` o sufijos `_test.cpp/.cc/.cxx`,
|
|
29
|
+
`Test.cpp`. `SKIP_DIRS` += `cmake-build-debug`, `cmake-build-release`, `_deps`
|
|
30
|
+
(FetchContent) — mismo trade-off global documentado.
|
|
31
|
+
|
|
32
|
+
## Nota honesta sobre C++
|
|
33
|
+
|
|
34
|
+
El ecosistema no tiene UNA convención de build (CMake/Bazel/make) — el kit no la
|
|
35
|
+
elige: pide que los REPORTES existan (Cobertura + JUnit + texto de clang-tidy) y el
|
|
36
|
+
cómo se generan vive en el adapter por-repo (`CLAUDE.md` del proyecto). Es el
|
|
37
|
+
contrato de siempre, explícito.
|
|
38
|
+
|
|
39
|
+
## Criterio pendiente (mismo contrato que python/node/go/rust/dotnet)
|
|
40
|
+
|
|
41
|
+
Dry-run de solo lectura contra un repo C++ real — entra sin repo de dogfooding.
|
|
42
|
+
|
|
43
|
+
## Diferido consciente
|
|
44
|
+
|
|
45
|
+
- rebuild: densidad de asserts. Perfiles A-E mecanizados. cppcheck (`--xml`) como
|
|
46
|
+
segundo linter cpp si un repo real lo pide.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# dev-loop-kit 1.9.0 — adapters `type: gradle` (Kotlin/JVM) y `type: swift` + fixes de los reviews 1.7.0/1.8.0 (2026-07-02)
|
|
2
|
+
|
|
3
|
+
Los dos adapters más baratos hasta ahora: **CERO parsers nuevos**. Todo es reuso
|
|
4
|
+
de formatos ya soportados en paths nuevos. Nota clave: **Kotlin sobre Maven ya
|
|
5
|
+
funcionaba con `type: maven`** (`.kt` está en SOURCE_EXT maven desde 1.0) —
|
|
6
|
+
`gradle` cubre el caso común Gradle. Smoke suite: 63/63.
|
|
7
|
+
|
|
8
|
+
## Engine (qa_ledger.py)
|
|
9
|
+
|
|
10
|
+
### `type: gradle` (Kotlin/JVM + Java-sobre-Gradle)
|
|
11
|
+
|
|
12
|
+
- Extensiones `.kt .kts .java`. LOC: `src/main` = prod; `src/test` y source
|
|
13
|
+
sets custom (`src/*Test`: integrationTest, functionalTest) = test.
|
|
14
|
+
- Coverage: **reusa el parser JaCoCo de maven** (`_jacoco_line_counter`) en los
|
|
15
|
+
paths Gradle (`build/reports/jacoco/test/jacocoTestReport.xml`).
|
|
16
|
+
- Tests: **reusa la suma per-clase de surefire** — `maven_test_count` y
|
|
17
|
+
`gradle_test_count` ahora comparten `_perclass_xml_count()`; los
|
|
18
|
+
`build/test-results/**/TEST-*.xml` de Gradle son el mismo formato.
|
|
19
|
+
- Linter: **detekt** emite formato checkstyle — `parse_checkstyle(tool="detekt")`
|
|
20
|
+
parametrizado, igual que golangci. `--detekt` explícito o por type;
|
|
21
|
+
combinado = `gradle-qa-gate`.
|
|
22
|
+
|
|
23
|
+
### `type: swift`
|
|
24
|
+
|
|
25
|
+
- Extensión `.swift`. LOC: convención SwiftPM (`Sources/` prod, `Tests/` +
|
|
26
|
+
`*Tests.swift`/`*Test.swift` test).
|
|
27
|
+
- Coverage: **reusa el parser lcov** (Flutter/node) — `llvm-cov export
|
|
28
|
+
-format=lcov` sobre el `.profdata` de `swift test --enable-code-coverage`.
|
|
29
|
+
- Tests: **reusa `junit_test_count`** — `swift test --xunit-output
|
|
30
|
+
reports/junit.xml` emite JUnit directo; el archivo hermano
|
|
31
|
+
`junit-swift-testing.xml` (Swift Testing) se SUMA (ver fixes 1.9.0).
|
|
32
|
+
- Linter: **SwiftLint** también emite checkstyle —
|
|
33
|
+
`parse_checkstyle(tool="swiftlint")`. `--swiftlint` o por type;
|
|
34
|
+
combinado = `swift-qa-gate`.
|
|
35
|
+
|
|
36
|
+
## Fixes del review fresco de 1.7.0 (rust/dotnet)
|
|
37
|
+
|
|
38
|
+
- **BLOCKER — clippy contaba los summaries de rustc como HIGH fantasma**:
|
|
39
|
+
`1 warning emitted` / `aborting due to N previous errors` son diagnósticos
|
|
40
|
+
REALES (level warning/error, `code:null`, `spans:[]`) que el branch code-null
|
|
41
|
+
convertía en `compile-error` HIGH — el gate rust no podía converger nunca con
|
|
42
|
+
un solo warning MEDIUM vivo. Fix: diagnósticos SIN primary span se saltean
|
|
43
|
+
ANTES del check de code (los compile errors reales siempre traen span).
|
|
44
|
+
Además dedupe por finding ID (cargo re-emite por target lib/bin/test).
|
|
45
|
+
- **SARIF**: Roslyn `ErrorLog` emite **v1** salvo `,version=2` — se documenta el
|
|
46
|
+
comando correcto Y el parser gana fallback v1 (`resultFile`/`analysisTarget`);
|
|
47
|
+
resultados suprimidos (`suppressions`/`suppressionStates`) se ignoran (un
|
|
48
|
+
`#pragma warning disable` no puede gatear un build limpio); URIs absolutas
|
|
49
|
+
`file:///` se relativizan contra el repo (IDs estables entre máquinas).
|
|
50
|
+
- **Paths dotnet**: `LogFilePath`/`CoverletOutput` relativos resuelven contra el
|
|
51
|
+
PROYECTO DE TEST, no la raíz — comando de ejemplo ahora ancla con `$PWD` y el
|
|
52
|
+
README lo advierte (+ `MergeWith` para multi-proyecto).
|
|
53
|
+
- **Junit de nextest**: no existe sin `[profile.default.junit]` en
|
|
54
|
+
`.config/nextest.toml` + copy desde `target/nextest/default/junit.xml` —
|
|
55
|
+
documentado y agregado al `test_command_rust`.
|
|
56
|
+
- **Regla 5 saldada**: los fixes de 1.6.0 que entraron sin check propio ahora
|
|
57
|
+
tienen smoke — junit root-max (gotestsum errors solo en root), dedupe de
|
|
58
|
+
bloques del cover profile (-coverpkg), y el summary/dup de clippy (T20/T25).
|
|
59
|
+
|
|
60
|
+
## Fixes del review fresco de 1.8.0 (cpp)
|
|
61
|
+
|
|
62
|
+
- **`backtest.cpp` ya no cuenta como test LOC**: el sufijo bare `test.cpp`
|
|
63
|
+
(lowercased) tragaba `backtest/protest/contest.cpp`; ahora el patrón CamelCase
|
|
64
|
+
gtest (`FooTest.cpp`) se matchea case-sensitive, como hace dotnet con
|
|
65
|
+
`Test.cs`. Smoke T25 lo pinnea.
|
|
66
|
+
- **`cmake-build-<perfil>` de CLion**: el skip ahora es por prefijo
|
|
67
|
+
(`cmake-build-*`), no solo debug/release — el README ya lo prometía y el
|
|
68
|
+
código no lo cumplía.
|
|
69
|
+
- **clang-tidy con paths absolutos**: se relativizan contra el repo
|
|
70
|
+
(`_node_rel`), IDs estables entre checkouts; extensiones `.tpp/.ipp/.inl/
|
|
71
|
+
.mm/.cu` entran al regex (un cert-* en un template header ya no desaparece
|
|
72
|
+
en silencio).
|
|
73
|
+
|
|
74
|
+
## Fixes del review fresco de 1.9.0 (gradle/swift)
|
|
75
|
+
|
|
76
|
+
- **detekt y SwiftLint imprimen paths ABSOLUTOS por default** — el branch
|
|
77
|
+
isabs de `parse_checkstyle` colapsaba esos IDs a basename (colisiones entre
|
|
78
|
+
módulos Gradle y archivos homónimos Swift, corrompiendo fixed/new/oscillation
|
|
79
|
+
que se computan sobre sets de IDs). Fix: `parse_checkstyle` gana `base` y
|
|
80
|
+
relativiza SIEMPRE para tools no-java (`_node_rel`), igual que
|
|
81
|
+
eslint/tsc/clang-tidy; `golangci` también lo recibe. `_node_rel` dejó de
|
|
82
|
+
depender de `os.path.isabs` (su veredicto para paths `/posix` en Windows
|
|
83
|
+
cambió entre versiones de Python): intenta `relpath` y descarta si escapa
|
|
84
|
+
del repo. Smokes T27/T28 ahora usan paths absolutos (el default real) y
|
|
85
|
+
asserten IDs repo-relativos.
|
|
86
|
+
- **Swift Testing era invisible**: `--xunit-output` escribe XCTest en
|
|
87
|
+
`junit.xml` y Swift Testing en un SEGUNDO `junit-swift-testing.xml` que el
|
|
88
|
+
counter no leía — un paquete Swift 6 (donde Swift Testing es el default)
|
|
89
|
+
medía `tests=0` con `report_found=True` y un failure real no disparaba el
|
|
90
|
+
veto "measured beats narrated": fail-open en la garantía central. Fix:
|
|
91
|
+
`junit_test_count` gana `extra_files` (reportes full-run de sets DISJUNTOS
|
|
92
|
+
que SÍ se suman) y el dispatch swift pasa ambos archivos. Smoke con failure
|
|
93
|
+
real en el archivo swift-testing.
|
|
94
|
+
- **detekt fuera del test command**: su default `maxIssues: 0` corta el build
|
|
95
|
+
con UN finding — la corrida de tests leería roja aunque los tests pasen,
|
|
96
|
+
mezclando el gate de lint (que tiene su canal propio) con el de tests.
|
|
97
|
+
`test_command_gradle` queda `./gradlew test jacocoTestReport`.
|
|
98
|
+
- **Source sets custom de Gradle**: `src/integrationTest/`, `src/functionalTest/`
|
|
99
|
+
(cualquier `src/*Test`) ahora cuentan como test LOC, no prod.
|
|
100
|
+
- README swift: variante Linux de `llvm-cov` (sin `xcrun`) + path del binario
|
|
101
|
+
de tests documentados.
|
|
102
|
+
|
|
103
|
+
## Contrato de siempre
|
|
104
|
+
|
|
105
|
+
Reporte ausente = el gate no corrió (jamás acredita fixes). Guard UNMEASURED:
|
|
106
|
+
los 9 types linteables. Criterio pendiente por adapter: dry-run de solo lectura
|
|
107
|
+
contra un repo real de cada lenguaje.
|
|
108
|
+
|
|
109
|
+
## Diferido consciente
|
|
110
|
+
|
|
111
|
+
- rebuild: densidad de asserts. Perfiles A-E mecanizados. Android (Gradle +
|
|
112
|
+
variantes) queda explícitamente FUERA de `type: gradle` hasta un repo real.
|