@andresmassello/uscha 1.40.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +104 -0
  3. package/bin/README.md +6 -0
  4. package/bin/uscha.js +28 -0
  5. package/package.json +38 -0
  6. package/uscha-kit/.claude/skills/uscha-adr-refine/SKILL.md +161 -0
  7. package/uscha-kit/.claude/skills/uscha-characterize/SKILL.md +124 -0
  8. package/uscha-kit/.claude/skills/uscha-devloop/SKILL.md +490 -0
  9. package/uscha-kit/.claude/skills/uscha-devloop/qa_ledger.py +5602 -0
  10. package/uscha-kit/.claude/skills/uscha-discovery/SKILL.md +161 -0
  11. package/uscha-kit/.claude/skills/uscha-mirador/SKILL.md +145 -0
  12. package/uscha-kit/.claude/skills/uscha-mirador/mirador-render.py +112 -0
  13. package/uscha-kit/.claude/skills/uscha-mirador/mirador-watch.ps1 +22 -0
  14. package/uscha-kit/.claude/skills/uscha-mirador/mirador-watch.sh +26 -0
  15. package/uscha-kit/.claude/skills/uscha-mirador/mirador.template.html +586 -0
  16. package/uscha-kit/.claude/skills/uscha-mirador/telemetry-extract.py +130 -0
  17. package/uscha-kit/.claude/skills/uscha-reverse-discovery/SKILL.md +116 -0
  18. package/uscha-kit/.claude/skills/uscha-rubric/SKILL.md +79 -0
  19. package/uscha-kit/.claude/skills/uscha-sysdoc/SKILL.md +88 -0
  20. package/uscha-kit/.claude-plugin/plugin.json +24 -0
  21. package/uscha-kit/.codex-plugin/plugin.json +37 -0
  22. package/uscha-kit/CHANGELOG-1.10.0.md +84 -0
  23. package/uscha-kit/CHANGELOG-1.11.0.md +67 -0
  24. package/uscha-kit/CHANGELOG-1.12.0.md +46 -0
  25. package/uscha-kit/CHANGELOG-1.13.0.md +33 -0
  26. package/uscha-kit/CHANGELOG-1.14.0.md +42 -0
  27. package/uscha-kit/CHANGELOG-1.15.0.md +58 -0
  28. package/uscha-kit/CHANGELOG-1.16.0.md +55 -0
  29. package/uscha-kit/CHANGELOG-1.17.0.md +44 -0
  30. package/uscha-kit/CHANGELOG-1.18.0.md +42 -0
  31. package/uscha-kit/CHANGELOG-1.19.0.md +41 -0
  32. package/uscha-kit/CHANGELOG-1.2.2.md +16 -0
  33. package/uscha-kit/CHANGELOG-1.2.3.md +20 -0
  34. package/uscha-kit/CHANGELOG-1.2.4.md +10 -0
  35. package/uscha-kit/CHANGELOG-1.2.5.md +23 -0
  36. package/uscha-kit/CHANGELOG-1.2.6.md +11 -0
  37. package/uscha-kit/CHANGELOG-1.2.7.md +15 -0
  38. package/uscha-kit/CHANGELOG-1.2.8.md +24 -0
  39. package/uscha-kit/CHANGELOG-1.2.9.md +4 -0
  40. package/uscha-kit/CHANGELOG-1.20.0.md +29 -0
  41. package/uscha-kit/CHANGELOG-1.21.0.md +33 -0
  42. package/uscha-kit/CHANGELOG-1.22.0.md +60 -0
  43. package/uscha-kit/CHANGELOG-1.23.0.md +75 -0
  44. package/uscha-kit/CHANGELOG-1.24.0.md +50 -0
  45. package/uscha-kit/CHANGELOG-1.25.0.md +55 -0
  46. package/uscha-kit/CHANGELOG-1.26.0.md +70 -0
  47. package/uscha-kit/CHANGELOG-1.27.0.md +45 -0
  48. package/uscha-kit/CHANGELOG-1.28.0.md +35 -0
  49. package/uscha-kit/CHANGELOG-1.29.0.md +20 -0
  50. package/uscha-kit/CHANGELOG-1.3.0.md +74 -0
  51. package/uscha-kit/CHANGELOG-1.30.0.md +46 -0
  52. package/uscha-kit/CHANGELOG-1.31.0.md +59 -0
  53. package/uscha-kit/CHANGELOG-1.32.0.md +50 -0
  54. package/uscha-kit/CHANGELOG-1.33.0.md +46 -0
  55. package/uscha-kit/CHANGELOG-1.34.0.md +55 -0
  56. package/uscha-kit/CHANGELOG-1.35.0.md +30 -0
  57. package/uscha-kit/CHANGELOG-1.36.0.md +33 -0
  58. package/uscha-kit/CHANGELOG-1.37.0.md +41 -0
  59. package/uscha-kit/CHANGELOG-1.38.0.md +11 -0
  60. package/uscha-kit/CHANGELOG-1.39.0.md +14 -0
  61. package/uscha-kit/CHANGELOG-1.4.0.md +68 -0
  62. package/uscha-kit/CHANGELOG-1.40.0.md +16 -0
  63. package/uscha-kit/CHANGELOG-1.40.1.md +11 -0
  64. package/uscha-kit/CHANGELOG-1.5.0.md +64 -0
  65. package/uscha-kit/CHANGELOG-1.6.0.md +57 -0
  66. package/uscha-kit/CHANGELOG-1.7.0.md +74 -0
  67. package/uscha-kit/CHANGELOG-1.8.0.md +46 -0
  68. package/uscha-kit/CHANGELOG-1.9.0.md +112 -0
  69. package/uscha-kit/LICENSE +21 -0
  70. package/uscha-kit/README.md +497 -0
  71. package/uscha-kit/VERSION +1 -0
  72. package/uscha-kit/WORKBENCH.md +178 -0
  73. package/uscha-kit/hooks/block-approved-writes.ps1 +46 -0
  74. package/uscha-kit/hooks/hooks.json +15 -0
  75. package/uscha-kit/install-uscha.py +344 -0
  76. package/uscha-kit/skills/uscha-adr-refine/SKILL.md +161 -0
  77. package/uscha-kit/skills/uscha-characterize/SKILL.md +124 -0
  78. package/uscha-kit/skills/uscha-devloop/SKILL.md +490 -0
  79. package/uscha-kit/skills/uscha-devloop/qa_ledger.py +5602 -0
  80. package/uscha-kit/skills/uscha-discovery/SKILL.md +161 -0
  81. package/uscha-kit/skills/uscha-mirador/SKILL.md +145 -0
  82. package/uscha-kit/skills/uscha-mirador/mirador-render.py +112 -0
  83. package/uscha-kit/skills/uscha-mirador/mirador-watch.ps1 +22 -0
  84. package/uscha-kit/skills/uscha-mirador/mirador-watch.sh +26 -0
  85. package/uscha-kit/skills/uscha-mirador/mirador.template.html +586 -0
  86. package/uscha-kit/skills/uscha-mirador/telemetry-extract.py +130 -0
  87. package/uscha-kit/skills/uscha-reverse-discovery/SKILL.md +116 -0
  88. package/uscha-kit/skills/uscha-rubric/SKILL.md +79 -0
  89. package/uscha-kit/skills/uscha-sysdoc/SKILL.md +88 -0
  90. package/uscha-kit/templates/.gitattributes +6 -0
  91. package/uscha-kit/templates/CLAUDE.md +56 -0
  92. package/uscha-kit/templates/CONSTITUTION.md +149 -0
  93. package/uscha-kit/templates/RUBRIC.md +38 -0
  94. package/uscha-kit/templates/docs/adr/README.md +19 -0
  95. package/uscha-kit/templates/rubric-grader-prompt.md +63 -0
  96. package/uscha-kit/tests/smoke-engine.sh +1739 -0
  97. package/uscha-kit/uscha.config.json +181 -0
  98. package/uscha-kit/workbench-doctor.sh +45 -0
@@ -0,0 +1,490 @@
1
+ ---
2
+ name: uscha-devloop
3
+ description: >
4
+ Spec-driven, multi-repo development + QA orchestrator. Plans from an ADR, builds,
5
+ then runs a severity-gated review loop (code-review / judgment-day / improve) that
6
+ converges instead of looping forever, with tests as a guardrail between passes.
7
+ Auto-triggers characterization tests when JaCoCo line coverage is below threshold.
8
+ Records every step in a deterministic ledger and stops at the merge gate for human
9
+ approval. Invoke for "run the dev loop", "QA this feature", "do the full cycle".
10
+ allowed-tools: Read, Edit, Write, Glob, Grep, Bash
11
+ disable-model-invocation: false
12
+ ---
13
+
14
+ # dev-loop orchestrator
15
+
16
+ **Who this is for:** a single operator driving one non-trivial or risk-bearing change,
17
+ kept honest by a deterministic ledger and a human merge gate. **NOT for trivial or
18
+ throwaway work** — a one-file fix or config tweak runs build+test only and skips
19
+ discovery/ADR/uscha-sysdoc entirely (see the risk-profile table in the playbook, play 03).
20
+
21
+ You are running a disciplined development + QA cycle across one or more repositories.
22
+ The measurement engine is `./.claude/skills/uscha-devloop/qa_ledger.py` per project, or the installed Codex/Claude global engine (stdlib Python 3).
23
+ **All metrics come from the ledger — never estimate counts from memory.** Run every
24
+ QA tool through the ledger so the final retrospective is real. The ledger contract has
25
+ two tiers: **measured** records (snapshots, ingest-gate, log-gate — parsed from real
26
+ artifacts; these can block) and **self-reported** agent counts (log-step — narration
27
+ recorded for the retrospective; a measured red always overrides a narrated green).
28
+
29
+ ## Non-negotiable principles
30
+
31
+ 1. **Converge, don't chase zero.** Block only on findings at or above the severity
32
+ gate (`config.defaults.severity_gate`, default BLOCKER/CRITICAL/HIGH). Everything
33
+ below goes to `ISSUES-DEFERRED.md`, never into the loop. Polishing Medium/Low
34
+ findings forever is the failure mode this skill exists to prevent.
35
+ 2. **Tests are a guardrail, not a finale.** Run the repo's test command (`mvn test` /
36
+ `flutter test` / `pytest` / `npm test` / `go test` / `cargo test` / `dotnet test` / `ctest` / `./gradlew test` / `swift test`) after every tool pass that changed code. A red suite
37
+ stops the loop.
38
+ 3. **Generating tests is not running tests.** `/improve test` (writing coverage) runs
39
+ ONCE at the end against stabilized code — never inside the loop. Inside the loop you
40
+ only *run* the existing suite.
41
+ 4. **Stop at merge.** You create the PR and confirm CI is green. You do NOT merge.
42
+ The human owns the merge gate.
43
+ 5. **Tracked-markdown protocol.** Before modifying any tracked `.md`
44
+ (CLAUDE.md, plan/delta docs, docs/adr), ask the human for the current version first.
45
+ Those files carry real progress (checkboxes, notes); never regenerate from scratch.
46
+ 6. **The golden is the one artifact you cannot author.** For migration/legacy work,
47
+ `.approved` fixtures are field truth captured from the ORIGINAL code and approved by
48
+ a HUMAN. You emit `.received` and stop; you never write, edit or rename `.approved`
49
+ (a `PreToolUse` hook denies the write — INV-GOLDEN-01).
50
+
51
+ ## Setup (once per run)
52
+
53
+ ```bash
54
+ QL="./.claude/skills/uscha-devloop/qa_ledger.py" # instalacion por proyecto
55
+ [ -f "$QL" ] || QL="$HOME/.codex/skills/uscha-devloop/qa_ledger.py" # Codex raw-skills install
56
+ [ -f "$QL" ] || QL="$HOME/plugins/uscha/skills/uscha-devloop/qa_ledger.py" # Codex plugin install
57
+ [ -f "$QL" ] || QL="$HOME/.claude/skills/uscha-devloop/qa_ledger.py" # Claude global install
58
+ python3 $QL init --config uscha.config.json
59
+ ```
60
+
61
+ ## Execution policy line (before every phase)
62
+
63
+ Before you start a phase, print the one-line routing note from the ledger, then do the
64
+ work. This tells the human what the methodology is doing and which model/effort policy is
65
+ selected for that phase:
66
+
67
+ ```bash
68
+ python3 $QL execution-policy --phase <idea|disc|spec|adr|build|qa|verify|prod>
69
+ ```
70
+
71
+ This is **routing metadata only**: it may guide the operator/adapter to use a stronger or
72
+ uncorrelated checker, but it never changes readiness and never overrides fact gates. If
73
+ `model=default`, keep the current agent model; if a phase declares a model/effort and the
74
+ host supports switching, use it for that phase.
75
+
76
+ ### Discovery intake: reality can reopen the contract
77
+
78
+ Three facts are allowed to push work back into discovery/SPEC instead of being buried as narration:
79
+
80
+ ```bash
81
+ python3 $QL production-finding --repo <REPO> --severity HIGH \
82
+ --source <sentry|support|user|prod-log> --title "..." --evidence "..."
83
+ python3 $QL spec-doubt --repo <REPO> --kind spec-wrong \
84
+ --note "why the SPEC/AC seems wrong" --evidence "demo/log/file pointer"
85
+ python3 $QL spec-change-request --repo <REPO> --source SD-001 \
86
+ --requested-change "what must change in SPEC/ADR" --evidence "demo/log/file pointer"
87
+ ```
88
+
89
+ - `production-finding` is for post-merge/prod feedback. It feeds the next discovery/SPEC cycle.
90
+ - `spec-doubt` is the builder's escape hatch when the SPEC conflicts with reality. Do **not** code around a doubtful SPEC silently; log it and ask the human.
91
+ - `spec-change-request` is the structured bridge from evidence/doubt to a human-approved SPEC/ADR amendment; an open SCR keeps the phase escalated.
92
+ - Resolve them only after the feedback was incorporated, explicitly reviewed, or the SPEC/ADR amendment decision was recorded:
93
+ `production-finding --id PF-001 --resolve --note "fed into SPEC"` / `spec-doubt --id SD-001 --resolve --decision "SPEC amended"` / `spec-change-request --id SCR-001 --resolve --decision accepted --amended ACCEPTANCE.md`.
94
+
95
+ The config lists every repo and its type (maven|flutter|python|node|go|rust|dotnet|cpp|gradle|swift). In a multi-repo session the
96
+ other repos must be mounted via `--add-dir` or `additionalDirectories`; the `path`
97
+ fields in the config are relative to where you run `init`.
98
+
99
+ For migration/legacy (risk profile E) work, also wire the golden invariant once:
100
+ install `hooks/block-approved-writes.ps1` (or its bash twin) as a `PreToolUse` hook in
101
+ `settings.json`, and add `*.approved.* binary` to `.gitattributes` (ships in
102
+ `templates/.gitattributes`) so line endings can't lie in the byte-compare.
103
+
104
+ ## Phase 0 — Plan (ADR-first)
105
+
106
+ - **Read `CONSTITUTION.md` first (if present).** It lists the project invariants no SPEC
107
+ or ADR may violate. A change that would breach an invariant is a BLOCKER — escalate, do
108
+ not work around it. The CONSTITUTION constrains the whole build.
109
+ - The ADR set + `ACCEPTANCE.md` are the input to this loop. They typically come from the
110
+ `uscha-adr-refine` skill (the front-half counterpart): `/uscha-adr-refine` → ADR set → `/uscha-devloop`.
111
+ - Confirm or write the ADR + PLAN. The plan must state **acceptance criteria** (the
112
+ `ACCEPTANCE.md` checkboxes) and the **severity gate / coverage threshold** up front.
113
+ The loop targets the plan, not "no issues". If acceptance criteria are missing, stop
114
+ and run `uscha-adr-refine` first (or ask the human).
115
+ - Acceptance criteria become the contract tests in Phase 1.
116
+
117
+ ## Phase 1 — Coverage gate → conditional characterization (per repo)
118
+
119
+ For each repo, decide whether a safety net exists before any refactoring:
120
+
121
+ ```bash
122
+ python3 $QL snapshot --repo <REPO> --phase pre
123
+ python3 $QL check-coverage --repo <REPO> # exit 0 = OK, exit 1 = BELOW threshold
124
+ ```
125
+
126
+ - **Coverage >= threshold:** the existing suite is the guardrail. Skip to Phase 2.
127
+ - **Coverage < threshold (or no report):** write **characterization / contract tests
128
+ at the boundary** (public API, endpoints, input→output behavior) — NOT internals.
129
+ These must survive refactoring. The ADR acceptance criteria are the spec for these.
130
+ **Have the human review these tests before trusting them as a gate** — a test that
131
+ passes for the wrong reason poisons the whole loop.
132
+ - **Migration/legacy (profile E): capture the golden BEFORE touching anything.** Run
133
+ the `uscha-characterize` skill (or `uscha-reverse-discovery` for a whole-system map first): it
134
+ executes the ORIGINAL code against a real input corpus, emits `.received` fixtures,
135
+ and STOPS for the human to approve them as `.approved`. No approved golden = no
136
+ migration build. This is the baseline `golden-diff` gates against in Phase 3.
137
+
138
+ ## Phase 2 — Build
139
+
140
+ Implement per the PLAN. Commit per logical step with conventional commits
141
+ (`feat:`, `fix:`, `refactor:`…) so the trail is reviewable and revertible.
142
+
143
+ ### ADR discipline during build
144
+
145
+ - **Consult before touching governed areas.** Before working on an area covered by an
146
+ accepted ADR, read it and follow its Implementation Plan (affected paths, patterns,
147
+ tests). Also re-check `CONSTITUTION.md`: if the change would breach an invariant, stop
148
+ and escalate — a constitution breach is a BLOCKER and is never resolved silently in code.
149
+ If the code contradicts the ADR, flag it to the human — never resolve the conflict
150
+ silently in code.
151
+ - **Proactive ADR triggers — stop and propose an ADR** when you are about to: introduce
152
+ a new dependency, create a new architectural pattern others must follow, choose between
153
+ real alternatives with non-obvious trade-offs, or contradict an accepted ADR. Tell the
154
+ human the decision, why it matters, and ask whether to capture it. If no, leave a short
155
+ `// ADR-not-taken: <why>` comment and move on.
156
+ - **Link code ↔ ADR.** When implementing a decision, add one lightweight comment at the
157
+ entry point: `// ADR: <slug> — see docs/adr/ADR-NNN-<slug>.md`. This makes supersede
158
+ safe (you can find all code an ADR governs).
159
+ - **Treat `Status: Experiment` as a visible hypothesis, not a license to improvise.** It
160
+ may proceed only when the ADR declares Hypothesis, Feedback Signal, Review By/Trigger,
161
+ Promote Criteria and Rollback/Supersede Criteria. `dashboard --json`/Mirador expose
162
+ malformed or expired experiment metadata as advisory; it is not a readiness score and
163
+ not a hard PR gate by itself.
164
+ - **Never edit the SPEC/ADR to make the implementation look correct.** If reality forces
165
+ a change, amend the SPEC (version it) and return to Ready.
166
+
167
+ ## Phase 2b — Simplicity gate ("Reduce")
168
+
169
+ Before the QA loop, check the change isn't overbuilt. This is the CONSTITUTION's
170
+ **Simplicidad** invariant made deterministic — diff minimality, nesting depth and new
171
+ abstractions, scored over the diff (not AST cyclomatic complexity; honest proxies):
172
+
173
+ ```bash
174
+ git diff --unified=0 <base> | python3 $QL simplicity-check --config uscha.config.json
175
+ # or: python3 $QL simplicity-check --from-git --base <base>
176
+ ```
177
+
178
+ Reads `SIMPLICITY: NN/100 — SIMPLE | ACCEPTABLE | OVERBUILT`. **OVERBUILT (exit 1) is a
179
+ BLOCKER**: reduce first (guard clauses, drop speculative types/layers, split giant hunks)
180
+ and re-run — do not carry it into the QA loop or converge on it. The flags tell you exactly
181
+ what to cut. Budgets live in `config.defaults.simplicity` (tighten per risk profile). For a
182
+ 2-space codebase pass `--indent-width 2`.
183
+
184
+ **Tests are OUTSIDE the budget** (kit 1.11.0): test files (the 9 stack conventions) are
185
+ counted and reported apart (`test_lines_added`) but never gate — writing tests must not
186
+ push a diff toward OVERBUILT (deleting them is already blocked by gate-check). A good
187
+ project can have MORE test code than production code.
188
+
189
+ **Persist the verdict** so convergence and readiness see it (facts block through the
190
+ ledger, not through your goodwill):
191
+
192
+ ```bash
193
+ python3 $QL log-gate --repo <REPO> --iteration <N> --kind simplicity \
194
+ --verdict <pass|fail> [--note "OVERBUILT: +612 lines vs 400 budget"]
195
+ ```
196
+
197
+ ### Phase 2c — REUSE-FIRST gate (kit 1.26.0)
198
+
199
+ Simplicity scores the diff in ISOLATION; it cannot see that the new block re-implements
200
+ something the repo already has. `waste-check` closes that gap — deterministic Type-1/2
201
+ clone detection of the diff **vs the repo** (the muda GitClear calls dominant in AI code):
202
+
203
+ ```bash
204
+ python3 $QL waste-check --from-git --base <base> --repo-root . --config uscha.config.json
205
+ ```
206
+
207
+ Reads `WASTE: NN/100 — LEAN | ACCEPTABLE | WASTEFUL`. **Advisory by default** (exit 0): the
208
+ flags name the existing `file:line` to reuse instead of cloning. It reports a FACT (the block
209
+ exists elsewhere) but "wasteful" is a heuristic with false positives (boilerplate, DTOs,
210
+ embedded SQL/JSON), so it does NOT block unless the human declares it — `defaults.waste.gate:
211
+ true` or `--gate`. When gated and WASTEFUL, reuse/refactor before the QA loop and persist:
212
+
213
+ ```bash
214
+ python3 $QL log-gate --repo <REPO> --iteration <N> --kind waste \
215
+ --verdict <pass|fail> [--note "clona util/money.py:40 — reusar"]
216
+ ```
217
+
218
+ It runs on **prod code only** (tests excluded, like simplicity) and skips the files the diff
219
+ touches (no self-match). Honest scope: Type-1/2 over normalized lines, not semantic clones;
220
+ tune `defaults.waste` (`allow_paths` for legit boilerplate, `window_size`, budgets). In risk
221
+ profile A (trivial change) skip it. It **collapses into `readiness`** as a `gate:waste` line.
222
+
223
+ ## Phase 3 — QA loop (per repo)
224
+
225
+ Run the tools in `config.defaults.qa_tools_order` (default: code-review → judgment-day
226
+ → improve). One pass of all tools = one cycle. After **each** tool pass:
227
+
228
+ 1. Apply only fixes at/above the severity gate. Send the rest to `ISSUES-DEFERRED.md`.
229
+ 2. Run the repo test command. If red and the fix isn't obvious → escalate.
230
+ 3. Log the agent QA tools (code-review / judgment-day / improve) with `log-step`,
231
+ using counts from each tool's own summary. These counts are **self-reported
232
+ narration** (recorded for churn/retrospective); the blocking signals in this loop
233
+ are the MEASURED records — ingest-gate, log-gate, snapshots:
234
+
235
+ ```bash
236
+ python3 $QL log-step --repo <REPO> --tool <code-review|judgment-day|improve> \
237
+ --iteration <N> \
238
+ --reported <total findings> --gated-reported <findings at/above gate> \
239
+ --fixed <fixed this pass> --deferred <sent to backlog> --suppressed <false positives> \
240
+ --tests-passed <true|false> --files-changed <count> \
241
+ --fingerprint <stable,finding,ids> # enables oscillation detection
242
+ ```
243
+
244
+ 3b. **Fact gates — on every pass that changed code**, run gate-check (did the change
245
+ weaken the measuring apparatus? did it ADD a secret? — private keys, cloud tokens and
246
+ key-container files block as facts, kit 1.12.0; generic password/token literals advise;
247
+ new dependencies advise too — the change-budget rule "no new deps without approval" made
248
+ visible, kit 1.30.0)
249
+ and, for migration work, golden-diff (does behavior still match the human-approved
250
+ baseline?). Then PERSIST each verdict with `log-gate` — a failing fact gate blocks
251
+ convergence and caps readiness ≤65 through the ledger:
252
+
253
+ **Rubric — the non-testable layer (kit 1.23.0).** If a `RUBRIC.md` exists (or
254
+ `defaults.rubric.file` declares one), on passes that changed code run the
255
+ `uscha-rubric` grade (isolated context — the grader reads ONLY diff + rubric;
256
+ evidence-or-nothing) and ingest the contract JSON:
257
+ `rubric-ingest --repo <REPO> --report reports/rubric-grade.json --iteration <N>`.
258
+ Advisory by default — it gates ONLY when the human declared
259
+ `defaults.rubric.gate: true` (then a below-threshold score blocks convergence like
260
+ any fact gate). Never declare the gate yourself.
261
+
262
+ **Find Bugs Once (kit 1.16.0).** When a pass you log carries `--fixed > 0`, run
263
+ `regression-check --repo <REPO> --from-git --base <base>`: closing findings without
264
+ adding a single NON-BLANK test-tree line is **NARRATED** closure — the failing test
265
+ goes BEFORE the fix (Tip 31), and every bug is found ONCE (Tip 94). It is a tripwire,
266
+ not a judge: any non-blank test line counts (even a comment — content across 9 stacks
267
+ is not guessed), so honor the `has_test_definition`/`has_assertion` facts and the
268
+ "evidencia DÉBIL" warning; test QUALITY is pit-check's job. NARRATED advises by
269
+ default; persist `log-gate --kind regression --verdict fail` if the team gates it.
270
+ Resolving a `flag-blocker` now REQUIRES `--escape-analysis "<which gate/test should
271
+ have caught this and what was done>"` — reflection is part of closing, not optional.
272
+
273
+ ```bash
274
+ python3 $QL gate-check --from-git --base <base> --repo <REPO> # exit 1 = BLOCKER
275
+ python3 $QL log-gate --repo <REPO> --iteration <N> --kind gate-check --verdict <pass|fail>
276
+
277
+ python3 $QL golden-diff [--dir <fixtures-root>] # exit 0 CLEAN · 1 DIVERGE · 2 NOT-RUN
278
+ python3 $QL log-gate --repo <REPO> --iteration <N> --kind golden-diff \
279
+ --verdict <pass|fail|not-run> # not-run records the absence — it is never green
280
+ ```
281
+
282
+ (pit-check stays on its scheduled/incremental tier — CONSTITUTION §Tests efectivos —
283
+ but when a PIT report EXISTS and fails the gate, persist it the same way:
284
+ `log-gate --kind pit-check --verdict fail`.)
285
+
286
+ 4. The **static analysis gate** (`java-qa-gate`: Checkstyle/PMD/SpotBugs/FindSecBugs)
287
+ is NOT counted by hand. Run the gate so its XML reports are written, then ingest
288
+ them — the ledger parses the reports, normalizes severities to the common gate
289
+ scale, splits FindSecBugs (SECURITY) out from SpotBugs, and computes the real
290
+ `fixed` count by diffing finding-IDs against the previous run:
291
+
292
+ ```bash
293
+ # run your java-qa-gate first (it must emit:
294
+ # target/checkstyle-result.xml, target/pmd.xml, target/spotbugsXml.xml)
295
+ python3 $QL ingest-gate --repo <REPO> --iteration <N>
296
+ # one static-gate step is logged per linter; pass --combined to merge into one.
297
+ ```
298
+
299
+ Severity normalization: Checkstyle error→HIGH / warning→MEDIUM; PMD priority
300
+ 1→BLOCKER … 5→LOW; SpotBugs priority 1→HIGH / 2→MEDIUM / 3→LOW; FindSecBugs
301
+ (category SECURITY) floored to HIGH. A report file that EXISTS but is empty credits the
302
+ fix; an ABSENT report is not treated as clean (means the gate didn't run).
303
+
304
+ **End-of-cycle checks (advisory — you make the final call):**
305
+
306
+ ```bash
307
+ python3 $QL converged --repo <REPO> --tools-per-cycle <count> # exit 0 = converged
308
+ python3 $QL oscillation --repo <REPO> --tool <tool> # exit 1 = oscillating
309
+ ```
310
+
311
+ Convergence requires ALL of: the latest agent step of EVERY tool in `qa_tools_order`
312
+ clean (zero gated findings, zero files changed, tests green — padding the window with
313
+ extra clean steps does not help, and a red snapshot vetoes a narrated green), AND the
314
+ latest static-gate run of every linter clean at the gate level, AND every persisted
315
+ fact gate (`gate:*`, `blocker:*` records from log-gate/flag-blocker) clean. A clean
316
+ agent cycle alone does not converge if any measured gate still flags something.
317
+
318
+ - **Converged** → leave the loop for this repo.
319
+ - **Not converged** → next cycle, up to `config.defaults.max_iterations`.
320
+
321
+ ## Phase 4 — Integration / contract pass (multi-repo)
322
+
323
+ After each repo converges individually, run the cross-repo layer with all repos mounted.
324
+ Run the integration/contract test command from the config and treat contract breakages
325
+ as gated findings. Log under `--repo integration`. This is the second layer of your
326
+ two-layer QA architecture; per-repo green does not imply the seams are green.
327
+
328
+ ## Phase 5 — Verify (coverage generation, once)
329
+
330
+ Now that code is stable:
331
+
332
+ ```bash
333
+ # /improve test → write the fine-grained coverage you deferred earlier
334
+ # Then run the full suite and regenerate coverage reports.
335
+ python3 $QL snapshot --repo <REPO> --phase post # for every repo + integration
336
+ ```
337
+
338
+ Full suite must be green and coverage at/above threshold before proceeding.
339
+
340
+ ## Phase 5b — Rebuild test (optional; risk profile C+/E or periodic CI)
341
+
342
+ Completeness of the SPEC, not correctness of the build: is the spec package enough to
343
+ regenerate the system from scratch? Worth running for critical/legacy work or on a
344
+ schedule, not every feature.
345
+
346
+ ```bash
347
+ # 1) capture the signature of the system as it stands now
348
+ python3 $QL rebuild --mode baseline --config uscha.config.json
349
+ # 2) in a CLEAN tree / fresh session, regenerate PRODUCTION code from SPEC/ADR/
350
+ # ACCEPTANCE only, PRESERVING the test suite, then run the tests.
351
+ # 3) score the regenerated tree against the baseline
352
+ python3 $QL rebuild --mode compare --baseline REBUILD-BASELINE.json # exit 0 = COVERS
353
+ ```
354
+
355
+ The dominant signal is the preserved suite: tests that passed originally but fail on
356
+ regenerated code are behavior the SPEC left implicit. Verdicts: COVERS (≥90), PARTIAL
357
+ (≥70), DIVERGE (<70). Feed the listed gaps back into the SPEC, then re-run — divergence
358
+ is a spec gap, not a code bug.
359
+
360
+ ## Phase 6 — PR (stop at merge)
361
+
362
+ - **Gate the PR on the DERIVED state (kit 1.18.0)** — per repo:
363
+
364
+ ```bash
365
+ python3 $QL phase --repo <REPO> --require pr-ready # exit 1 = the facts say no
366
+ ```
367
+
368
+ The state is COMPUTED from the ledger (converged + green tests + zero
369
+ BLOCKER/CRITICAL + no open escalation), never self-declared — if it exits 1, the
370
+ output lists exactly which facts are missing; do NOT open the PR, close the gap.
371
+ A `spike/*` branch NEVER passes this gate (kit 1.19.0): spike code is disposable
372
+ by contract — its only legitimate output is an ADR with lessons, never a merge.
373
+ - Ensure conventional-commit history is clean.
374
+ - Open the PR(s). Confirm CI is green.
375
+ - **STOP.** Present the PR link(s) and wait for the human to merge.
376
+
377
+ ## Phase 7 — Smoke list
378
+
379
+ Produce a concrete manual smoke-test checklist (real user paths / endpoints / device
380
+ flows for this change), so the human can verify the system behaves as intended.
381
+
382
+ ## Phase 8 — Hand off to docs + retrospective
383
+
384
+ ```bash
385
+ python3 $QL summary # human-readable
386
+ python3 $QL summary --json # machine-readable, includes post_merge_calibration
387
+ ```
388
+
389
+ **Readiness KPI — show this after finishing ANY task, not only full runs.** It measures
390
+ the STATE of the result (not effort spent), as a weighted score 0..100 with hard caps:
391
+
392
+ ```bash
393
+ python3 $QL readiness --acceptance <ACCEPTANCE.md> --tools-per-cycle <count>
394
+ ```
395
+
396
+ **Single-verdict view (kit 1.25.0, anti-ceremony).** By default `readiness` is ONE
397
+ screen: the verdict line, any conditional warning that actually fired (it speaks only
398
+ when it matters), and a `--- gates:` line that COLLAPSES every persisted gate record —
399
+ the per-language linter gates (`*-qa-gate` from `ingest-gate`) plus the discrete fact
400
+ gates (`gate:*` from `log-gate`, `rubric:grade`, `blocker:*` from `flag-blocker`) — into
401
+ `N ok / M bloqueando (repo/gate...)`. This
402
+ is presentation over facts already in the ledger — it never recomputes the score, so
403
+ the KPI is identical to before the rollup existed. When the acceptance file has traceable
404
+ AC-IDs, the default view also prints the honest **`acceptance medido: X%`** line (kit
405
+ 1.28.0 — criteria closed by a green name-tagged test / total; the `measured_pct` field in
406
+ `--json`): the one "% done" the kit can sign, MEASURED not narrated, informational and
407
+ never a gate. With no AC-IDs it does not print (a % over bare checkboxes would be
408
+ narrated). Pass `--verbose` to expand the dimensions table, the acceptance/coverage/churn
409
+ summary and the per-repo breakdown.
410
+ Show the human the default; reach for `--verbose` only when they ask what is inside the
411
+ number.
412
+
413
+ Dimensions and default weights: acceptance (traced, MEASURED) 30, ADR/checkbox
414
+ completion 15, coverage 15, static gate 20, convergence 10, integration 10. A
415
+ lint-capable repo whose static gate NEVER ran scores that dimension UNMEASURED (0.0) —
416
+ silence is not success. Hard caps override the weighted score: tests red → ≤35,
417
+ BLOCKER/CRITICAL open → ≤65, unresolved escalation → ≤75 (held until
418
+ `resolve-escalation` — a recorded event, not an implication). A `CONSTITUTION.md`
419
+ breach does NOT reach the engine by itself: **you MUST log it** —
420
+ `flag-blocker --repo <REPO> --kind constitution --note "<invariant breached>"` — and
421
+ once logged it caps readiness ≤65 and blocks convergence until `--resolve`. Bands:
422
+ <50 NOT READY, 50–79 IN PROGRESS, 80–94 RELEASE CANDIDATE, 95–100 READY.
423
+
424
+ **Acceptance traceability (the DOMINANT dimension — kit 1.10.0).** Each ACCEPTANCE
425
+ criterion carries a stable ID: `- [ ] AC-01 — when X then Y`. A criterion counts as
426
+ CLOSED only when ≥1 GREEN testcase whose name carries the tag (`test_ac1_x`,
427
+ `testAC01X`, `"AC-01: ..."` — IDs normalize by number, `AC-01 == AC_1 == ac1`) exists
428
+ in the ingested JUnit reports AND no tagged testcase is red. The checkbox is the
429
+ NARRATIVE; the testcase is the FACT — a checked box without a green tagged test shows
430
+ up as `narrated_only` and does NOT close (measured beats narrated, per criterion).
431
+ A JUnit report older than the repo's source code is treated as STALE (the code changed
432
+ after the tests ran) and is DISCARDED — a criterion backed only by stale reports stays
433
+ UNMEASURED, never falsely closed or vetoed (kit 1.31.0; surfaced as `stale_reports`).
434
+ So: when you write the tests for a criterion, put its AC-n in the test name; run
435
+ `spec-check --acceptance ACCEPTANCE.md` up front (zero traceable criteria / duplicate
436
+ IDs block as structural FACTS). Files without IDs fall back to the checkbox ratio
437
+ with a warning (legacy mode — adopt incrementally).
438
+
439
+ **Heed the two readiness advisories (kit 1.14.0 — they recommend, never gate).**
440
+ `stall:` = gated findings flat or RISING for 3 agent cycles: more iteration is not
441
+ approaching the solution — stop iterating, go back to the ADR / re-plan WITH the human.
442
+ `stop-signal:` = every repo converged and zero blocking facts remain: what's left is
443
+ measurable debt (coverage/acceptance), not findings — raise "candidate to cut and go
444
+ to PR" to the human instead of polishing further.
445
+
446
+ ADR completion is parsed from the **acceptance task list** (markdown `- [x]`/`- [ ]`),
447
+ read-only — set the path via `config.defaults.acceptance_file` or `--acceptance`. Count
448
+ the WHOLE file (the CLI default); only pass `--section` if you have verified the heading
449
+ text matches your template exactly — a mismatched section silently zeroes a heavy
450
+ dimension. Present the single-verdict headline (the number, the capping blocker if any,
451
+ and the collapsed `--- gates:` line); add `--verbose` only if the human wants the
452
+ dimension breakdown behind the number. Cycles/regressions are churn (process health) and
453
+ are reported separately — they never raise readiness.
454
+
455
+ Optionally (on request — reporting, not part of the verified build) invoke the `uscha-sysdoc`
456
+ skill to generate the two-view HTML deck. Finish with a retrospective drawn FROM the
457
+ ledger summary: total steps, %fixed per tool, coverage, prod LOC vs test LOC, test
458
+ count, tests/kLOC, **first-time yield** (kit 1.27.0 — the Lean % of repos that cleared
459
+ QA on the first cycle with no second pass, regression or escalation; passive, derived
460
+ from the ledger, informational only — never a gate), plus concrete methodology
461
+ improvements.
462
+
463
+ ## Escalation contract — STOP and ask the human when:
464
+
465
+ - The iteration cap is hit without convergence.
466
+ - Oscillation is detected (a finding set keeps returning).
467
+ - A previously-passing test now fails and the fix is non-trivial.
468
+ - Two tools give contradictory directives on the same code.
469
+ - A fix would require an architectural decision (ADR-level change).
470
+ - A change would breach the `CONSTITUTION.md` (an inviolable invariant) — never trade it
471
+ away; changing the constitution is a separate, explicit human decision.
472
+
473
+ Record every escalation, and record its CLOSURE — the readiness cap holds until the
474
+ human resolves it:
475
+
476
+ ```bash
477
+ python3 $QL escalate --repo <REPO> --reason "<what blocked + what you need from me>"
478
+ # ... human reviews/decides ...
479
+ python3 $QL resolve-escalation --repo <REPO> --note "<how it was closed>"
480
+ ```
481
+
482
+ A CONSTITUTION breach is escalated AND flagged as a first-class blocker:
483
+
484
+ ```bash
485
+ python3 $QL flag-blocker --repo <REPO> --kind constitution --note "<invariant breached>"
486
+ # after the human decision: flag-blocker --repo <REPO> --kind constitution --resolve
487
+ ```
488
+
489
+ Never auto-merge, never silently exceed the iteration cap, never fix below the gate to
490
+ make the number look better.