@andresmassello/uscha 1.51.1 → 1.51.3

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.
Files changed (82) hide show
  1. package/README.md +6 -1
  2. package/package.json +3 -2
  3. package/uscha-kit/.claude/skills/uscha-mirador/SKILL.md +11 -4
  4. package/uscha-kit/.claude/skills/uscha-mirador/mirador-render.py +16 -8
  5. package/uscha-kit/.claude-plugin/plugin.json +2 -2
  6. package/uscha-kit/.codex-plugin/plugin.json +2 -2
  7. package/uscha-kit/INSTALL.md +3 -0
  8. package/uscha-kit/README.md +1 -1
  9. package/uscha-kit/VERSION +1 -1
  10. package/uscha-kit/install-uscha.py +9 -3
  11. package/uscha-kit/skills/uscha-mirador/SKILL.md +11 -4
  12. package/uscha-kit/skills/uscha-mirador/mirador-render.py +16 -8
  13. package/uscha-kit/uscha.config.json +1 -1
  14. package/uscha-kit/CHANGELOG-1.10.0.md +0 -84
  15. package/uscha-kit/CHANGELOG-1.11.0.md +0 -67
  16. package/uscha-kit/CHANGELOG-1.12.0.md +0 -46
  17. package/uscha-kit/CHANGELOG-1.13.0.md +0 -33
  18. package/uscha-kit/CHANGELOG-1.14.0.md +0 -42
  19. package/uscha-kit/CHANGELOG-1.15.0.md +0 -58
  20. package/uscha-kit/CHANGELOG-1.16.0.md +0 -55
  21. package/uscha-kit/CHANGELOG-1.17.0.md +0 -44
  22. package/uscha-kit/CHANGELOG-1.18.0.md +0 -42
  23. package/uscha-kit/CHANGELOG-1.19.0.md +0 -41
  24. package/uscha-kit/CHANGELOG-1.2.2.md +0 -16
  25. package/uscha-kit/CHANGELOG-1.2.3.md +0 -20
  26. package/uscha-kit/CHANGELOG-1.2.4.md +0 -10
  27. package/uscha-kit/CHANGELOG-1.2.5.md +0 -23
  28. package/uscha-kit/CHANGELOG-1.2.6.md +0 -11
  29. package/uscha-kit/CHANGELOG-1.2.7.md +0 -15
  30. package/uscha-kit/CHANGELOG-1.2.8.md +0 -24
  31. package/uscha-kit/CHANGELOG-1.2.9.md +0 -4
  32. package/uscha-kit/CHANGELOG-1.20.0.md +0 -29
  33. package/uscha-kit/CHANGELOG-1.21.0.md +0 -33
  34. package/uscha-kit/CHANGELOG-1.22.0.md +0 -60
  35. package/uscha-kit/CHANGELOG-1.23.0.md +0 -75
  36. package/uscha-kit/CHANGELOG-1.24.0.md +0 -50
  37. package/uscha-kit/CHANGELOG-1.25.0.md +0 -55
  38. package/uscha-kit/CHANGELOG-1.26.0.md +0 -70
  39. package/uscha-kit/CHANGELOG-1.27.0.md +0 -45
  40. package/uscha-kit/CHANGELOG-1.28.0.md +0 -35
  41. package/uscha-kit/CHANGELOG-1.29.0.md +0 -20
  42. package/uscha-kit/CHANGELOG-1.3.0.md +0 -74
  43. package/uscha-kit/CHANGELOG-1.30.0.md +0 -46
  44. package/uscha-kit/CHANGELOG-1.31.0.md +0 -59
  45. package/uscha-kit/CHANGELOG-1.32.0.md +0 -50
  46. package/uscha-kit/CHANGELOG-1.33.0.md +0 -46
  47. package/uscha-kit/CHANGELOG-1.34.0.md +0 -55
  48. package/uscha-kit/CHANGELOG-1.35.0.md +0 -30
  49. package/uscha-kit/CHANGELOG-1.36.0.md +0 -33
  50. package/uscha-kit/CHANGELOG-1.37.0.md +0 -41
  51. package/uscha-kit/CHANGELOG-1.38.0.md +0 -11
  52. package/uscha-kit/CHANGELOG-1.39.0.md +0 -14
  53. package/uscha-kit/CHANGELOG-1.4.0.md +0 -68
  54. package/uscha-kit/CHANGELOG-1.40.0.md +0 -16
  55. package/uscha-kit/CHANGELOG-1.40.1.md +0 -11
  56. package/uscha-kit/CHANGELOG-1.40.2.md +0 -13
  57. package/uscha-kit/CHANGELOG-1.41.0.md +0 -18
  58. package/uscha-kit/CHANGELOG-1.41.1.md +0 -53
  59. package/uscha-kit/CHANGELOG-1.41.2.md +0 -34
  60. package/uscha-kit/CHANGELOG-1.41.3.md +0 -30
  61. package/uscha-kit/CHANGELOG-1.42.0.md +0 -41
  62. package/uscha-kit/CHANGELOG-1.43.0.md +0 -37
  63. package/uscha-kit/CHANGELOG-1.44.0.md +0 -90
  64. package/uscha-kit/CHANGELOG-1.44.1.md +0 -26
  65. package/uscha-kit/CHANGELOG-1.45.0.md +0 -58
  66. package/uscha-kit/CHANGELOG-1.46.0.md +0 -50
  67. package/uscha-kit/CHANGELOG-1.46.1.md +0 -35
  68. package/uscha-kit/CHANGELOG-1.47.0.md +0 -45
  69. package/uscha-kit/CHANGELOG-1.48.0.md +0 -35
  70. package/uscha-kit/CHANGELOG-1.48.1.md +0 -55
  71. package/uscha-kit/CHANGELOG-1.48.2.md +0 -47
  72. package/uscha-kit/CHANGELOG-1.49.0.md +0 -45
  73. package/uscha-kit/CHANGELOG-1.5.0.md +0 -64
  74. package/uscha-kit/CHANGELOG-1.50.0.md +0 -52
  75. package/uscha-kit/CHANGELOG-1.50.1.md +0 -52
  76. package/uscha-kit/CHANGELOG-1.50.2.md +0 -62
  77. package/uscha-kit/CHANGELOG-1.51.0.md +0 -44
  78. package/uscha-kit/CHANGELOG-1.51.1.md +0 -33
  79. package/uscha-kit/CHANGELOG-1.6.0.md +0 -57
  80. package/uscha-kit/CHANGELOG-1.7.0.md +0 -74
  81. package/uscha-kit/CHANGELOG-1.8.0.md +0 -46
  82. package/uscha-kit/CHANGELOG-1.9.0.md +0 -112
@@ -1,41 +0,0 @@
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.
@@ -1,11 +0,0 @@
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.
@@ -1,14 +0,0 @@
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.
@@ -1,68 +0,0 @@
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`).
@@ -1,16 +0,0 @@
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`
@@ -1,11 +0,0 @@
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`
@@ -1,13 +0,0 @@
1
- # uscha-kit 1.40.2
2
-
3
- ## Changed
4
-
5
- - Reworked install documentation around the npm/npx path for Codex, Claude Code, and mixed-machine setups.
6
- - Added `uscha-kit/INSTALL.md` as the focused install guide.
7
- - Kept Git checkout/link mode, Claude Code plugin commands, and manual copy as secondary/debugging options with tradeoffs.
8
-
9
- ## Verification
10
-
11
- - `npm view @andresmassello/uscha version`
12
- - `npx --yes @andresmassello/uscha@latest version --json`
13
- - `bash uscha-kit/tests/smoke-engine.sh`
@@ -1,18 +0,0 @@
1
- # uscha-kit 1.41.0 — safety release
2
-
3
- Significant backwards-compatible release covering WU1–WU7.
4
-
5
- - **WU1:** measured `pr-ready`, fail-closed Ruff/JUnit schemas, and validated counters.
6
- - **WU2:** safe init, authoritative doctor, portable active Claude hook, marketplace preflight, and staged rollback.
7
- - **WU3:** evidence-bearing PF/SD/SCR closure, config validation, and monotonic iterations/counters.
8
- - **WU4:** integration readiness heterogeneous-event false-green prevention, unknown escalation repo rejection, and Spanish ADR label folding.
9
- - **WU5:** ADR templates use AC IDs; the resolved constitution blocker example includes `--escape-analysis`.
10
- - **WU6:** npm router probes usable Python >=3.8 before one installer invocation with no retry; workbench-doctor uses portable Python and the current skill roster.
11
- - **WU7:** complete Claude installation transaction with rollback across managed skills, hook, settings, and marker; T77 covers existing and absent marker rollback.
12
- - **P0 hardening:** Mirador script/DOM injection removed; structured static reports including Clippy fail closed; stale JUnit evidence cannot satisfy `pr-ready`.
13
- - **P1 installer hardening:** init preflights all targets and rejects symlinks; Codex restores marketplace state during rollback; hook matcher and malformed Claude settings are validated.
14
- - **P1 ledger hardening:** readiness configuration is validated completely and PF/SD/SCR closure is immutable after its first resolution.
15
- - **Documentation truth-pass:** exact 29-command reference, npx-first Codex/Claude adoption, eight-skill inventory, completed EN twins, and refreshed diagrams.
16
- - Smoke suite: **351/351 green**.
17
-
18
- Known boundary: Codex and Claude targets are independently transactional; `--target both` remains sequential rather than cross-target atomic.
@@ -1,53 +0,0 @@
1
- # uscha-kit 1.41.1 — adversarial-review hardening (2026-07-11)
2
-
3
- An independent adversarial review of the 1.41.0 "safety hardening" release (4 parallel
4
- reviewers, each tasked to REFUTE the safety claims) confirmed three real defects — two of
5
- them in the engine's core "measured beats narrated" promise. Fixed here, each with a
6
- regression check that fails without the fix. Smoke suite: 355/355.
7
-
8
- ## Fixes
9
-
10
- ### 1 — `pr-ready` accepted a JUnit that LIES (HIGH, core-promise)
11
- `_junit_counts` read `tests`/`failures`/`errors` from the `<testsuite>` **attributes** and
12
- never reconciled them against the actual `<testcase>`/`<failure>`/`<error>` **elements**. A
13
- report declaring `failures="0"` while containing a real `<failure>` element read as all-green
14
- and could satisfy `pr-ready`. Fix: honor the child elements, fail-closed —
15
- `failures = max(attr, element_failures)`, same for errors. A present failure can no longer be
16
- attribute-declared away. Attribute-only summary suites (no `<testcase>` elements — the form
17
- many emitters legitimately use) keep their counts, so real adapters are unaffected.
18
- `qa_ledger.py:_junit_counts`. Regression: smoke **T69b**.
19
-
20
- ### 2 — integration readiness trusted the single last event (MEDIUM-HIGH, core-promise)
21
- The integration dimension read `integ_steps[-1]`, so a trailing green test-only step masked
22
- an earlier FAILING integration gate (dim → 1.0). Fix: green now requires **0 open gated
23
- findings across the latest record per integration tool** AND the latest test event passing —
24
- so a failing gate is not masked, while a same-tool re-run that clears the gate is still seen.
25
- `qa_ledger.py:cmd_readiness`. Regression: smoke **T69c**. (The 1.41.0 CHANGELOG claimed WU4
26
- fixed this; the code still used `integ_steps[-1]` — the claim was inaccurate.)
27
-
28
- ### 3 — Codex install rollback destroyed the pre-existing plugin (HIGH, data loss)
29
- `install_codex` gated its restore on `swapped` (only true after BOTH the backup-move and the
30
- install-move succeeded), then the `finally` deleted the backup unconditionally. If the
31
- `stage → plugin_root` swap failed after the original was moved to backup (a real Windows AV /
32
- locked-handle failure on reinstall), the restore was skipped and the `finally` deleted the
33
- only surviving copy — silently. Fix: gate the restore on the **backup existing** (not on
34
- `swapped`), and drop the backup only on SUCCESS (never in `finally`), so a failure restores
35
- the original and a hard interrupt leaves it intact. Mirrors the Claude path, which already did
36
- this. `install-uscha.py:install_codex`. Regression: smoke **T77b**. (This is exactly the
37
- "rollback leaves partial state" category 1.41.0 claimed to close — it closed it for Claude,
38
- not Codex.)
39
-
40
- ## Honest limits (not fixed here, by design)
41
- - A JUnit `<testsuite tests="3"/>` with ZERO `<testcase>` elements is still credited as 3
42
- tests. This is the same trust the engine extends to any tool-emitted summary (a coverage %
43
- in a coverage report), and closing it would reject the legitimate attribute-only reports
44
- many emitters produce. The defense against a **forged** bare report is the "evidence
45
- captured by execution" invariant (the SKILL runs the real test command; the agent does not
46
- hand-write the XML) + the human merge gate — not per-report forgery detection.
47
-
48
- ## Also
49
- - `docs/skills-referencia.html` + `-EN.html`: stale "24 subcommands" → 29 (truth-pass).
50
-
51
- ## Note on the test suite
52
- The installer/npm smoke checks hardcode the version string, so a version bump requires
53
- updating those literals (done here). A follow-up could have them read `VERSION` dynamically.
@@ -1,34 +0,0 @@
1
- # uscha-kit 1.41.2 — mirador launch UX (2026-07-18)
2
-
3
- A usability release for the mirador (the bird's-eye dashboard). No engine measurement
4
- logic changed; this makes the mirador honest about "not ready" and trivial to launch from
5
- inside a running project — "nada de magia oculta". Smoke suite: 357/357.
6
-
7
- ## Fixes
8
-
9
- ### 1 — "NOT READY" no longer reads as "hasn't started" (readiness title)
10
- The mirador mapped the `NOT READY` band (score 0–49) to a fixed title `"Todavia no arranca"`
11
- ("hasn't started yet"). But a project at, say, readiness 22 HAS started — it simply lacks
12
- enough **measured** evidence. The wording contradicted the score right next to it. Fix: the
13
- `NOT READY` title is now score-aware — `"Todavia sin evidencia medida"` only at score 0, and
14
- `"En construccion -- evidencia insuficiente"` above 0. The dead fixed entry was removed from
15
- `_MIRADOR_TITLE` so the old wording cannot reappear. `qa_ledger.py:cmd_dashboard`.
16
- Regression: smoke **T78**.
17
-
18
- ## Launch UX
19
-
20
- ### 2 — `mirador-render.py` self-resolves its siblings
21
- `--engine` (the `qa_ledger.py` path) and `--template` (the mirador HTML) now default to the
22
- renderer's **sibling** skill files. From any project you can run the renderer — or
23
- `/uscha-mirador` — with just `--ledger`, no long absolute paths. `mirador-render.py:main`.
24
-
25
- ### 3 — the rendered mirador opens itself, and always prints where it is
26
- After writing `mirador.html` the renderer opens it in the default browser (best-effort:
27
- `os.startfile` on Windows, `open`/`xdg-open` elsewhere — never fails on headless/CI) and
28
- prints the **absolute path** on an `OPEN IT:` line. A new `--no-open` flag suppresses the
29
- auto-open; the live-watch loop (`mirador-watch.sh`/`.ps1`) and the smoke suite pass it so
30
- they never spawn browser tabs on every refresh. `mirador-render.py`.
31
-
32
- ## Note on the test suite
33
- The installer/npm smoke checks still hardcode the version string, so this bump updated those
34
- literals (T44, T66/T67 assertions). A follow-up could have them read `VERSION` dynamically.
@@ -1,30 +0,0 @@
1
- # uscha-kit 1.41.3 — mirador live-view no longer spams browser tabs (2026-07-18)
2
-
3
- A hotfix for a regression shipped in 1.41.2. Smoke suite: 358/358.
4
-
5
- ## Fix
6
-
7
- ### mirador-render auto-open + `--refresh` spawned a new browser tab every cycle (HIGH, regression)
8
- 1.41.2 made `mirador-render.py` auto-open the rendered file in the browser. But the live
9
- second-screen view (`mirador-watch`, and any render with `--refresh N`) injects a
10
- `<meta http-equiv="refresh">` so a single open tab **reloads itself** every N seconds — and
11
- the renderer is re-invoked each cycle. Auto-opening on every invocation therefore spawned a
12
- **new browser tab on every refresh** (30s → a wall of tabs), making the machine unusable while
13
- a watch loop ran. The `--no-open` flag was not enough on its own: a watch process started
14
- before 1.41.2 calls the renderer without it.
15
-
16
- Fix: auto-open is now suppressed whenever `--refresh > 0` (live mode) — the meta-refresh owns
17
- the reload, in one tab. Auto-open remains for a genuine **one-shot** render (`/uscha-mirador`
18
- with no `--refresh`), and `--no-open` still suppresses it everywhere. The `OPEN IT: <abs path>`
19
- line is always printed, so the live view is one manual open away and never hidden.
20
- `mirador-render.py:main`. Regression: smoke **T79** (live → 0 opens, one-shot → 1, `--no-open`
21
- → 0).
22
-
23
- Because the renderer is a fresh subprocess each cycle, a running watch loop picks up this fix
24
- on its **next** render with no restart — and for a link/junction skill install (the renderer
25
- lives in this repo), no reinstall either. A copy-mode install needs a reinstall to get the
26
- fixed file.
27
-
28
- ## Note on the test suite
29
- The installer/npm smoke checks still hardcode the version string, so this bump updated those
30
- literals. A follow-up could have them read `VERSION` dynamically.
@@ -1,41 +0,0 @@
1
- # uscha-kit 1.42.0 — the mirador answers "how's it going / what's blocking / what's next" (2026-07-18)
2
-
3
- Until now the mirador showed the project's SKELETON — the phase trail, the counters, the
4
- invariant names — but a real early-stage project rendered as a wall of empty-looking cards
5
- that left you with "sabor a nada": you could not tell, at a glance, how it was going, what was
6
- blocking it, or what to do next. This release makes the mirador lead with exactly those three
7
- answers — and every one of them is **measured**, not narrated. Smoke suite: 359/359.
8
-
9
- ## The status story (hero block)
10
-
11
- A three-line block sits under the verdict, each line derived purely from fields the engine
12
- already emits in `dashboard --json` (no new engine logic, still model-agnostic):
13
-
14
- - **Cómo viene** — the measured sub-scores, verbatim: e.g. `coverage 0% · simplicity FAIL`.
15
- - **Qué lo traba** — the hard blockers, each traceable to a measured field: failing gates
16
- (sub-scores reading FAIL/MISS), the readiness cap (`readiness.sub`), open discovery intake
17
- (production findings / spec doubts / spec change requests), and expired/malformed ADR
18
- experiments. A failing gate is NOT double-reported as its flipped CONSTITUTION invariant.
19
- When nothing blocks, it says so and names the dimensions still lacking measured evidence.
20
- - **Qué sigue** — the active phase in the derived FSM plus its method and execution hint
21
- (`tier` / `model` / `effort`), so the operator sees the next concrete move.
22
-
23
- `mirador.template.html:renderStatus`. Regression: smoke **T80**.
24
-
25
- ## Empty cards earn their place
26
-
27
- Cards no longer render as dead space when a real project has nothing for them yet:
28
-
29
- - **The 6 layers of truth** (`capas`) — the engine never feeds this for a real project (it was
30
- demo-only), so the whole card now HIDES when empty instead of showing an empty grid.
31
- - **Specifications / ADRs / QA loops** — when empty, show a one-line hint of what fills them
32
- and in which phase, instead of a blank list or a bare `0/0`.
33
-
34
- ## Safety
35
- All status/hint DOM is built with `textContent` / `createTextNode` (no `innerHTML`), so the
36
- 1.41.0 Mirador XSS hardening still holds — smoke P0-A (script-context escaping, no HTML sinks)
37
- stays green.
38
-
39
- ## Note on the test suite
40
- The installer/npm smoke checks still hardcode the version string, so this bump updated those
41
- literals. A follow-up could have them read `VERSION` dynamically.
@@ -1,37 +0,0 @@
1
- # uscha-kit 1.43.0 — `uscha mirador`: one command, no python, no paths (2026-07-18)
2
-
3
- Adoption fix. Bringing up the mirador for a running project meant typing
4
- `python <long-skill-path>/mirador-render.py --ledger QA-LEDGER.json` — friction that pushed
5
- users away. The kit already had an npm/npx router (`bin/uscha.js`) forwarding to
6
- `install-uscha.py`; it was missing one verb. Smoke suite: 361/361.
7
-
8
- ## New: the `mirador` verb
9
-
10
- From the root of any project that has a `QA-LEDGER.json`:
11
-
12
- ```
13
- uscha mirador # render + open the dashboard
14
- uscha mirador --watch # live second-screen view (auto-refresh, one tab)
15
- npx @andresmassello/uscha mirador # same, zero install
16
- ```
17
-
18
- No python, no paths, no flags required. The verb:
19
- - resolves the renderer inside the kit (either skill-tree layout), which self-resolves its own
20
- engine + template siblings;
21
- - defaults the ledger to the `QA-LEDGER.json` convention in the current directory
22
- (`--ledger` to point elsewhere);
23
- - one-shot renders and opens the file; `--watch` opens ONE self-reloading tab and re-renders
24
- every `--interval` seconds (default 30) WITHOUT re-opening — no browser-tab spam (honors the
25
- 1.41.3 live-mode rule);
26
- - fails clearly (exit 1) when the ledger is missing, instead of a stack trace.
27
-
28
- `install-uscha.py:cmd_mirador` (exposed through the existing `bin/uscha.js` router).
29
- Regression: smoke **T81**.
30
-
31
- ## Docs
32
- `INSTALL.md` gains a "See the dashboard (mirador)" section; the uscha-mirador `SKILL.md`
33
- leads its human/terminal path with `uscha mirador`.
34
-
35
- ## Note on the test suite
36
- The installer/npm smoke checks still hardcode the version string, so this bump updated those
37
- literals. A follow-up could have them read `VERSION` dynamically.
@@ -1,90 +0,0 @@
1
- # uscha-kit 1.44.0 — brownfield truth: what the engine could not measure, it now says (2026-07-21)
2
-
3
- Field release. Everything here comes from a retrospective of a real run: a gzip migration
4
- across two legacy Java 8 / Ant repositories with fiscal data, taken end to end
5
- (reverse-discovery → approved golden → adr-refine → devloop → merge). The run succeeded, and
6
- it surfaced four defects that all share one root: **the engine knew something and did not say
7
- it**. Smoke suite: 366/366.
8
-
9
- Not in this release: the inert `risk_profile` (declared in config, read by nobody) — the
10
- deepest finding of the same retro. It gets its own release; see the note at the end.
11
-
12
- ## Fixes
13
-
14
- ### 1 — coverage: "no report at all" is not the same fact as "a measured 0%"
15
- `static_unmeasured` already taught the engine that *silence is not success* for the static
16
- gate. Coverage had no equivalent: a repo with no instrumentation scored exactly like a repo
17
- whose report says 0%, and the operator had no way to tell which — the field report had to read
18
- `qa_ledger.py` to find out. Two legacy repos with 18 green tests sat at readiness **66.7**
19
- purely because of this, an artificial ceiling in exactly the brownfield scenario
20
- `reverse-discovery` targets.
21
-
22
- Fix: the coverage parsers already returned `report_found`; the readiness dimension now uses it.
23
- `coverage_unmeasured` is exposed per repo (`facts`) and aggregated
24
- (`facts.coverage_unmeasured_repos`), and readiness prints the repos with the remedy named.
25
-
26
- The score is deliberately **unchanged** (still 0.0): auto-redistributing the weight would let
27
- any repo raise its score by DELETING its instrumentation — the precise anti-pattern
28
- `static_unmeasured` exists to prevent. The relief is a **human declaration**:
29
- `defaults.readiness_weights.coverage = 0` redistributes the weight, is versioned in the config,
30
- and carries provenance (config = requirement, kit 1.17.0). Silence never buys points; a
31
- declaration does. `qa_ledger.py`. Regression: smoke **T82** (pins the field's 66.7 → 100.0).
32
-
33
- ### 2 — no `ant` project type
34
- Supported types were maven, gradle, flutter, python, node, go, rust, dotnet, cpp, swift. Ant —
35
- the dominant build tool in legacy Java, i.e. the terrain the brownfield front is FOR — was
36
- missing, so the field run had to declare two Ant projects as `maven`. Added `ant`: because Ant
37
- has no standard output layout (the `todir` is build-file defined), its reports are discovered
38
- **recursively by name** (`**/TEST-*.xml`, `**/jacoco.xml`) instead of guessing one convention.
39
- Also added to the lint-capable set for `static_unmeasured`.
40
-
41
- Recursive discovery needs two guards, both found by an adversarial review of this very
42
- release: (a) reports are pruned of **third-party trees only** (`node_modules`, `vendor`,
43
- `.git`, `.venv`...) — deliberately NOT of `build/`, `target/` or `coverage/`, because reports
44
- LIVE in build output and the existing `SKIP_DIRS` (built for scanning SOURCE) would have
45
- hidden exactly the files being looked for; and (b) name-based discovery is **tolerant**: a
46
- `TEST-*.xml` that turns out not to be a JUnit `<testsuite>` — or that has a valid root but
47
- impossible counters, e.g. a truncated run — is dropped instead of aborting the whole run with
48
- `SystemExit(2)`. Precise patterns (maven/gradle) keep the hard failure.
49
-
50
- Crucially, a drop is **never silent**: `report_found` now means a *usable* report, and every
51
- dropped file is returned in `skipped_reports`, persisted in the snapshot, exposed per repo
52
- (`facts.dropped_reports`) and aggregated (`facts.dropped_report_repos`), and named by
53
- `readiness` on **stdout** — because `dashboard --json` (the mirador) captures stdout, so a
54
- stderr-only warning would be invisible exactly where operators look. Dropping evidence quietly
55
- would be silence buying a pass, which is the one thing this engine must not do.
56
- Regression: smoke **T83**.
57
-
58
- **Known limitation (by design, for now):** because report discovery for `ant` searches by name
59
- and deliberately does not prune `build/`/`target/` (reports live there), a nested sibling Maven
60
- or Gradle module inside an `ant` repo will have its reports swept into the parent's totals.
61
- That is the trade for a build tool with no convention; declare such modules as their own repos
62
- in `uscha.config.json` to keep their evidence separate.
63
-
64
- ### 3 — JUnit discovery too narrow (an integrity issue, not a convenience one)
65
- The engine looked for `target/surefire-reports/TEST-*.xml`, `reports/junit.xml` and
66
- `junit.xml`. A runner writing a DIRECTORY of per-class XML under `reports/junit/` was invisible,
67
- so the operator **hand-copied reports** to a path the engine knew. That is not friction: a
68
- hand-placed report breaks the *evidence captured by execution* invariant, which is the whole
69
- defense against a forged report. Now `reports/junit/**/*.xml` is discovered too.
70
- Regression: smoke **T83**.
71
-
72
- ### 4 — a Windows reserved filename took down a whole gate
73
- `waste-check` died with `ValueError: path is on mount '\\.\nul'` on a repo containing a file
74
- named `nul`; the gate simply never ran. Reserved device names (`nul`, `con`, `aux`, `prn`,
75
- `com1..9`, `lpt1..9`) are now skipped in all four tree walks. Detection splits on the FIRST
76
- dot, not the last: Windows treats `nul.tar.gz` as the device too, and an initial fix using
77
- `os.path.splitext` left that crash reachable (`_newest_source`, `count_loc`,
78
- `_test_file_set`, `_waste_repo_hashes`). A weird filename degrades to a skip, never a crash.
79
- Regression: smoke **T84** (multi-extension cases, and no false positives: `nullable.py`,
80
- `console.ts`, `com1x.go`).
81
-
82
- ## Note on the risk profile
83
- The same retro verified that `risk_profile` appears **zero times** in the engine: it is declared
84
- and read by nobody, so the decision of "how much process does this change deserve" rests
85
- entirely on the operator. That is the difference between a methodology and a convention, and it
86
- is too deep to bundle here — it is the next release.
87
-
88
- ## Note on the test suite
89
- The installer/npm smoke checks still hardcode the version string, so this bump updated those
90
- literals.
@@ -1,26 +0,0 @@
1
- # uscha-kit 1.44.1 — `uscha init` is per-file, not all-or-nothing (2026-07-21)
2
-
3
- Found by dogfooding: running `uscha init` on the kit's own repository. Smoke suite: 367/367.
4
-
5
- ## Fix
6
-
7
- ### `init` was unusable on any repo that already had a `CLAUDE.md`
8
- `cmd_init` copies four files (`uscha.config.json`, `CLAUDE.md`, `CONSTITUTION.md`,
9
- `.gitattributes`). It was **all-or-nothing**: if any target already existed and differed from
10
- the template, the whole init aborted and wrote **nothing**. But `CLAUDE.md` differs in every
11
- repo that already uses Claude Code — i.e. exactly the repos adopting uscha — so init reliably
12
- did nothing, and the only escape was `--force`, which would **overwrite the user's own
13
- `CLAUDE.md`**. The first command of the self-application run hit this immediately.
14
-
15
- Fix: `init` is now per-file. The non-conflicting files are written regardless; each conflict is
16
- reported and left **untouched** (resolve by hand, or re-run with `--force` to replace it
17
- deliberately). Status is `partial` when some files were written and conflicts remain, and the
18
- exit code stays **1** while any conflict is pending, so the partial state is visible and
19
- scriptable. A clean repo still initializes fully and exits 0 — backward compatible. The JSON
20
- output gains a `wrote` list of the paths actually written. `install-uscha.py:cmd_init`.
21
- Regression: smoke **T85**.
22
-
23
- ## Note
24
- This is the first fix that came out of `uscha` measuring itself (the repo now carries its own
25
- `uscha.config.json`, `ACCEPTANCE.md`, and versioned `QA-LEDGER.json`). More of the same retro's
26
- findings — chiefly the inert `risk_profile` — are still queued.
@@ -1,58 +0,0 @@
1
- # uscha-kit 1.45.0 — the risk profile stops being a decoration (2026-07-21)
2
-
3
- Release B of the field retrospective, and its deepest finding: `risk_profile` was declared in
4
- config and read by **nobody** in the engine — "the difference between a methodology and a
5
- convention." Designed front-to-back with `uscha-adr-refine` (five rounds of interrogation
6
- before a line of code); see `docs/adr/ADR-001` and `ADR-002`. Smoke suite: 372/372.
7
-
8
- ## What it does
9
-
10
- ### `risk_profile` is a named preset that modulates the flow (ADR-001)
11
- A profile is **not** a fixed table the engine imposes — that would contradict the provenance
12
- doctrine (kit 1.17.0), where the human declares what gates and the engine holds no opinion of
13
- its own. It is a **kit-shipped, overridable preset**: at config load, `risk_profile` expands
14
- into knobs the config already understands (`qa_tools_order`, `coverage_threshold`,
15
- `golden_required`), and any explicit `defaults` key wins per-key. The gating power it confers is
16
- exactly the power a human already has by declaring those knobs — a preset with provenance, not
17
- a new mechanism.
18
-
19
- Default table (all overridable):
20
-
21
- | Profile | `qa_tools_order` (required to converge) | `golden_required` | coverage_threshold |
22
- |---|---|---|---|
23
- | A | `[code-review]` | no | — |
24
- | B | `[code-review, improve]` | no | — |
25
- | C | `[code-review, judgment-day, improve]` | no | — |
26
- | D | `[code-review, judgment-day, improve]` | **yes** | 70 |
27
- | E | `[code-review, judgment-day, improve]` | **yes** | 80 |
28
-
29
- - An **unknown** profile fails loud (`SystemExit`) — a declared risk level is never inert
30
- (INV-RISK-01, new in `CONSTITUTION.md`).
31
- - **No** `risk_profile` → behavior byte-identical to before (backward compatible).
32
- - The origin of each expanded key is tracked so a cap can label its provenance.
33
-
34
- ### `golden_required` — a declarable cap for "an approved golden must exist" (ADR-002)
35
- A new readiness knob, declarable by **any** config (profiles D/E preset it on). When active and
36
- **no approved `golden-diff` gate** was ever logged for a repo, the frozen baseline is ABSENT —
37
- a measured fact — and that repo's readiness is capped at **49** (NOT READY, does not pass the
38
- human merge gate). A present-but-FAILED golden is left to the existing BLOCKER path (no
39
- double-cap). Provenance is three-way: `requerimiento (perfil E)` when it came from a profile,
40
- `requerimiento (config)` when declared directly, exposed in `cap_source`.
41
-
42
- ## Scope
43
- Engine-only. This makes the profile **weigh in the ledger and readiness** — it kills the inert
44
- defect. The token-saving half (the `uscha-devloop` orchestrator actually SKIPPING sub-agents by
45
- profile at run time) is orchestrator behavior, not deterministic engine logic, and is a named
46
- follow-up. The profile does not touch `execution_policy` (routing), is global (not per-repo),
47
- and never auto-classifies risk — the human declares it.
48
-
49
- ## Regressions
50
- - Smoke **T86**: profile expands the knobs with a provenance marker; explicit config wins;
51
- unknown profile fails hard.
52
- - Smoke **T87**: `golden_required` caps readiness to 49 when the golden is absent, with the
53
- right `cap_source` (profile vs config); with an approved golden or an explicit override, it
54
- does not fire.
55
-
56
- ## Note on the test suite
57
- The installer/npm smoke checks still hardcode the version string, so this bump updated those
58
- literals.
@@ -1,50 +0,0 @@
1
- # uscha-kit 1.46.0 — a progress statusline, generic and auto-wired (2026-07-21)
2
-
3
- The progress statusline (the colored bars at the bottom of Claude Code) was a prototype living
4
- inside a single consumer project (ANTI-FARO), full of that project's specifics. This
5
- generalizes it into the kit and makes the installer wire it, so a project gets a live progress
6
- readout with **zero** `settings.json` editing. Smoke suite: 374/374.
7
-
8
- ## Generic, config-driven scripts
9
- `templates/scripts/uscha_statusline.py` (the renderer) and `uscha_progress.py` (the Stop-hook
10
- refresher) carry **no** project-specific data. Everything that used to be hardcoded — the
11
- tracked repo, its label, its roadmap, its build priority — now comes from `uscha.config.json`:
12
-
13
- ```jsonc
14
- "repos": [{
15
- "name": "myproj", "path": ".", "type": "python", "label": "MY PROJECT",
16
- "roadmap": [ {"name": "01 Core", "path": "src/core.py"}, ... ],
17
- "build_priority": ["02 API", "01 Core"]
18
- }]
19
- ```
20
-
21
- The refresher reads REAL numbers only — acceptance from `ACCEPTANCE.md` (tolerant of `AC-01`
22
- and `**AC-01**`), tests/coverage from the ledger snapshot, roadmap items counted as built when
23
- their file actually exists and is non-trivial. Truth-pass: a missing source leaves its field
24
- null. The renderer degrades to an **empty** line (hidden) when there is no data — no hardcoded
25
- fallback ever.
26
-
27
- ## Auto-wired by `uscha init`
28
- `init` now also copies the two scripts to the project's `.claude/scripts/` and MERGES into
29
- `.claude/settings.json`, without clobbering:
30
- - `statusLine` → `python .claude/scripts/uscha_statusline.py` (added only if absent; an
31
- existing DIFFERENT statusLine is reported as a conflict, never overwritten — `--force` to
32
- replace);
33
- - a `Stop` hook → `python .claude/scripts/uscha_progress.py` (appended only if not already
34
- registered; idempotent).
35
-
36
- Commands are by name with forward slashes (Windows eats backslashes in the statusLine command;
37
- absolute paths are brittle across machines). A clean repo initializes fully; a repo with a
38
- conflicting file stays per-file (kit 1.44.1) and the settings merge still runs.
39
-
40
- ## Regressions
41
- - Smoke **T88**: the scripts are generic (config-driven, no ANTI-FARO), render with the
42
- config's label, and degrade to empty with no data.
43
- - Smoke **T89**: `init` wires `statusLine` + Stop hook + scripts, is idempotent, and never
44
- clobbers a foreign `statusLine`.
45
- - Smoke **T85** updated: `init` now writes the scripts + `settings.json` alongside the templates.
46
-
47
- ## Note
48
- Migrating the ANTI-FARO consumer to the kit's version (dropping its local prototype) is the
49
- consumer's job, out of this repo. Making the statusline command auto-detect `python`/`py -3`
50
- like the npm router is a possible follow-up.