@andresmassello/uscha 2.1.0 → 2.2.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.
- package/README.md +21 -4
- package/package.json +1 -1
- package/uscha-kit/.claude/skills/uscha-adr-refine/SKILL.md +2 -0
- package/uscha-kit/.claude/skills/uscha-characterize/SKILL.md +2 -0
- package/uscha-kit/.claude/skills/uscha-devloop/SKILL.md +141 -8
- package/uscha-kit/.claude/skills/uscha-devloop/qa_ledger.py +1946 -74
- package/uscha-kit/.claude/skills/uscha-discovery/SKILL.md +58 -4
- package/uscha-kit/.claude/skills/uscha-mirador/SKILL.md +2 -0
- package/uscha-kit/.claude/skills/uscha-reverse-discovery/SKILL.md +2 -0
- package/uscha-kit/.claude/skills/uscha-rubric/SKILL.md +2 -0
- package/uscha-kit/.claude/skills/uscha-status/SKILL.md +40 -0
- package/uscha-kit/.claude/skills/uscha-sysdoc/SKILL.md +2 -0
- package/uscha-kit/.claude-plugin/plugin.json +2 -2
- package/uscha-kit/.codex-plugin/plugin.json +1 -1
- package/uscha-kit/README.md +229 -5
- package/uscha-kit/VERSION +1 -1
- package/uscha-kit/install-uscha.py +18 -2
- package/uscha-kit/skills/uscha-adr-refine/SKILL.md +2 -0
- package/uscha-kit/skills/uscha-characterize/SKILL.md +2 -0
- package/uscha-kit/skills/uscha-devloop/SKILL.md +141 -8
- package/uscha-kit/skills/uscha-devloop/qa_ledger.py +1946 -74
- package/uscha-kit/skills/uscha-discovery/SKILL.md +58 -4
- package/uscha-kit/skills/uscha-mirador/SKILL.md +2 -0
- package/uscha-kit/skills/uscha-reverse-discovery/SKILL.md +2 -0
- package/uscha-kit/skills/uscha-rubric/SKILL.md +2 -0
- package/uscha-kit/skills/uscha-status/SKILL.md +40 -0
- package/uscha-kit/skills/uscha-sysdoc/SKILL.md +2 -0
- package/uscha-kit/templates/CLAUDE.md +16 -0
- package/uscha-kit/templates/CONSTITUTION.md +45 -0
- package/uscha-kit/templates/docs/adr/README.md +15 -0
- package/uscha-kit/templates/scripts/smoke-report-example.json +24 -0
- package/uscha-kit/uscha.config.json +6 -1
|
@@ -19,6 +19,8 @@ shape.** Your job is to interrogate until there is a shared system shape, and to
|
|
|
19
19
|
the documents as you go — not to ask the human to design the system for you.
|
|
20
20
|
|
|
21
21
|
<!-- uscha:orientation-block:begin -->
|
|
22
|
+
<!-- uscha kit: 2.2.0 -- generated region: edit tools/skill-blocks/, then run `python tools/gen-skill-blocks.py` (never this block by hand) -->
|
|
23
|
+
|
|
22
24
|
## First contact (show ONCE, then never again)
|
|
23
25
|
|
|
24
26
|
**Only when this project has no uscha artifacts yet** -- no `QA-LEDGER.json`, no `SPEC.md` or
|
|
@@ -94,9 +96,16 @@ Keep the CONTENT in the conversation's language, but keep the labels (`CLOSED`,
|
|
|
94
96
|
that makes discovery work: you propose (entities, endpoints, architecture, a default
|
|
95
97
|
decision), the human confirms or corrects. Never dump a list of 20 questions, and
|
|
96
98
|
never ask the human to supply structure you can propose yourself.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
99
|
+
**Close every question round item by item.** Before moving on, list what YOU decided in
|
|
100
|
+
that round and ask the human to confirm each one SEPARATELY — an "ok" over a twenty-item
|
|
101
|
+
summary is a rebound, not a decision, and it is exactly how a global default became a
|
|
102
|
+
tree-wide rename nobody had asked for. Write the answer onto the item as it arrives
|
|
103
|
+
(principle 6).
|
|
104
|
+
2. **Explore instead of asking — ask for DECISIONS, never for INFORMATION** (ADR-044). If a
|
|
105
|
+
reference doc/URL/PDF, the existing codebase, or an existing `CONTEXT.md`/`docs/adr/`
|
|
106
|
+
can answer a question, read it first. The current version of a tracked file, what a
|
|
107
|
+
config says, whether a test exists: all information — READ it. Only ask the human what
|
|
108
|
+
genuinely requires their judgment.
|
|
100
109
|
3. **Propose the shape.** From the idea + references, propose the core entities, the
|
|
101
110
|
operation/API surface, and 2–3 architecture options with trade-offs. Walk the design
|
|
102
111
|
tree branch by branch, resolving dependencies between decisions one at a time.
|
|
@@ -105,6 +114,14 @@ Keep the CONTENT in the conversation's language, but keep the labels (`CLOSED`,
|
|
|
105
114
|
failed.
|
|
106
115
|
5. **Write files lazily and inline.** Create a file only when you have something real to
|
|
107
116
|
write, and update it the moment a decision crystallizes — don't batch to the end.
|
|
117
|
+
6. **Mark what YOU decided: `origin: agent`.** Any acceptance criterion, ADR decision item
|
|
118
|
+
or HANDOFF rule that came from your proposal rather than from a human answer is written
|
|
119
|
+
with the marker on its own line — `(origin: agent)` while it is unconfirmed, and
|
|
120
|
+
`(origin: agent, confirmed: YYYY-MM-DD)` the moment the human confirms THAT item. Items
|
|
121
|
+
with no marker are human-origin by default; nothing already written is retro-tagged. An
|
|
122
|
+
unconfirmed item is NOT in scope: it is written down so it is visible, never so it is
|
|
123
|
+
agreed. `spec-check` names the unconfirmed ones with file:line (advisory — it changes no
|
|
124
|
+
exit code), and your close block lists them.
|
|
108
125
|
|
|
109
126
|
## Inputs
|
|
110
127
|
|
|
@@ -137,6 +154,17 @@ answer.
|
|
|
137
154
|
1. **Purpose / value / why now.** What job does this remove? Cost of not doing it?
|
|
138
155
|
2. **Domain model.** Propose the core entities and their relationships. ("From the domain
|
|
139
156
|
I deduce these core entities: … do they work for you, or is one missing?")
|
|
157
|
+
Then ask, MANDATORY, before the round closes (ADR-046): **"what input comes from the REAL
|
|
158
|
+
world, and where is the corpus?"** In greenfield every test payload is invented by the agent
|
|
159
|
+
that writes the code, so a green suite can be silent about the inputs the world actually
|
|
160
|
+
produces — one field build shipped a parser that passed every test its author wrote and was
|
|
161
|
+
96.96 % right on the real corpus. Name the real-input surfaces (files, payloads, messages,
|
|
162
|
+
documents), ask WHERE a sample with its expected outputs can be obtained, and record the path
|
|
163
|
+
as `repos[R].corpus` in `uscha.config.json` so `qa_ledger.py corpus-run` can score it.
|
|
164
|
+
**No corpus on day 1 is not a blocker — it is a HIGH risk in `RISKS.md` with an OWNER and a
|
|
165
|
+
date.** Do not invent one: a corpus the agent authored is the same invented input this
|
|
166
|
+
question exists to expose. The percentage gates nothing until the project declares a budget
|
|
167
|
+
(`corpus_threshold`), which is round 10's decision, not the kit's.
|
|
140
168
|
3. **Operation / API surface.** Propose the endpoints/operations and their
|
|
141
169
|
contracts (idempotency, status codes).
|
|
142
170
|
4. **Stack and lifecycle (MANDATORY — before any stack/architecture decision is
|
|
@@ -187,6 +215,18 @@ answer.
|
|
|
187
215
|
`spike/*` branch and its ONLY legitimate output is an **ADR with lessons**
|
|
188
216
|
(facts that feed the SPEC) — never mergeable code. The contract is executable:
|
|
189
217
|
`phase --require pr-ready` refuses any `spike/*` branch, INV-GOLDEN-01 style.
|
|
218
|
+
12. **Operability — who owns the RUNBOOK and the seed? (kit 2.2.0, ADR-048).** Ask it on
|
|
219
|
+
DAY 1, with your recommended answer, because the cheapest moment to decide it is before
|
|
220
|
+
anything is built and the most expensive is the week before go-live: who writes and owns
|
|
221
|
+
the **RUNBOOK** (start/boot, config, rollback, smoke), who owns the **seed/reset**
|
|
222
|
+
command that puts a fresh environment into a known state, and who owns the **release
|
|
223
|
+
workflow** that publishes the artifact. Record the answers as they crystallize:
|
|
224
|
+
`defaults.operability.seed_command` (or `repos[R].operability.seed_command`) in
|
|
225
|
+
`uscha.config.json`, and the RUNBOOK at `docs/RUNBOOK.md`. This is MEASURED, not
|
|
226
|
+
narrated — `qa_ledger.py operability --repo <REPO>` reads the four facts out of the tree,
|
|
227
|
+
and on risk profiles C/D/E a missing one is a BLOCKER, so a project that defers them
|
|
228
|
+
cannot reach `pr-ready`. Two field projects discovered all four in their last week; the
|
|
229
|
+
question costs one minute here.
|
|
190
230
|
|
|
191
231
|
## Files to write (lazily, inline)
|
|
192
232
|
|
|
@@ -210,7 +250,9 @@ answer.
|
|
|
210
250
|
`Rollback / Supersede Criteria`.
|
|
211
251
|
- **`ACCEPTANCE.md`** — Definition of Done as `- [ ]` checkboxes + success metrics. This
|
|
212
252
|
is the file the readiness KPI measures downstream. Give EVERY criterion a stable
|
|
213
|
-
traceable ID: `- [ ] AC-01 — when X then Y` (sequential, never reused)
|
|
253
|
+
traceable ID: `- [ ] AC-01 — when X then Y` (sequential, never reused); a criterion YOU
|
|
254
|
+
proposed also carries the `origin: agent` marker of principle 6 until the human confirms
|
|
255
|
+
it item by item. Downstream,
|
|
214
256
|
a criterion only closes MEASURED when a green testcase carries its tag in the name
|
|
215
257
|
(`test_ac1_x` / `testAC01X` / `"AC-01: ..."`) — write criteria so each one is
|
|
216
258
|
coverable by at least one named test.
|
|
@@ -231,6 +273,18 @@ as explicit assumptions), every failure mode has defined behavior, out-of-scope
|
|
|
231
273
|
explicit, and the DoD is checkable. State plainly that it converged, then write/finalize
|
|
232
274
|
the package and the handoff.
|
|
233
275
|
|
|
276
|
+
**The close block names what is still unconfirmed.** Before you emit it, run
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
python3 <path-to>/qa_ledger.py spec-check --spec SPEC.md --acceptance ACCEPTANCE.md
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
and copy the `~ origin: N agent-origin item(s) unconfirmed` list into `Blocks:` — one item
|
|
283
|
+
per line, with its file and line. Those are the decisions the human still owes; converging
|
|
284
|
+
with them silently in the package is the failure this marker exists to prevent. `Produced:`
|
|
285
|
+
still lists the files. If the list is empty, `Blocks:` says `nothing` as it always did:
|
|
286
|
+
silence and an explicit `nothing` are not the same fact.
|
|
287
|
+
|
|
234
288
|
## Handoff
|
|
235
289
|
|
|
236
290
|
End with the implementation handoff (works for a human, an agent, or CI):
|
|
@@ -18,6 +18,8 @@ Paints the REAL state of the project at a glance. It does not narrate or estimat
|
|
|
18
18
|
wires the JSON the engine emits into the template. Read-only.
|
|
19
19
|
|
|
20
20
|
<!-- uscha:orientation-block:begin -->
|
|
21
|
+
<!-- uscha kit: 2.2.0 -- generated region: edit tools/skill-blocks/, then run `python tools/gen-skill-blocks.py` (never this block by hand) -->
|
|
22
|
+
|
|
21
23
|
## Orientation markers (non-negotiable)
|
|
22
24
|
|
|
23
25
|
The operator must never have to ask "where am I?" or "what happens now?".
|
|
@@ -24,6 +24,8 @@ evidence-classed, content-addressed, and promoted to the contract only by a per-
|
|
|
24
24
|
human verdict (ADR-013).**
|
|
25
25
|
|
|
26
26
|
<!-- uscha:orientation-block:begin -->
|
|
27
|
+
<!-- uscha kit: 2.2.0 -- generated region: edit tools/skill-blocks/, then run `python tools/gen-skill-blocks.py` (never this block by hand) -->
|
|
28
|
+
|
|
27
29
|
## First contact (show ONCE, then never again)
|
|
28
30
|
|
|
29
31
|
**Only when this project has no uscha artifacts yet** -- no `QA-LEDGER.json`, no `SPEC.md` or
|
|
@@ -22,6 +22,8 @@ the grader — this skill just wraps the neutral prompt so Claude Code users get
|
|
|
22
22
|
in one command. Never add Claude-specific behavior to the contract.
|
|
23
23
|
|
|
24
24
|
<!-- uscha:orientation-block:begin -->
|
|
25
|
+
<!-- uscha kit: 2.2.0 -- generated region: edit tools/skill-blocks/, then run `python tools/gen-skill-blocks.py` (never this block by hand) -->
|
|
26
|
+
|
|
25
27
|
## First contact (show ONCE, then never again)
|
|
26
28
|
|
|
27
29
|
**Only when this project has no uscha artifacts yet** -- no `QA-LEDGER.json`, no `SPEC.md` or
|
|
@@ -19,7 +19,47 @@ skill (**pull** — one screen when the human asks), and the **mirador** (bird's
|
|
|
19
19
|
HTML). This skill exists because some surfaces never show a statusline; the answer
|
|
20
20
|
is the same data, printed in chat when requested.
|
|
21
21
|
|
|
22
|
+
## Before the readout: are the installed skills older than the kit? (2.2.0)
|
|
23
|
+
|
|
24
|
+
A field report found `~/.claude/skills/uscha-*` still on 1.54.0 while the kit in the repo was
|
|
25
|
+
1.97.0. An entire discovery ran on prose three months stale and NOTHING said so, because a
|
|
26
|
+
SKILL.md carried no version to compare. Since 2.2.0 every generated orientation block opens with
|
|
27
|
+
`<!-- uscha kit: X.Y.Z ... -->`, so the comparison is mechanical. Do it FIRST, before the
|
|
28
|
+
breadcrumb:
|
|
29
|
+
|
|
30
|
+
1. Run the engine's own check — it reads the marker out of every installed `SKILL.md` and
|
|
31
|
+
compares it against the kit's `VERSION`:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
python <kit>/.claude/skills/uscha-devloop/qa_ledger.py doctor --json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Read `skills_installed`: one row per install root the installer writes to (Claude
|
|
38
|
+
`~/.claude/skills/`, Codex `~/plugins/uscha/skills/`, pi `~/.agents/skills/`, and the other
|
|
39
|
+
Agent-Skills roots), each with `status`, `installed` and `kit`. `doctor` exits 0 whether or
|
|
40
|
+
not anything is outdated — this reports, it never gates.
|
|
41
|
+
2. If any row reads `outdated`, print exactly ONE line ABOVE the breadcrumb, then continue
|
|
42
|
+
normally:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
SKILLS OUTDATED: installed 1.54.0 < kit 2.2.0 -- run `python install-uscha.py install --target claude`
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Where the installed block predates 2.2.0 and carries no marker at all, `installed` is null:
|
|
49
|
+
say `installed <no kit: marker, pre-2.2.0>` rather than inventing a version.
|
|
50
|
+
3. `not installed` is NOT a finding — the kit installs one agent at a time, and six absent roots
|
|
51
|
+
are the normal shape of a healthy machine. Say nothing about them.
|
|
52
|
+
|
|
53
|
+
Advisory, always: the line never blocks the readout, never changes a number, and the block below
|
|
54
|
+
prints exactly as it would have. What it removes is the silence.
|
|
55
|
+
|
|
56
|
+
Honest limit: an installed skill that predates 2.2.0 does not carry these instructions, so on
|
|
57
|
+
that surface the warning cannot come from the skill itself. The `doctor` seam is the instrument
|
|
58
|
+
that still works there — it runs from any kit checkout and reads the installs from outside.
|
|
59
|
+
|
|
22
60
|
<!-- uscha:orientation-block:begin -->
|
|
61
|
+
<!-- uscha kit: 2.2.0 -- generated region: edit tools/skill-blocks/, then run `python tools/gen-skill-blocks.py` (never this block by hand) -->
|
|
62
|
+
|
|
23
63
|
## Orientation markers (non-negotiable)
|
|
24
64
|
|
|
25
65
|
The operator must never have to ask "where am I?" or "what happens now?".
|
|
@@ -22,6 +22,8 @@ switch between at any time:
|
|
|
22
22
|
coverage, known deferred issues.
|
|
23
23
|
|
|
24
24
|
<!-- uscha:orientation-block:begin -->
|
|
25
|
+
<!-- uscha kit: 2.2.0 -- generated region: edit tools/skill-blocks/, then run `python tools/gen-skill-blocks.py` (never this block by hand) -->
|
|
26
|
+
|
|
25
27
|
## First contact (show ONCE, then never again)
|
|
26
28
|
|
|
27
29
|
**Only when this project has no uscha artifacts yet** -- no `QA-LEDGER.json`, no `SPEC.md` or
|
|
@@ -33,6 +33,22 @@ each change lives in `SPEC.md` / `docs/adr/` / `ACCEPTANCE.md`, not here.
|
|
|
33
33
|
forces a SPEC change, version it and go back to Ready.
|
|
34
34
|
9. **Human gate.** Don't merge or release automatically. You stop at the PR; the merge and
|
|
35
35
|
the smoke test in a real environment are decided by a person.
|
|
36
|
+
10. **Ask for DECISIONS, never for INFORMATION — and mark what the agent decided.** What the
|
|
37
|
+
tree holds (the current version of a tracked file, what a config says, whether a test
|
|
38
|
+
exists) is READ, never asked. What the human has not decided is never entered silently:
|
|
39
|
+
every acceptance criterion, ADR decision item or `HANDOFF.md` rule the AGENT introduced
|
|
40
|
+
carries a trailing marker on its own line —
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
- [ ] AC-12 — when X then Y. (origin: agent)
|
|
44
|
+
- [ ] AC-12 — when X then Y. (origin: agent, confirmed: 2026-09-07)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Items with no marker are human-origin by default; nothing existing is retro-tagged. An
|
|
48
|
+
unconfirmed item is **not in scope**: it is confirmed ITEM BY ITEM, and a package-level
|
|
49
|
+
"ok" confirms none of them. `qa_ledger.py spec-check` names the unconfirmed ones with
|
|
50
|
+
file:line and `readiness` counts them on their own line — both advisory: they change no
|
|
51
|
+
exit code and cap no score.
|
|
36
52
|
|
|
37
53
|
## Truth hierarchy
|
|
38
54
|
|
|
@@ -154,6 +154,51 @@ enforcing the record is the engine's job. It is never resolved by "working aroun
|
|
|
154
154
|
asserts and **new dependencies** (the "0 deps without approval" rule, made visible —
|
|
155
155
|
kit 1.30.0) = review (or `--strict`). For high blast-radius a checker
|
|
156
156
|
uncorrelated with the maker (different family/profile) is also required — that is process, not code.
|
|
157
|
+
- The **CI pipeline** is a FACT gate without an invariant of its own: `log-gate --kind ci
|
|
158
|
+
--verdict <pass|fail|not-run>` records what the pipeline actually did, with `--ref <run URL or
|
|
159
|
+
id>` as the receipt. A `fail` is a **BLOCKER** — readiness cap ≤ 65 and convergence blocked —
|
|
160
|
+
exactly like `gate-check`; a `not-run` records absence and leaves the last state standing.
|
|
161
|
+
`--verdict advisory` is REFUSED on it, as on every FACT gate. It is admitted to the closed
|
|
162
|
+
`--kind` vocabulary (ADR-014, INV-ADVISORY-01) because a pipeline either went green on a
|
|
163
|
+
commit or it did not: an LLM judgment does not become a gate by being important.
|
|
164
|
+
- The **Field truth** invariant (greenfield) is measured by `qa_ledger.py corpus-run`: a JSONL
|
|
165
|
+
corpus of REAL inputs with their real expected outputs, run through the real command, scored
|
|
166
|
+
as hits/total. In greenfield every test payload was invented by the agent that wrote the code,
|
|
167
|
+
so a green suite proves nothing about the inputs the world produces — and `characterize` has
|
|
168
|
+
no answer there, because there is no old code to be the truth. **Advisory by default**: the
|
|
169
|
+
percentage is measured and gates nothing until the project declares a budget (`--threshold`,
|
|
170
|
+
else `repos[R].corpus_threshold`, else `defaults.corpus_threshold`). With one declared, a run
|
|
171
|
+
under it is a **BLOCKER** — readiness cap ≤ 65, convergence blocked — exactly like
|
|
172
|
+
`gate-check`, persisted as `gate:corpus`. A corpus that is missing, empty or malformed is
|
|
173
|
+
**exit 2** naming the line, never a scored 0 %. `log-gate --kind corpus` is the parity door
|
|
174
|
+
for a run measured elsewhere and it DOES accept `--verdict advisory` — the third and last kind
|
|
175
|
+
that may, because the check's own default mode is advisory; every other FACT kind still
|
|
176
|
+
refuses it. `--ac AC-nn` stamps criteria on the record: a criterion whose only evidence is a
|
|
177
|
+
corpus record closes MEASURED iff that record passed (ADR-046).
|
|
178
|
+
- The **Smoke** invariant is measured by `qa_ledger.py smoke-ingest`: the smoke run is a
|
|
179
|
+
REPORT the project's own tool writes — `{"checks": [{"name": ..., "ok": true|false,
|
|
180
|
+
"status": ..., "latency_ms": ..., "evidence": ...}]}` — and never a sentence an agent
|
|
181
|
+
wrote. **Evidence is executed, not narrated**: "the endpoint answered 200" believed on an
|
|
182
|
+
agent's word is the failure mode this exists to remove, and it has already cost a release
|
|
183
|
+
(every run returned an empty list because the database had no rows). A failed check is a
|
|
184
|
+
**BLOCKER** — readiness cap ≤ 65, convergence blocked — persisted as `gate:smoke`, cleared
|
|
185
|
+
by a later clean report. A report that is missing, malformed, has no `checks`, holds an
|
|
186
|
+
EMPTY list, or carries a check without a `name` or a boolean `ok` is **exit 2** naming it:
|
|
187
|
+
a run that verified nothing is not a clean gate. `smoke` joins the closed `--kind`
|
|
188
|
+
vocabulary (ADR-014, INV-ADVISORY-01) as a FACT, and `--verdict advisory` is REFUSED on it
|
|
189
|
+
— a smoke check is binary, so there is no budget it could be measured against. A check
|
|
190
|
+
named `AC-nn ...` closes that criterion MEASURED when it is `ok` and its report passed; a
|
|
191
|
+
failed one vetoes it (ADR-047).
|
|
192
|
+
- The **Operability** invariant is measured by `qa_ledger.py operability --repo R` (ADR-048): four
|
|
193
|
+
FACTS read out of the tree — a `.github/workflows` step running the repo's **configured** test
|
|
194
|
+
command, a workflow that publishes or attaches a release asset, a `RUNBOOK.md` naming
|
|
195
|
+
start/config/rollback/smoke, and a declared `seed_command` whose script is on disk. Its own exit
|
|
196
|
+
code is always 0; the verdict is persisted as `gate:operability` and the POSTURE is the risk
|
|
197
|
+
profile's — **advisory** on A/B (caps nothing, blocks nothing, never counted as `ok`) and a
|
|
198
|
+
**BLOCKER** on C/D/E, where `defaults.operability.gate` is `true`: readiness cap ≤ 65,
|
|
199
|
+
convergence blocked, and `phase --require pr-ready` refuses naming the missing check. A CI
|
|
200
|
+
system this engine does not read is reported `unknown`, never green and never red. Release,
|
|
201
|
+
reset and the RUNBOOK are part of done, not of the last week.
|
|
157
202
|
- The **Golden (INV-GOLDEN-01)** invariant is measured by `qa_ledger.py golden-diff`: any `.received`
|
|
158
203
|
that does not match its `.approved` (or is unapproved) = **DIVERGE**, cutting the chain before judgment-day.
|
|
159
204
|
The agent does not touch `.approved` (ideally a `PreToolUse` hook makes it impossible).
|
|
@@ -13,6 +13,21 @@ machine-readable `lifecycle:` frontmatter block (component / version / eol / sou
|
|
|
13
13
|
that `spec-check` compares against the SPEC's declared `go_live` (ADR-040). Advisory: it reports,
|
|
14
14
|
it never gates.
|
|
15
15
|
|
|
16
|
+
A **decision item the AGENT introduced** — one that came from the agent's proposal rather
|
|
17
|
+
than from a human answer — carries a trailing marker on its own line:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
- D-03 — the tree is renamed to English. (origin: agent)
|
|
21
|
+
- D-03 — the tree is renamed to English. (origin: agent, confirmed: 2026-09-07)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Items with no marker are human-origin by default (nothing already written is retro-tagged).
|
|
25
|
+
An unconfirmed item is NOT in scope: it is confirmed one item at a time, never by a
|
|
26
|
+
package-level "ok". `spec-check` lists the unconfirmed ones with file:line and `readiness`
|
|
27
|
+
counts them on a line of their own; both are advisory — no exit code, no score changes. A
|
|
28
|
+
marker inside a fenced block or an inline code span (like the two above) is documentation and
|
|
29
|
+
is skipped.
|
|
30
|
+
|
|
16
31
|
`Status: Experiment` is for a bounded, reversible hypothesis that needs real feedback.
|
|
17
32
|
It must include: Hypothesis, Feedback Signal, Review By or Review Trigger, Promote
|
|
18
33
|
Criteria, and Rollback / Supersede Criteria. Missing/expired metadata is advisory in
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"checks": [
|
|
3
|
+
{
|
|
4
|
+
"name": "AC-01 the API serves /health under the real database",
|
|
5
|
+
"ok": true,
|
|
6
|
+
"status": 200,
|
|
7
|
+
"latency_ms": 6,
|
|
8
|
+
"evidence": "curl -sS http://localhost:8080/health -> {\"status\":\"UP\",\"db\":\"UP\"}"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"name": "the catalogue endpoint returns the seeded rows",
|
|
12
|
+
"ok": true,
|
|
13
|
+
"status": 200,
|
|
14
|
+
"latency_ms": 41,
|
|
15
|
+
"evidence": "GET /catalogue -> 128 items (the seed loads 128; an EMPTY list is the failure this check exists to catch)"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "an unauthenticated write is rejected",
|
|
19
|
+
"ok": true,
|
|
20
|
+
"status": 401,
|
|
21
|
+
"evidence": "POST /catalogue with no token -> 401"
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_comment": "COMPREHENSIVE REFERENCE, not a project config. Every knob the engine and the skills understand, at the kit's own value, so a human can read what can be declared. `uscha init` does NOT copy this file: it GENERATES a minimal project config, because a copied default is an explicit declaration and an explicit declaration outranks the preset named by defaults.risk_profile (ADR-001, as amended). Copy a block from here into your project only when you mean to override the engine default or the preset. NOTE: no version string may be written into this comment -- the release script requires exactly one occurrence of the version in this file (I3), and a second one refuses the next release.",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"project": null,
|
|
5
5
|
"defaults": {
|
|
6
6
|
"coverage_threshold": 60,
|
|
@@ -84,6 +84,11 @@
|
|
|
84
84
|
"allow_paths": [],
|
|
85
85
|
"gate": false
|
|
86
86
|
},
|
|
87
|
+
"operability": {
|
|
88
|
+
"runbook": "docs/RUNBOOK.md",
|
|
89
|
+
"seed_command": "make seed",
|
|
90
|
+
"gate": false
|
|
91
|
+
},
|
|
87
92
|
"execution_policy": {
|
|
88
93
|
"default": {
|
|
89
94
|
"tier": "standard",
|