@andresmassello/uscha 1.67.0 → 1.69.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.
@@ -5,9 +5,10 @@ description: >
5
5
  inverse of discovery: the system already exists and its behavior IS the truth, so you
6
6
  EXTRACT facts instead of proposing shape. Produce ONLY facts — a system map (endpoints,
7
7
  contracts, dependency graph, module candidates via static analysis) and a golden suite
8
- captured mechanically at the boundaries — plus CANDIDATE specs in quarantine
9
- (discovery/, evidence + confidence mandatory), which NEVER promote without a human
10
- verdict in BEHAVIOR-LEDGER.md (ADR-009, INV-CURATION-01: the engine measures the gate).
8
+ captured mechanically at the boundaries — plus a typed CANDIDATE-DELTA of quarantined
9
+ observations (discovery/CANDIDATE-DELTA.json, evidence class + provenance mandatory),
10
+ which NEVER promote without a per-observation human verdict recorded by `curate`
11
+ (ADR-013, INV-CURATION-01: the engine measures the gate).
11
12
  Invoke for "reverse-discovery",
12
13
  "migrar/modernizar este sistema", "caracterizar el sistema viejo antes de tocarlo".
13
14
  allowed-tools: Read, Write, Glob, Grep, Bash
@@ -18,8 +19,9 @@ disable-model-invocation: false
18
19
 
19
20
  `uscha-discovery` is greenfield: you only have an idea, so you PROPOSE the shape. This is the
20
21
  opposite. The system already runs; its observable behavior is the ground truth. **Facts
21
- first, always — and what cannot be fact yet becomes a CANDIDATE in quarantine: evidenced,
22
- confidence-tagged, and promoted to the contract only by a human verdict (ADR-009).**
22
+ first, always — and what cannot be fact yet becomes an OBSERVATION in quarantine: typed,
23
+ evidence-classed, content-addressed, and promoted to the contract only by a per-observation
24
+ human verdict (ADR-013).**
23
25
 
24
26
  ## First contact (show ONCE, then never again)
25
27
 
@@ -32,9 +34,9 @@ breadcrumb. Repeating it every run would be exactly the ceremony the method forb
32
34
  [uscha · reverse-discovery · START]
33
35
  Method: you bring the idea, the method builds the rest. Facts block, guesses advise;
34
36
  nothing closes on a checkbox, and the human approves the merge.
35
- Here: I EXTRACT facts and CANDIDATES from the system that already exists. Candidates stay quarantined until YOUR verdict promotes them.
36
- Output: SYSTEM-MAP.md · DISCOVERY-SUMMARY.md -- endpoints, contracts, dependency graph,
37
- module candidates + discovery/ candidates + BEHAVIOR-LEDGER.md. The verdicts are yours.
37
+ Here: I EXTRACT facts and OBSERVATIONS from the system that already exists. Observations stay quarantined until YOUR verdict promotes them.
38
+ Output: SYSTEM-MAP.md · DISCOVERY-SUMMARY.md · discovery/CANDIDATE-DELTA.json (+ rendered
39
+ .md twin) -- endpoints, contracts, dependency graph, typed observations. The verdicts are yours, one OBS at a time.
38
40
  Next: `/uscha-characterize` freezes current behavior and a HUMAN approves the golden;
39
41
  only judged candidates reach the migration SPEC; the golden stays the oracle.
40
42
  Stop: say so at any point -- whatever is already written stays.
@@ -100,21 +102,26 @@ the exact blind spot the golden exists to counter. The old rule banned authoring
100
102
  claims outright; ADR-009 renegotiated it: **you may author them as CANDIDATES, in
101
103
  quarantine, and you may NEVER judge or promote them.**
102
104
 
103
- - Every candidate lives in `discovery/`, with mandatory frontmatter: `evidence.type`
104
- (`test | code | inference`), `evidence.refs` (real `file:line(s)` — the engine resolves
105
- them; a ref that does not resolve makes the candidate invalid, named), and `confidence`
106
- (`inference` is ALWAYS `low`).
105
+ - Every observation lives in `discovery/CANDIDATE-DELTA.json` (ADR-013), typed
106
+ (`behavior | invariant | contract | config | dependency | decision_trace`) with a strict
107
+ evidence class the ENGINE assigns: `measured` (a ledger-ingested golden/characterization
108
+ run — real execution, nothing else), `static` (deterministic extraction — if AST/regex
109
+ cannot establish it, it is not static), `narrated` (your inference: legitimate, useful,
110
+ and labeled). You supply ONLY the narrated ones, as `{type, statement, files}`; refs must
111
+ resolve (a ref that does not makes the input invalid, named). OBS ids are
112
+ content-addressed — never invent or edit one.
107
113
  - **You capture; you do not judge.** Never decide whether a behavior is bug or feature —
108
114
  that is the verdict (`preserve` / `fix` / `undefined`), it belongs to the human, and it
109
- lands in `BEHAVIOR-LEDGER.md` with an ADR per verdict. You may present a candidate with
110
- its evidence and ASK; you may write the skeleton row once the human decides; the verdict
111
- itself is theirs.
112
- - The gate is MEASURED, not promised: `qa_ledger.py curation-check` blocks the forward flow
113
- while any candidate lacks a verdict (INV-CURATION-01) — and a malformed candidate or a
114
- tampered ledger blocks harder (`exit 2`), because "could not validate" must never read
115
- as judged.
116
- - The ledger is append-only (verified against git): reverting a verdict is a NEW row plus a
117
- new ADR, never an edit.
115
+ is recorded as an append-only ledger object by `curate`, one OBS at a time (no batch path
116
+ exists, and the CLI refuses to grow one). You may present an observation with its
117
+ evidence and ASK; you run `curate` once the human decides; the verdict itself is theirs.
118
+ - The gate is MEASURED, not promised: `promote` refuses over ANY uncurated OBS naming the
119
+ ids, and `phase --require pr-ready` blocks while they exist (INV-CURATION-01) — and a
120
+ malformed or hand-edited delta blocks harder (`exit 2`), because "could not validate"
121
+ must never read as judged.
122
+ - Re-curation SUPERSEDES, never deletes: a changed mind is a new ledger record; both stay
123
+ retrievable. (Repos still on the 1.64 `.md`-candidate flow: `curation-check` +
124
+ `BEHAVIOR-LEDGER.md` keep working unchanged; new runs use the delta.)
118
125
 
119
126
  ## Phase 1 — Map (fact)
120
127
 
@@ -143,27 +150,36 @@ Delegate to the `uscha-characterize` skill; if it is not installed, follow its c
143
150
  inputs of past bugs. A boundary whose corpus does not exercise its known branches is
144
151
  marked **PARTIAL**, never covered.
145
152
 
146
- ## Phase 3 — Candidates (claims, quarantined)
153
+ ## Phase 3 — Candidates (the typed delta, quarantined)
147
154
 
148
- For every observable behavior the map + golden surface, emit one candidate file in
149
- `discovery/` (`NNN-short-slug.md`): frontmatter per the section above, then a short
150
- description of the behavior — what it does, not whether it should. Undesigned edge cases
151
- are captured too, as `inference`/`low`. Then run:
155
+ For every observable behavior the map + golden surface that is NOT already a mechanical
156
+ fact, write one narrated observation — `{type, statement, files}` — into a JSON list
157
+ (e.g. `discovery/narrated.json`). Undesigned edge cases are captured too; they are
158
+ inference, and the engine will label them `narrated`. Then run:
152
159
 
153
160
  ```bash
154
- python qa_ledger.py curation-check --repo <name>
161
+ python qa_ledger.py discover --repo <name> --narrated discovery/narrated.json
155
162
  ```
156
163
 
157
- Echo its output verbatim — it names invalid candidates and everything awaiting verdict.
164
+ The engine derives the `measured` observations (from ingested golden runs) and the
165
+ `static` ones (deterministic extractors — Python-only in v0; other stacks are reported
166
+ UNSUPPORTED, never guessed) itself, assigns content-addressed OBS ids, and emits
167
+ `discovery/CANDIDATE-DELTA.json` plus the rendered `.md` twin. Echo its summary verbatim.
158
168
  The skill wires; the engine measures.
159
169
 
160
- ## Phase 4 — Curation (the human's verdicts)
170
+ ## Phase 4 — Curation (the human's verdicts, one OBS at a time)
161
171
 
162
- Present one candidate at a time: the behavior, its evidence refs, its confidence. Ask for
163
- the verdict. On each answer, append the ledger row (`| # | candidate | evidence |
164
- confidence | verdict | ADR-RD-NNN |`) and write the skeleton `ADR-RD-NNN` (5-10 lines:
165
- context, evidence, verdict, consequence) for the human to complete. Re-run `curation-check`
166
- after the pass: exit 0 means every candidate is judged and the quarantine is clear.
172
+ Present one observation at a time: the statement, its evidence class, its provenance.
173
+ Ask for the verdict. On each answer run:
174
+
175
+ ```bash
176
+ python qa_ledger.py curate --repo <name> --obs OBS-xxxxxxxxxxxx --verdict preserve|fix|undefined [--note "..."]
177
+ ```
178
+
179
+ After the pass run `promote --repo <name>`: `preserve` moves into
180
+ `discovery/CANONICAL.json` with `derived_from` lineage, `fix` becomes an
181
+ `ISSUES-DEFERRED.md` work item (never canonical), `undefined` stays open in the readouts.
182
+ A refusal naming uncurated ids means the pass is not done — never work around it.
167
183
 
168
184
  ## Phase 5 — Summary (facts, no opinion)
169
185
 
@@ -173,9 +189,9 @@ to write the migration SPEC. Do not editorialize.
173
189
 
174
190
  ## What you do NOT do (the human's job)
175
191
 
176
- - Do NOT record a verdict, promote a candidate, or skip the ledger — the quarantine gate
177
- is the human's, and the engine measures it (INV-CURATION-01).
178
- - Do NOT write the migration SPEC — only judged candidates feed it, and the human writes it.
192
+ - Do NOT choose a verdict, batch-curate, or skip the gate — the verdict is the human's per
193
+ OBS; you only run `curate` with what they decided (INV-CURATION-01).
194
+ - Do NOT write the migration SPEC — only judged observations feed it, and the human writes it.
179
195
  - Do NOT decide the NEW structure (module boundaries, shared kernel, sync vs events). Those
180
196
  are forward decisions → `/uscha-adr-refine`.
181
197
 
@@ -189,17 +205,17 @@ to write the migration SPEC. Do not editorialize.
189
205
  ## Convergence — finish when
190
206
 
191
207
  The map is complete (every boundary and dependency accounted for, or explicitly marked
192
- unknown), the golden is captured and **human-approved**, every candidate has a verdict
193
- (`curation-check` exits 0 — measured, not remembered), and the coverage report states
208
+ unknown), the golden is captured and **human-approved**, every observation has a verdict
209
+ (`promote` runs without refusal — measured, not remembered), and the coverage report states
194
210
  what is covered vs PARTIAL. State plainly that the facts are ready, then hand off.
195
211
 
196
212
  ## Handoff
197
213
 
198
- > "Read SYSTEM-MAP.md, DISCOVERY-SUMMARY.md and BEHAVIOR-LEDGER.md, and inspect the
199
- > approved golden. The facts are measured; the verdicts are yours and recorded. Now write
200
- > the migration SPEC from the JUDGED candidates — `preserve` == golden must match, `fix` ==
201
- > divergence declared by its ADR, `undefined` == out of contract — and take the partition
202
- > decisions via /uscha-adr-refine."
214
+ > "Read SYSTEM-MAP.md, DISCOVERY-SUMMARY.md and discovery/CANONICAL.json (with its
215
+ > CANDIDATE-DELTA twin), and inspect the approved golden. The facts are measured; the
216
+ > verdicts are yours and recorded. Now write the migration SPEC from the JUDGED
217
+ > observations — `preserve` == golden must match, `fix` == an ISSUES-DEFERRED work item,
218
+ > `undefined` == out of contract — and take the partition decisions via /uscha-adr-refine."
203
219
 
204
220
  Flow (migration): `uscha-reverse-discovery` (facts) → human writes SPEC + `/uscha-adr-refine` (forward
205
221
  module decisions) → `/uscha-devloop` (restructure; `golden-diff` + `ApplicationModules.verify()`
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
3
3
  "name": "uscha",
4
- "version": "1.67.0",
4
+ "version": "1.69.0",
5
5
  "displayName": "Uscha",
6
- "description": "Spec-driven development for LLM coding agents: 9 skills (discovery, adr-refine, reverse-discovery, characterize, devloop, sysdoc, rubric, mirador, status) + a stdlib measurement engine (qa_ledger.py, 35 subcommands + universal installer + npm/npx router). Facts block, guesses advise; the human approves.",
6
+ "description": "Spec-driven development for LLM coding agents: 9 skills (discovery, adr-refine, reverse-discovery, characterize, devloop, sysdoc, rubric, mirador, status) + a stdlib measurement engine (qa_ledger.py, 40 subcommands + universal installer + npm/npx router). Facts block, guesses advise; the human approves.",
7
7
  "author": {
8
8
  "name": "Andres Massello",
9
9
  "url": "https://github.com/andresmassello"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uscha",
3
- "version": "1.67.0",
3
+ "version": "1.69.0",
4
4
  "description": "Uscha spec-driven development methodology for coding agents. Includes npm/npx router.",
5
5
  "author": {
6
6
  "name": "Andres Massello",
@@ -1,6 +1,6 @@
1
1
  # uscha-kit
2
2
 
3
- **Kit version:** v1.67.0 <!-- uscha:version --> · **[uscha.dev](https://uscha.dev)**
3
+ **Kit version:** v1.69.0 <!-- uscha:version --> · **[uscha.dev](https://uscha.dev)**
4
4
 
5
5
  Spec-driven orchestrator + multi-repo QA for Claude Code, with a deterministic ledger.
6
6
  **Nine skills** (`uscha-discovery`, `uscha-adr-refine`, `uscha-devloop`, `uscha-sysdoc`, `uscha-reverse-discovery`,
package/uscha-kit/VERSION CHANGED
@@ -1 +1 @@
1
- uscha-kit 1.67.0
1
+ uscha-kit 1.69.0
@@ -0,0 +1 @@
1
+ {"AC-DD-01": true, "AC-DD-02": true, "AC-DD-03": true, "AC-DD-04": true, "AC-DD-05": true, "AC-DD-06": true, "AC-CU-06": true, "AC-CU-01": true, "AC-CU-02": true, "AC-CU-03": true, "AC-CU-04": true, "AC-CU-05": true, "review-m1": true, "review-m3": true, "review-h1": true}
@@ -0,0 +1 @@
1
+ {"AC-SF-01": true, "AC-SF-02": true, "AC-SF-03": true, "AC-SF-04": true, "AC-SF-05": true}
@@ -0,0 +1 @@
1
+ {"AC-FV-01": true, "AC-FV-02": true, "AC-FV-04": true, "AC-FV-05": true, "AC-FV-03": true, "review-h2": true, "review-m4": true}