@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.
- package/README.md +6 -1
- package/package.json +3 -2
- package/uscha-kit/.claude/skills/uscha-mirador/SKILL.md +11 -4
- package/uscha-kit/.claude/skills/uscha-mirador/mirador-render.py +16 -8
- package/uscha-kit/.claude-plugin/plugin.json +2 -2
- package/uscha-kit/.codex-plugin/plugin.json +2 -2
- package/uscha-kit/INSTALL.md +3 -0
- package/uscha-kit/README.md +1 -1
- package/uscha-kit/VERSION +1 -1
- package/uscha-kit/install-uscha.py +9 -3
- package/uscha-kit/skills/uscha-mirador/SKILL.md +11 -4
- package/uscha-kit/skills/uscha-mirador/mirador-render.py +16 -8
- package/uscha-kit/uscha.config.json +1 -1
- package/uscha-kit/CHANGELOG-1.10.0.md +0 -84
- package/uscha-kit/CHANGELOG-1.11.0.md +0 -67
- package/uscha-kit/CHANGELOG-1.12.0.md +0 -46
- package/uscha-kit/CHANGELOG-1.13.0.md +0 -33
- package/uscha-kit/CHANGELOG-1.14.0.md +0 -42
- package/uscha-kit/CHANGELOG-1.15.0.md +0 -58
- package/uscha-kit/CHANGELOG-1.16.0.md +0 -55
- package/uscha-kit/CHANGELOG-1.17.0.md +0 -44
- package/uscha-kit/CHANGELOG-1.18.0.md +0 -42
- package/uscha-kit/CHANGELOG-1.19.0.md +0 -41
- package/uscha-kit/CHANGELOG-1.2.2.md +0 -16
- package/uscha-kit/CHANGELOG-1.2.3.md +0 -20
- package/uscha-kit/CHANGELOG-1.2.4.md +0 -10
- package/uscha-kit/CHANGELOG-1.2.5.md +0 -23
- package/uscha-kit/CHANGELOG-1.2.6.md +0 -11
- package/uscha-kit/CHANGELOG-1.2.7.md +0 -15
- package/uscha-kit/CHANGELOG-1.2.8.md +0 -24
- package/uscha-kit/CHANGELOG-1.2.9.md +0 -4
- package/uscha-kit/CHANGELOG-1.20.0.md +0 -29
- package/uscha-kit/CHANGELOG-1.21.0.md +0 -33
- package/uscha-kit/CHANGELOG-1.22.0.md +0 -60
- package/uscha-kit/CHANGELOG-1.23.0.md +0 -75
- package/uscha-kit/CHANGELOG-1.24.0.md +0 -50
- package/uscha-kit/CHANGELOG-1.25.0.md +0 -55
- package/uscha-kit/CHANGELOG-1.26.0.md +0 -70
- package/uscha-kit/CHANGELOG-1.27.0.md +0 -45
- package/uscha-kit/CHANGELOG-1.28.0.md +0 -35
- package/uscha-kit/CHANGELOG-1.29.0.md +0 -20
- package/uscha-kit/CHANGELOG-1.3.0.md +0 -74
- package/uscha-kit/CHANGELOG-1.30.0.md +0 -46
- package/uscha-kit/CHANGELOG-1.31.0.md +0 -59
- package/uscha-kit/CHANGELOG-1.32.0.md +0 -50
- package/uscha-kit/CHANGELOG-1.33.0.md +0 -46
- package/uscha-kit/CHANGELOG-1.34.0.md +0 -55
- package/uscha-kit/CHANGELOG-1.35.0.md +0 -30
- package/uscha-kit/CHANGELOG-1.36.0.md +0 -33
- package/uscha-kit/CHANGELOG-1.37.0.md +0 -41
- package/uscha-kit/CHANGELOG-1.38.0.md +0 -11
- package/uscha-kit/CHANGELOG-1.39.0.md +0 -14
- package/uscha-kit/CHANGELOG-1.4.0.md +0 -68
- package/uscha-kit/CHANGELOG-1.40.0.md +0 -16
- package/uscha-kit/CHANGELOG-1.40.1.md +0 -11
- package/uscha-kit/CHANGELOG-1.40.2.md +0 -13
- package/uscha-kit/CHANGELOG-1.41.0.md +0 -18
- package/uscha-kit/CHANGELOG-1.41.1.md +0 -53
- package/uscha-kit/CHANGELOG-1.41.2.md +0 -34
- package/uscha-kit/CHANGELOG-1.41.3.md +0 -30
- package/uscha-kit/CHANGELOG-1.42.0.md +0 -41
- package/uscha-kit/CHANGELOG-1.43.0.md +0 -37
- package/uscha-kit/CHANGELOG-1.44.0.md +0 -90
- package/uscha-kit/CHANGELOG-1.44.1.md +0 -26
- package/uscha-kit/CHANGELOG-1.45.0.md +0 -58
- package/uscha-kit/CHANGELOG-1.46.0.md +0 -50
- package/uscha-kit/CHANGELOG-1.46.1.md +0 -35
- package/uscha-kit/CHANGELOG-1.47.0.md +0 -45
- package/uscha-kit/CHANGELOG-1.48.0.md +0 -35
- package/uscha-kit/CHANGELOG-1.48.1.md +0 -55
- package/uscha-kit/CHANGELOG-1.48.2.md +0 -47
- package/uscha-kit/CHANGELOG-1.49.0.md +0 -45
- package/uscha-kit/CHANGELOG-1.5.0.md +0 -64
- package/uscha-kit/CHANGELOG-1.50.0.md +0 -52
- package/uscha-kit/CHANGELOG-1.50.1.md +0 -52
- package/uscha-kit/CHANGELOG-1.50.2.md +0 -62
- package/uscha-kit/CHANGELOG-1.51.0.md +0 -44
- package/uscha-kit/CHANGELOG-1.51.1.md +0 -33
- package/uscha-kit/CHANGELOG-1.6.0.md +0 -57
- package/uscha-kit/CHANGELOG-1.7.0.md +0 -74
- package/uscha-kit/CHANGELOG-1.8.0.md +0 -46
- 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.
|