@andresmassello/uscha 1.40.2 → 1.43.0

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 (39) hide show
  1. package/README.md +6 -6
  2. package/bin/uscha.js +19 -7
  3. package/package.json +1 -1
  4. package/uscha-kit/.claude/skills/uscha-adr-refine/SKILL.md +2 -2
  5. package/uscha-kit/.claude/skills/uscha-devloop/SKILL.md +3 -1
  6. package/uscha-kit/.claude/skills/uscha-devloop/qa_ledger.py +729 -155
  7. package/uscha-kit/.claude/skills/uscha-mirador/SKILL.md +22 -7
  8. package/uscha-kit/.claude/skills/uscha-mirador/mirador-render.py +44 -5
  9. package/uscha-kit/.claude/skills/uscha-mirador/mirador-watch.ps1 +1 -1
  10. package/uscha-kit/.claude/skills/uscha-mirador/mirador-watch.sh +1 -1
  11. package/uscha-kit/.claude/skills/uscha-mirador/mirador.template.html +666 -586
  12. package/uscha-kit/.claude-plugin/plugin.json +1 -1
  13. package/uscha-kit/.codex-plugin/plugin.json +1 -1
  14. package/uscha-kit/CHANGELOG-1.41.0.md +18 -0
  15. package/uscha-kit/CHANGELOG-1.41.1.md +53 -0
  16. package/uscha-kit/CHANGELOG-1.41.2.md +34 -0
  17. package/uscha-kit/CHANGELOG-1.41.3.md +30 -0
  18. package/uscha-kit/CHANGELOG-1.42.0.md +41 -0
  19. package/uscha-kit/CHANGELOG-1.43.0.md +37 -0
  20. package/uscha-kit/INSTALL.md +120 -101
  21. package/uscha-kit/README.md +24 -13
  22. package/uscha-kit/VERSION +1 -1
  23. package/uscha-kit/WORKBENCH.md +19 -5
  24. package/uscha-kit/hooks/block-approved-writes.py +25 -0
  25. package/uscha-kit/install-uscha.py +534 -267
  26. package/uscha-kit/skills/uscha-adr-refine/SKILL.md +2 -2
  27. package/uscha-kit/skills/uscha-devloop/SKILL.md +3 -1
  28. package/uscha-kit/skills/uscha-devloop/qa_ledger.py +729 -155
  29. package/uscha-kit/skills/uscha-mirador/SKILL.md +22 -7
  30. package/uscha-kit/skills/uscha-mirador/mirador-render.py +44 -5
  31. package/uscha-kit/skills/uscha-mirador/mirador-watch.ps1 +1 -1
  32. package/uscha-kit/skills/uscha-mirador/mirador-watch.sh +1 -1
  33. package/uscha-kit/skills/uscha-mirador/mirador.template.html +666 -586
  34. package/uscha-kit/templates/CONSTITUTION.md +4 -4
  35. package/uscha-kit/templates/docs/adr/README.md +19 -19
  36. package/uscha-kit/tests/ledger-integrity-regressions.py +136 -0
  37. package/uscha-kit/tests/smoke-engine.sh +1312 -29
  38. package/uscha-kit/uscha.config.json +1 -1
  39. package/uscha-kit/workbench-doctor.sh +47 -3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
3
3
  "name": "uscha",
4
- "version": "1.40.2",
4
+ "version": "1.43.0",
5
5
  "displayName": "Uscha",
6
6
  "description": "Spec-driven development for LLM coding agents: 8 skills (discovery, adr-refine, reverse-discovery, characterize, devloop, sysdoc, rubric, mirador) + a stdlib measurement engine (qa_ledger.py, 29 subcommands + universal installer + npm/npx router). Facts block, guesses advise; the human approves.",
7
7
  "author": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uscha",
3
- "version": "1.40.2",
3
+ "version": "1.43.0",
4
4
  "description": "Uscha spec-driven development methodology for coding agents. Includes npm/npx router.",
5
5
  "author": {
6
6
  "name": "Andres Massello",
@@ -0,0 +1,18 @@
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.
@@ -0,0 +1,53 @@
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.
@@ -0,0 +1,34 @@
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.
@@ -0,0 +1,30 @@
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.
@@ -0,0 +1,41 @@
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.
@@ -0,0 +1,37 @@
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,101 +1,120 @@
1
- # Install Uscha
2
-
3
- Uscha installs as a machine-level helper for coding agents. The recommended path
4
- is npm/npx because it works the same on a fresh Codex or Claude Code machine.
5
-
6
- ## Quick path
7
-
8
- ### Codex Desktop
9
-
10
- ```bash
11
- npx --yes @andresmassello/uscha@latest version
12
- npx --yes @andresmassello/uscha@latest install --target codex --dry-run
13
- npx --yes @andresmassello/uscha@latest install --target codex
14
- npx --yes @andresmassello/uscha@latest doctor --target codex
15
- ```
16
-
17
- Then restart Codex or open a new thread. The installer registers Uscha as a
18
- personal local plugin under `~/plugins/uscha` and updates
19
- `~/.agents/plugins/marketplace.json`.
20
-
21
- ### Claude Code
22
-
23
- ```bash
24
- npx --yes @andresmassello/uscha@latest install --target claude --dry-run
25
- npx --yes @andresmassello/uscha@latest install --target claude
26
- npx --yes @andresmassello/uscha@latest doctor --target claude
27
- ```
28
-
29
- This installs the `uscha-*` skills and hooks under `~/.claude`. Restart or reload
30
- Claude Code after installing.
31
-
32
- ### Same machine uses both
33
-
34
- ```bash
35
- npx --yes @andresmassello/uscha@latest install --target both --dry-run
36
- npx --yes @andresmassello/uscha@latest install --target both
37
- npx --yes @andresmassello/uscha@latest doctor --target both
38
- ```
39
-
40
- ## Prepare a project repo
41
-
42
- After the machine install, initialize each project where Uscha should govern the
43
- workflow:
44
-
45
- ```bash
46
- npx --yes @andresmassello/uscha@latest init --repo . --dry-run
47
- npx --yes @andresmassello/uscha@latest init --repo .
48
- ```
49
-
50
- Project state stays in the project: `uscha.config.json`, `QA-LEDGER.json`,
51
- `ACCEPTANCE.md`, and approved golden fixtures when used.
52
-
53
- ## Requirements
54
-
55
- | Requirement | Why |
56
- |-------------|-----|
57
- | Node.js + npm | Runs the universal `npx` entrypoint. |
58
- | Python 3.8+ | Runs the canonical stdlib installer and engine. |
59
- | Git | Used by the method and by project setup checks. |
60
- | Codex Desktop and/or Claude Code | The agent runtime you want to install Uscha into. |
61
-
62
- No `pip install` is required. The engine is Python stdlib-only.
63
-
64
- ## Other install options
65
-
66
- | Option | Use when | Tradeoff |
67
- |--------|----------|----------|
68
- | `npx @andresmassello/uscha@latest ...` | Normal install/update on any machine. | Requires npm registry access. |
69
- | Git checkout + `python uscha-kit/install-uscha.py ...` | Developing Uscha itself or testing unreleased changes. | You must clone/pull the repo yourself. |
70
- | `--mode link` from a checkout | This machine develops the kit and installed skills should follow local edits. | Links are great for development, risky for normal users. |
71
- | Claude Code plugin commands | You specifically want Claude Code's native plugin flow. | Codex still needs the npm/git installer path. |
72
- | Manual copy | Debugging the installer. | Easy to drift; not recommended for adoption. |
73
-
74
- Development checkout example:
75
-
76
- ```bash
77
- git clone https://github.com/andresmassello/uscha.git
78
- cd uscha
79
- python uscha-kit/install-uscha.py install --target both --mode link --dry-run
80
- python uscha-kit/install-uscha.py install --target both --mode link
81
- ```
82
-
83
- Claude Code plugin option:
84
-
85
- ```text
86
- /plugin marketplace add andresmassello/uscha
87
- /plugin install uscha@uscha
88
- ```
89
-
90
- ## Update and verify
91
-
92
- ```bash
93
- npm view @andresmassello/uscha version
94
- npx --yes @andresmassello/uscha@latest version
95
- npx --yes @andresmassello/uscha@latest install --target both
96
- npx --yes @andresmassello/uscha@latest doctor --target both
97
- ```
98
-
99
- If `npm view` returns `404` immediately after a new release, wait a few minutes:
100
- npm search/dist-tags can propagate before the package metadata endpoint used by
101
- `npx`. Do not republish the same version while propagation is in progress.
1
+ # Install Uscha
2
+
3
+ Uscha installs as a machine-level helper for coding agents. The recommended path
4
+ is npm/npx because it works the same on a fresh Codex or Claude Code machine.
5
+
6
+ ## Quick path
7
+
8
+ ### Codex Desktop
9
+
10
+ ```bash
11
+ npx --yes @andresmassello/uscha@latest version
12
+ npx --yes @andresmassello/uscha@latest install --target codex --dry-run
13
+ npx --yes @andresmassello/uscha@latest install --target codex
14
+ npx --yes @andresmassello/uscha@latest doctor --target codex
15
+ ```
16
+
17
+ Then restart Codex or open a new thread. The installer registers Uscha as a
18
+ personal local plugin under `~/plugins/uscha` and updates
19
+ `~/.agents/plugins/marketplace.json`. It preflights that marketplace before replacing the plugin tree and writes the install marker last.
20
+
21
+ ### Claude Code
22
+
23
+ ```bash
24
+ npx --yes @andresmassello/uscha@latest install --target claude --dry-run
25
+ npx --yes @andresmassello/uscha@latest install --target claude
26
+ npx --yes @andresmassello/uscha@latest doctor --target claude
27
+ ```
28
+
29
+ This installs the `uscha-*` skills and registers a portable Python `PreToolUse` hook under `~/.claude` while preserving unrelated `settings.json` entries. Restart or reload Claude Code after installing.
30
+
31
+ ### Same machine uses both
32
+
33
+ ```bash
34
+ npx --yes @andresmassello/uscha@latest install --target both --dry-run
35
+ npx --yes @andresmassello/uscha@latest install --target both
36
+ npx --yes @andresmassello/uscha@latest doctor --target both
37
+ ```
38
+
39
+ ## Prepare a project repo
40
+
41
+ After the machine install, initialize each project where Uscha should govern the
42
+ workflow:
43
+
44
+ ```bash
45
+ npx --yes @andresmassello/uscha@latest init --repo . --dry-run
46
+ npx --yes @andresmassello/uscha@latest init --repo .
47
+ # Existing differing files are preserved; use --force only to replace them deliberately.
48
+ npx --yes @andresmassello/uscha@latest init --repo . --force
49
+ ```
50
+
51
+ `init` exits nonzero and reports conflicts for differing `uscha.config.json`, `CLAUDE.md`, `CONSTITUTION.md`, or `.gitattributes`; `--dry-run` performs the same conflict check without writing.
52
+
53
+ Project state stays in the project: `uscha.config.json`, `QA-LEDGER.json`,
54
+ `ACCEPTANCE.md`, and approved golden fixtures when used.
55
+
56
+ ## See the dashboard (mirador)
57
+
58
+ From the root of any project that has a `QA-LEDGER.json`, one command renders the mirador and
59
+ opens it no python, no paths:
60
+
61
+ ```bash
62
+ npx --yes @andresmassello/uscha@latest mirador # one glance: render + open
63
+ npx --yes @andresmassello/uscha@latest mirador --watch # live second-screen view (auto-refresh)
64
+ ```
65
+
66
+ It defaults to the `QA-LEDGER.json` convention in the current directory (pass `--ledger` to
67
+ point elsewhere) and prints the absolute path it wrote. `--watch` re-renders every `--interval`
68
+ seconds (default 30) into one self-reloading tab.
69
+
70
+ ## Requirements
71
+
72
+ | Requirement | Why |
73
+ |-------------|-----|
74
+ | Node.js + npm | Runs the universal `npx` entrypoint. |
75
+ | Python 3.8+ | Runs the canonical stdlib installer and engine. |
76
+ | Git | Used by the method and by project setup checks. |
77
+ | Codex Desktop and/or Claude Code | The agent runtime you want to install Uscha into. |
78
+
79
+ No `pip install` is required. The engine is Python stdlib-only.
80
+
81
+ ## Other install options
82
+
83
+ | Option | Use when | Tradeoff |
84
+ |--------|----------|----------|
85
+ | `npx @andresmassello/uscha@latest ...` | Normal install/update on any machine. | Requires npm registry access. |
86
+ | Git checkout + `python uscha-kit/install-uscha.py ...` | Developing Uscha itself or testing unreleased changes. | You must clone/pull the repo yourself. |
87
+ | `--mode link` from a checkout | This machine develops the kit and installed skills should follow local edits. | Links are great for development, risky for normal users. |
88
+ | Claude Code plugin commands | You specifically want Claude Code's native plugin flow. | Codex still needs the npm/git installer path. |
89
+ | Manual copy | Debugging the installer. | Easy to drift; not recommended for adoption. |
90
+
91
+ Development checkout example:
92
+
93
+ ```bash
94
+ git clone https://github.com/andresmassello/uscha.git
95
+ cd uscha
96
+ python uscha-kit/install-uscha.py install --target both --mode link --dry-run
97
+ python uscha-kit/install-uscha.py install --target both --mode link
98
+ ```
99
+
100
+ Claude Code plugin option:
101
+
102
+ ```text
103
+ /plugin marketplace add andresmassello/uscha
104
+ /plugin install uscha@uscha
105
+ ```
106
+
107
+ ## Update and verify
108
+
109
+ ```bash
110
+ npm view @andresmassello/uscha version
111
+ npx --yes @andresmassello/uscha@latest version
112
+ npx --yes @andresmassello/uscha@latest install --target both
113
+ npx --yes @andresmassello/uscha@latest doctor --target both
114
+ ```
115
+
116
+ `doctor` exits 1 for any unhealthy target in either text or `--json` mode. It checks installed skill presence, manifest/marketplace or hook registration, marker, and version; it does not measure file-content integrity.
117
+
118
+ If `npm view` returns `404` immediately after a new release, wait a few minutes:
119
+ npm search/dist-tags can propagate before the package metadata endpoint used by
120
+ `npx`. Do not republish the same version while propagation is in progress.
@@ -1,6 +1,6 @@
1
1
  # uscha-kit
2
2
 
3
- **Kit version:** v1.40.2 <!-- uscha:version -->
3
+ **Kit version:** v1.43.0 <!-- uscha:version -->
4
4
 
5
5
  Spec-driven orchestrator + multi-repo QA for Claude Code, with a deterministic ledger.
6
6
  **Eight skills** (`uscha-discovery`, `uscha-adr-refine`, `uscha-devloop`, `uscha-sysdoc`, `uscha-reverse-discovery`,
@@ -130,8 +130,11 @@ BEFORE touching anything.
130
130
  | test count | `cargo nextest run` + copy (see note) | `reports/junit.xml` (wrapped JUnit supported) |
131
131
  | clippy | `cargo clippy --message-format=json > reports/clippy.json` | `reports/clippy.json` (JSONL: error→HIGH · warning→MEDIUM · `code:null` compile-error→HIGH; summaries without span ignored) |
132
132
 
133
- `ingest-gate` with explicit `--clippy` or by type. The inline `#[cfg(test)]` tests
134
- count as prod LOC (documented limitation); `tests/` = integration.
133
+ `ingest-gate` with explicit `--clippy` or by type. Its JSONL evidence is fail-closed:
134
+ each nonblank line must be a UTF-8 Cargo JSON object with a string `reason`; malformed
135
+ records or malformed compiler diagnostics are rejected before ledger mutation. An empty
136
+ file plus valid Cargo summaries and span-less diagnostic summaries remain clean/noise.
137
+ The inline `#[cfg(test)]` tests count as prod LOC (documented limitation); `tests/` = integration.
135
138
  **Watch out for junit**: nextest does NOT emit JUnit by default — you have to enable it in
136
139
  `.config/nextest.toml` (`[profile.default.junit] path = "junit.xml"`) and the file
137
140
  lands in `target/nextest/default/junit.xml`; copy it to `reports/junit.xml`
@@ -166,6 +169,13 @@ BEFORE touching anything.
166
169
  Bazel/make) belongs to the per-repo adapter — the kit only requires that the reports exist.
167
170
  `cmake-build-*` (any CLion profile) and `_deps` are excluded from the LOC.
168
171
 
172
+ **Text-report boundary:** mypy, tsc, and clang-tidy ingest only their recognized diagnostic
173
+ lines. Their legitimate clean/noise forms include status/success text, tool summaries, and
174
+ (for clang-tidy) passed-through compiler output, so a nonempty unmatched line is not safely
175
+ distinguishable from a clean report. The kit deliberately does **not** invent fail-closed
176
+ heuristics for those text formats; use their structured output where a fail-closed schema is
177
+ required.
178
+
169
179
  Kotlin/JVM with Gradle (`type: gradle`, kit 1.9.0) — **Kotlin over Maven already
170
180
  works with `type: maven`** (`.kt` has always counted; JaCoCo/Surefire don't
171
181
  distinguish JVM language). This type is for the common Gradle case:
@@ -287,7 +297,7 @@ claude --add-dir ../backend-api --add-dir ../mobile-app
287
297
  Inside Claude Code, invoke the orchestrator (with the ADR/PLAN ready or ask it for one):
288
298
 
289
299
  ```
290
- /dev-loop
300
+ /uscha-devloop
291
301
  ```
292
302
 
293
303
  The skill handles the phases on its own: plan → coverage gate → (characterization if needed)
@@ -327,7 +337,7 @@ result, not on effort spent**:
327
337
 
328
338
  ```bash
329
339
  python3 $QL readiness --acceptance ACCEPTANCE.md
330
- python3 $QL readiness --json # consumed by sys-doc (traffic-light widget)
340
+ python3 $QL readiness --json # consumed by uscha-sysdoc (traffic-light widget)
331
341
  python3 $QL execution-policy --phase qa # one-line methodology/model/effort routing
332
342
  python3 $QL production-finding --repo backend-api --severity HIGH --title "..." --evidence "..."
333
343
  python3 $QL spec-doubt --repo backend-api --kind spec-wrong --note "..." --evidence "..."
@@ -371,7 +381,7 @@ python3 $QL rebuild --mode baseline --config uscha.config.json # → REBUILD-B
371
381
  # SPEC/ADR/ACCEPTANCE, PRESERVING the tests, and run the suite.
372
382
  # 3) score the regenerated tree against the baseline
373
383
  python3 $QL rebuild --mode compare --baseline REBUILD-BASELINE.json # exit 0 = COVERS
374
- python3 $QL rebuild --mode compare --baseline REBUILD-BASELINE.json --json # consumed by sys-doc
384
+ python3 $QL rebuild --mode compare --baseline REBUILD-BASELINE.json --json # consumed by uscha-sysdoc
375
385
  ```
376
386
 
377
387
  - Dimensions/weights: tests 60, acceptance 20, coverage 15, surface 5. The dominant signal
@@ -388,7 +398,7 @@ The **Simplicity** invariant of the CONSTITUTION made a deterministic gate: it s
388
398
  ```bash
389
399
  git diff --unified=0 <base> | python3 $QL simplicity-check --config uscha.config.json
390
400
  python3 $QL simplicity-check --from-git --base main # uses git for you
391
- python3 $QL simplicity-check --diff changes.diff --json # consumed by sys-doc / CI
401
+ python3 $QL simplicity-check --diff changes.diff --json # consumed by uscha-sysdoc / CI
392
402
  ```
393
403
 
394
404
  - Dimensions/weights: diff_size 35, nesting 30, net_growth 20, fan_out 8, blob 7
@@ -403,10 +413,11 @@ python3 $QL simplicity-check --diff changes.diff --json # consumed by sys
403
413
 
404
414
  ## Ledger subcommands
405
415
 
406
- `doctor · init · snapshot · check-coverage · log-step · ingest-gate · log-gate · flag-blocker ·
407
- converged · oscillation · escalate · resolve-escalation · summary · readiness · execution-policy · production-finding · spec-doubt · rebuild ·
408
- simplicity-check · pit-check · gate-check · spec-check · golden-diff · regression-check ·
409
- phase · rubric-ingest · doctor` each with `--help`.
416
+ `doctor - rubric-ingest - init - snapshot - check-coverage - log-step - ingest-gate - phase -
417
+ converged - oscillation - escalate - resolve-escalation - log-gate - flag-blocker -
418
+ production-finding - spec-doubt - spec-change-request - regression-check - summary - readiness -
419
+ execution-policy - dashboard - rebuild - simplicity-check - waste-check - pit-check - gate-check -
420
+ spec-check - golden-diff` - the exact current `qa_ledger.py` parser surface; each supports `--help`.
410
421
 
411
422
  The **fact gates** (golden-diff, gate-check, pit-check, simplicity) are PERSISTED with
412
423
  `log-gate`: a fail blocks convergence and caps readiness ≤65 via the ledger. A CONSTITUTION
@@ -453,5 +464,5 @@ Inside Claude Code, ask it:
453
464
  List the active rules from CLAUDE.md and the available skills.
454
465
  ```
455
466
 
456
- The protocol rules and the commands /uscha-discovery /uscha-adr-refine
457
- /uscha-devloop /uscha-sysdoc should appear. (For the machine's toolchain: `bash uscha-kit/workbench-doctor.sh`.)
467
+ The protocol rules and the commands `/uscha-discovery`, `/uscha-adr-refine`,
468
+ `/uscha-devloop`, and `/uscha-sysdoc` should appear. (For the machine's toolchain: `bash uscha-kit/workbench-doctor.sh`.)
package/uscha-kit/VERSION CHANGED
@@ -1 +1 @@
1
- uscha-kit 1.40.2
1
+ uscha-kit 1.43.0
@@ -18,11 +18,23 @@ los linters del static gate, drivers) es el *adapter* del proyecto y vive en el
18
18
  | **Python 3.8+** | corre `qa_ledger.py` (stdlib pura, sin dependencias) | `python3` en PATH |
19
19
  | **git** | versionado | 2.x, con `user.name`/`user.email` |
20
20
  | **gh** (GitHub CLI) | crear repo / abrir PR | opcional pero recomendado |
21
- | **skills del kit** | `discovery`, `adr-refine`, `dev-loop`, `sys-doc` | copiados a `~/.claude/skills/` |
21
+ | **skills del kit (8)** | `uscha-discovery`, `uscha-adr-refine`, `uscha-devloop`, `uscha-sysdoc`, `uscha-reverse-discovery`, `uscha-characterize`, `uscha-rubric`, `uscha-mirador` | instalados por `npx` en Codex y/o Claude Code |
22
22
  | **skills de QA** | `code-review`, `judgment-day`, `improve` | tus skills globales (el dev-loop los **orquesta**, no los trae) |
23
23
 
24
24
  ---
25
25
 
26
+ ## Camino feliz: instalar Uscha con npx
27
+
28
+ Uscha instala los skills y la configuracion para Codex, Claude Code o ambos:
29
+
30
+ ```bash
31
+ npx --yes @andresmassello/uscha@latest version
32
+ npx --yes @andresmassello/uscha@latest install --target both
33
+ npx --yes @andresmassello/uscha@latest doctor --target both
34
+ ```
35
+
36
+ `--target codex` o `--target claude` limita la instalacion a un solo entorno. Este es el camino recomendado y portable.
37
+
26
38
  ## 2. Instalar Claude Code
27
39
 
28
40
  **Native installer (recomendado — no requiere Node, se auto-actualiza):**
@@ -87,6 +99,8 @@ gh auth login # habilita gh repo create / gh pr
87
99
 
88
100
  ## 5. Instalar los skills del kit
89
101
 
102
+ **Manual, avanzado/legacy (solo Claude Code; preferi `npx` arriba):**
103
+
90
104
  **Global (todos los repos):**
91
105
 
92
106
  ```bash
@@ -102,14 +116,14 @@ cp -r uscha-kit/.claude/skills <repo>/.claude/
102
116
  cp uscha-kit/uscha.config.json <repo>/ # config en la raíz del repo
103
117
  ```
104
118
 
105
- **Verificar:** abrí `claude` y mirá `/help` deberían aparecer `/discovery`,
106
- `/adr-refine`, `/dev-loop`, `/sys-doc`. O `ls ~/.claude/skills`.
119
+ **Verificar:** abra `claude` y mire `/help`: deberian aparecer `/uscha-discovery`,
120
+ `/uscha-adr-refine`, `/uscha-devloop`, `/uscha-sysdoc` y las otras cuatro skills del kit. O `ls ~/.claude/skills`.
107
121
 
108
122
  ---
109
123
 
110
124
  ## 6. Los skills de QA externos (dependencia)
111
125
 
112
- El `dev-loop` **orquesta** `code-review` / `judgment-day` / `improve` — **no los empaqueta**.
126
+ El `uscha-devloop` **orquesta** `code-review` / `judgment-day` / `improve` — **no los empaqueta**.
113
127
  Tienen que estar en `~/.claude/skills/` (tus skills globales). Si usás otros nombres,
114
128
  editá `qa_tools_order` en `uscha.config.json`. Si no los tenés, el loop no encuentra
115
129
  las tools de juicio (igual corre el static gate determinístico).
@@ -173,6 +187,6 @@ claude whoami # cuenta autenticada
173
187
  - [ ] `python3 --version` ≥ 3.8
174
188
  - [ ] git configurado (`user.name` / `user.email`)
175
189
  - [ ] `gh auth login` hecho (si vas a abrir PRs)
176
- - [ ] `/discovery` `/adr-refine` `/dev-loop` `/sys-doc` aparecen en `/help`
190
+ - [ ] `/uscha-discovery` `/uscha-adr-refine` `/uscha-devloop` `/uscha-sysdoc` aparecen en `/help`
177
191
  - [ ] `code-review` / `judgment-day` / `improve` presentes (o `qa_tools_order` ajustado)
178
192
  - [ ] `uscha.config.json` en la raíz del repo