@andresmassello/uscha 1.51.1 → 1.53.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 +24 -5
- package/package.json +3 -2
- package/uscha-kit/.claude/skills/uscha-adr-refine/SKILL.md +203 -161
- package/uscha-kit/.claude/skills/uscha-characterize/SKILL.md +40 -0
- package/uscha-kit/.claude/skills/uscha-devloop/SKILL.md +40 -0
- package/uscha-kit/.claude/skills/uscha-discovery/SKILL.md +203 -161
- package/uscha-kit/.claude/skills/uscha-mirador/SKILL.md +192 -161
- package/uscha-kit/.claude/skills/uscha-mirador/mirador-render.py +16 -8
- package/uscha-kit/.claude/skills/uscha-reverse-discovery/SKILL.md +42 -0
- package/uscha-kit/.claude/skills/uscha-rubric/SKILL.md +119 -79
- package/uscha-kit/.claude/skills/uscha-status/SKILL.md +24 -0
- package/uscha-kit/.claude/skills/uscha-sysdoc/SKILL.md +128 -88
- package/uscha-kit/.claude-plugin/plugin.json +2 -2
- package/uscha-kit/.codex-plugin/plugin.json +2 -2
- package/uscha-kit/INSTALL.md +3 -0
- package/uscha-kit/README.md +1 -1
- package/uscha-kit/VERSION +1 -1
- package/uscha-kit/install-uscha.py +77 -43
- package/uscha-kit/skills/uscha-adr-refine/SKILL.md +203 -161
- package/uscha-kit/skills/uscha-characterize/SKILL.md +40 -0
- package/uscha-kit/skills/uscha-devloop/SKILL.md +40 -0
- package/uscha-kit/skills/uscha-discovery/SKILL.md +203 -161
- package/uscha-kit/skills/uscha-mirador/SKILL.md +192 -161
- package/uscha-kit/skills/uscha-mirador/mirador-render.py +16 -8
- package/uscha-kit/skills/uscha-reverse-discovery/SKILL.md +42 -0
- package/uscha-kit/skills/uscha-rubric/SKILL.md +119 -79
- package/uscha-kit/skills/uscha-status/SKILL.md +24 -0
- package/uscha-kit/skills/uscha-sysdoc/SKILL.md +128 -88
- package/uscha-kit/uscha.config.json +1 -1
- package/uscha-kit/CHANGELOG-1.10.0.md +0 -84
- package/uscha-kit/CHANGELOG-1.11.0.md +0 -67
- package/uscha-kit/CHANGELOG-1.12.0.md +0 -46
- package/uscha-kit/CHANGELOG-1.13.0.md +0 -33
- package/uscha-kit/CHANGELOG-1.14.0.md +0 -42
- package/uscha-kit/CHANGELOG-1.15.0.md +0 -58
- package/uscha-kit/CHANGELOG-1.16.0.md +0 -55
- package/uscha-kit/CHANGELOG-1.17.0.md +0 -44
- package/uscha-kit/CHANGELOG-1.18.0.md +0 -42
- package/uscha-kit/CHANGELOG-1.19.0.md +0 -41
- package/uscha-kit/CHANGELOG-1.2.2.md +0 -16
- package/uscha-kit/CHANGELOG-1.2.3.md +0 -20
- package/uscha-kit/CHANGELOG-1.2.4.md +0 -10
- package/uscha-kit/CHANGELOG-1.2.5.md +0 -23
- package/uscha-kit/CHANGELOG-1.2.6.md +0 -11
- package/uscha-kit/CHANGELOG-1.2.7.md +0 -15
- package/uscha-kit/CHANGELOG-1.2.8.md +0 -24
- package/uscha-kit/CHANGELOG-1.2.9.md +0 -4
- package/uscha-kit/CHANGELOG-1.20.0.md +0 -29
- package/uscha-kit/CHANGELOG-1.21.0.md +0 -33
- package/uscha-kit/CHANGELOG-1.22.0.md +0 -60
- package/uscha-kit/CHANGELOG-1.23.0.md +0 -75
- package/uscha-kit/CHANGELOG-1.24.0.md +0 -50
- package/uscha-kit/CHANGELOG-1.25.0.md +0 -55
- package/uscha-kit/CHANGELOG-1.26.0.md +0 -70
- package/uscha-kit/CHANGELOG-1.27.0.md +0 -45
- package/uscha-kit/CHANGELOG-1.28.0.md +0 -35
- package/uscha-kit/CHANGELOG-1.29.0.md +0 -20
- package/uscha-kit/CHANGELOG-1.3.0.md +0 -74
- package/uscha-kit/CHANGELOG-1.30.0.md +0 -46
- package/uscha-kit/CHANGELOG-1.31.0.md +0 -59
- package/uscha-kit/CHANGELOG-1.32.0.md +0 -50
- package/uscha-kit/CHANGELOG-1.33.0.md +0 -46
- package/uscha-kit/CHANGELOG-1.34.0.md +0 -55
- package/uscha-kit/CHANGELOG-1.35.0.md +0 -30
- package/uscha-kit/CHANGELOG-1.36.0.md +0 -33
- package/uscha-kit/CHANGELOG-1.37.0.md +0 -41
- package/uscha-kit/CHANGELOG-1.38.0.md +0 -11
- package/uscha-kit/CHANGELOG-1.39.0.md +0 -14
- package/uscha-kit/CHANGELOG-1.4.0.md +0 -68
- package/uscha-kit/CHANGELOG-1.40.0.md +0 -16
- package/uscha-kit/CHANGELOG-1.40.1.md +0 -11
- package/uscha-kit/CHANGELOG-1.40.2.md +0 -13
- package/uscha-kit/CHANGELOG-1.41.0.md +0 -18
- package/uscha-kit/CHANGELOG-1.41.1.md +0 -53
- package/uscha-kit/CHANGELOG-1.41.2.md +0 -34
- package/uscha-kit/CHANGELOG-1.41.3.md +0 -30
- package/uscha-kit/CHANGELOG-1.42.0.md +0 -41
- package/uscha-kit/CHANGELOG-1.43.0.md +0 -37
- package/uscha-kit/CHANGELOG-1.44.0.md +0 -90
- package/uscha-kit/CHANGELOG-1.44.1.md +0 -26
- package/uscha-kit/CHANGELOG-1.45.0.md +0 -58
- package/uscha-kit/CHANGELOG-1.46.0.md +0 -50
- package/uscha-kit/CHANGELOG-1.46.1.md +0 -35
- package/uscha-kit/CHANGELOG-1.47.0.md +0 -45
- package/uscha-kit/CHANGELOG-1.48.0.md +0 -35
- package/uscha-kit/CHANGELOG-1.48.1.md +0 -55
- package/uscha-kit/CHANGELOG-1.48.2.md +0 -47
- package/uscha-kit/CHANGELOG-1.49.0.md +0 -45
- package/uscha-kit/CHANGELOG-1.5.0.md +0 -64
- package/uscha-kit/CHANGELOG-1.50.0.md +0 -52
- package/uscha-kit/CHANGELOG-1.50.1.md +0 -52
- package/uscha-kit/CHANGELOG-1.50.2.md +0 -62
- package/uscha-kit/CHANGELOG-1.51.0.md +0 -44
- package/uscha-kit/CHANGELOG-1.51.1.md +0 -33
- package/uscha-kit/CHANGELOG-1.6.0.md +0 -57
- package/uscha-kit/CHANGELOG-1.7.0.md +0 -74
- package/uscha-kit/CHANGELOG-1.8.0.md +0 -46
- package/uscha-kit/CHANGELOG-1.9.0.md +0 -112
|
@@ -1,161 +1,192 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: uscha-mirador
|
|
3
|
-
description: >
|
|
4
|
-
Bird's-eye status view ("mirador") of a spec-loop project: one glance at
|
|
5
|
-
readiness, sub-scores, the phase path, invariants, QA loops and a readiness
|
|
6
|
-
time-lapse. Runs `qa_ledger.py dashboard --json` (read-only, deterministic,
|
|
7
|
-
zero LLM narration), injects that JSON into mirador.template.html, writes
|
|
8
|
-
mirador.html at the project root and opens it. The skill WIRES, it does not
|
|
9
|
-
calculate — every number comes from the ledger (truth-pass: a field with no
|
|
10
|
-
source shows null and the template degrades, never invented). Invoke for
|
|
11
|
-
"mirador", "vista de estado", "bird's-eye", "dashboard del proyecto".
|
|
12
|
-
allowed-tools: Read, Write, Glob, Grep, Bash
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
# uscha-mirador — bird's-eye status view
|
|
16
|
-
|
|
17
|
-
Paints the REAL state of the project at a glance. It does not narrate or estimate: it
|
|
18
|
-
wires the JSON the engine emits into the template. Read-only.
|
|
19
|
-
|
|
20
|
-
##
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
- **
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
1
|
+
---
|
|
2
|
+
name: uscha-mirador
|
|
3
|
+
description: >
|
|
4
|
+
Bird's-eye status view ("mirador") of a spec-loop project: one glance at
|
|
5
|
+
readiness, sub-scores, the phase path, invariants, QA loops and a readiness
|
|
6
|
+
time-lapse. Runs `qa_ledger.py dashboard --json` (read-only, deterministic,
|
|
7
|
+
zero LLM narration), injects that JSON into mirador.template.html, writes
|
|
8
|
+
mirador.html at the project root and opens it. The skill WIRES, it does not
|
|
9
|
+
calculate — every number comes from the ledger (truth-pass: a field with no
|
|
10
|
+
source shows null and the template degrades, never invented). Invoke for
|
|
11
|
+
"mirador", "vista de estado", "bird's-eye", "dashboard del proyecto".
|
|
12
|
+
allowed-tools: Read, Write, Glob, Grep, Bash
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# uscha-mirador — bird's-eye status view
|
|
16
|
+
|
|
17
|
+
Paints the REAL state of the project at a glance. It does not narrate or estimate: it
|
|
18
|
+
wires the JSON the engine emits into the template. Read-only.
|
|
19
|
+
|
|
20
|
+
## Orientation markers (non-negotiable)
|
|
21
|
+
|
|
22
|
+
The operator must never have to ask "where am I?" or "what happens now?".
|
|
23
|
+
|
|
24
|
+
This skill is a **one-shot read-only readout**: its block IS the answer. It therefore does NOT
|
|
25
|
+
take the conversational close block — that would be exactly the padding this skill forbids.
|
|
26
|
+
It carries the two minimal markers instead.
|
|
27
|
+
|
|
28
|
+
**Open with a breadcrumb:**
|
|
29
|
+
|
|
30
|
+
`[uscha · mirador · step <n> → <target>]`
|
|
31
|
+
|
|
32
|
+
**End with the two routing lines, and nothing else:**
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
Next: <the next action, derived from what this readout just showed>
|
|
36
|
+
Run: <the exact command or skill to invoke>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`Next` is **derived** from the state you just read — never copied from a fixed route,
|
|
40
|
+
including any `Flow:` line in this file. If nothing is actionable, say that plainly rather
|
|
41
|
+
than inventing a step. Keep the CONTENT in the conversation's language and the labels
|
|
42
|
+
(`Next`, `Run`) verbatim — the smoke suite checks for them.
|
|
43
|
+
|
|
44
|
+
## Contract
|
|
45
|
+
|
|
46
|
+
- **Source of truth:** `qa_ledger.py dashboard --json` — aggregates ONLY state the
|
|
47
|
+
ledger already has (readiness, subscores, phases, acceptance, adrs, inv, layers, loops,
|
|
48
|
+
snapshots, evidence). A field with no source comes out `null`/`[]`; the template
|
|
49
|
+
degrades. **A datum is never invented.**
|
|
50
|
+
- **Template:** `mirador.template.html` (in this folder). The data block lives between
|
|
51
|
+
`/*MIRADOR_DATA_START*/` and `/*MIRADOR_DATA_END*/`; the sample `const DATA` it ships
|
|
52
|
+
with is the **offline fallback**. The skill replaces ONLY that region; it does not
|
|
53
|
+
touch the rest of the HTML.
|
|
54
|
+
- **Project name (top):** the mirador shows the project name prominently at the top, from
|
|
55
|
+
`config.project` in `uscha.config.json` (set it in `uscha-discovery`); if unset, it falls
|
|
56
|
+
back to the joined repo names (truth-pass — no invented name).
|
|
57
|
+
- **Execution policy (bird's-eye):** `dashboard --json` also exposes
|
|
58
|
+
`execution_policy` plus `phase.execution` for each trail node. This is routing metadata
|
|
59
|
+
from `config.defaults.execution_policy` (`method`, `tier`, `model`, `effort`,
|
|
60
|
+
`uncorrelated`), not a score. The template renders it as a separate panel so the human
|
|
61
|
+
sees which methodology/model/effort is selected per phase without mixing it into
|
|
62
|
+
readiness.
|
|
63
|
+
- **Discovery intake:** `dashboard --json` carries `discovery_intake` from readiness:
|
|
64
|
+
open `production_findings`, `spec_doubts`, and `spec_change_requests`. The current template keeps the top-level
|
|
65
|
+
verdict honest through readiness/caps; future panels may render the intake directly.
|
|
66
|
+
- **ADR experiments:** ADR rows may carry `adr_status: "experiment"`, `review_by`,
|
|
67
|
+
`review_trigger`, `experiment_valid`, `experiment_missing`, and `expired`; top-level
|
|
68
|
+
`adr_experiments` summarizes open/malformed/expired experiments. This is advisory
|
|
69
|
+
visibility for measured hypotheses, not readiness scoring.
|
|
70
|
+
- **Session telemetry (optional, vendor-reported):** if `.uscha/telemetry.jsonl` exists,
|
|
71
|
+
the skill aggregates it and MERGES a `telemetry` object into `DATA`. This is the ONE
|
|
72
|
+
panel that is **narrated by the vendor (Claude Code), not measured by the engine** —
|
|
73
|
+
tokens, wall time, model, effort — so it renders in a **segregated strip** labeled as
|
|
74
|
+
such, never mixed with the measured panels. `dashboard --json` NEVER emits it; it enters
|
|
75
|
+
only through this adapter. Absent file → no strip (degrades). This is the doctrinal
|
|
76
|
+
line: telemetry is neither a fact-gate nor a guess-advisor, so it must not dilute
|
|
77
|
+
*measured beats narrated*.
|
|
78
|
+
|
|
79
|
+
## Flow
|
|
80
|
+
|
|
81
|
+
1. **Resolve the engine.** Use the first one that exists:
|
|
82
|
+
- `./.claude/skills/uscha-devloop/qa_ledger.py` (per-project install)
|
|
83
|
+
- `~/plugins/uscha/skills/uscha-devloop/qa_ledger.py` (Codex plugin install)
|
|
84
|
+
- `~/.codex/skills/uscha-devloop/qa_ledger.py` (Codex raw-skills install)
|
|
85
|
+
- `~/.claude/skills/uscha-devloop/qa_ledger.py` (Claude global install)
|
|
86
|
+
|
|
87
|
+
2. **Resolve the ledger.** `QA-LEDGER.json` in the cwd (or the `--ledger` the user
|
|
88
|
+
points to). If it does not exist, warn: you have to run `uscha-devloop` (or
|
|
89
|
+
`qa_ledger.py init`) first — with no ledger there is no state to look at.
|
|
90
|
+
|
|
91
|
+
(`<skill-dir>` below = this folder: `.claude/skills/uscha-mirador/` per-project, or `~/plugins/uscha/skills/uscha-mirador/` / `~/.codex/skills/uscha-mirador/` / `~/.claude/skills/uscha-mirador/` global.)
|
|
92
|
+
|
|
93
|
+
3. **(Optional) record this session's telemetry.** For the vendor-telemetry strip, append
|
|
94
|
+
the current Claude Code session to the sidecar:
|
|
95
|
+
```bash
|
|
96
|
+
python3 <skill-dir>/telemetry-extract.py <path-to-CC-transcript.jsonl>
|
|
97
|
+
```
|
|
98
|
+
It **upserts by session** (safe to re-run — a watch loop won't inflate the totals). Skip
|
|
99
|
+
this for a pure measured view.
|
|
100
|
+
|
|
101
|
+
4. **Render `mirador.html`** with the standalone renderer — it runs `dashboard --json`,
|
|
102
|
+
merges the sidecar telemetry if present, injects `const DATA`, writes the file, prints its
|
|
103
|
+
absolute path (`OPEN IT: ...`), and opens it in the default browser **the first time it
|
|
104
|
+
creates the file** (see step 5 — a re-render updates the open tab instead). From the project root,
|
|
105
|
+
with no long paths — `--engine` and `--template` default to the renderer's sibling skill
|
|
106
|
+
files (kit 1.41.2):
|
|
107
|
+
```bash
|
|
108
|
+
python3 <skill-dir>/mirador-render.py --ledger QA-LEDGER.json
|
|
109
|
+
```
|
|
110
|
+
The engine stays model-agnostic — telemetry is merged by the renderer (the adapter), NOT
|
|
111
|
+
by `dashboard`. If the ledger is missing, warn and stop (run `uscha-devloop` first). The
|
|
112
|
+
time-lapse feeds from `qa_ledger.py readiness --record` — since kit 1.47.0 the dev-loop
|
|
113
|
+
records at every pass close, so history accumulates without extra ceremony.
|
|
114
|
+
|
|
115
|
+
5. **Where to look:** the renderer opens `mirador.html` **once — only the first time it is
|
|
116
|
+
created** — and always prints its absolute path on the `OPEN IT:` line; surface that path to
|
|
117
|
+
the operator. Re-rendering (this skill invoked again on a later pass, or the watch loop)
|
|
118
|
+
rewrites the SAME file, and the page's built-in auto-refresh reloads the already-open tab in
|
|
119
|
+
place, so a re-render never spawns a new browser tab. On a fresh session the file is already
|
|
120
|
+
on disk, so nothing pops — open the printed path once, or pass `--open` (`uscha mirador
|
|
121
|
+
--open`) to force a reopen when you closed the tab. `--no-open` suppresses opening
|
|
122
|
+
everywhere and wins over `--open` (headless/CI, or the watch loop, which passes it);
|
|
123
|
+
`--refresh 0` writes a frozen snapshot with no auto-reload.
|
|
124
|
+
|
|
125
|
+
## For a human at a terminal: `uscha mirador`
|
|
126
|
+
|
|
127
|
+
The one-liner above is what THIS skill runs. A human who just wants the dashboard — without a
|
|
128
|
+
Claude Code session — has a zero-friction verb instead (kit 1.43.0): from the project root,
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
uscha mirador # render + open, defaults to the QA-LEDGER.json convention
|
|
132
|
+
uscha mirador --watch # live second-screen view (auto-refresh, one self-reloading tab)
|
|
133
|
+
npx @andresmassello/uscha mirador # same, no install
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
No python, no paths: the verb resolves the engine, template and ledger on its own.
|
|
137
|
+
|
|
138
|
+
## Live second-screen view
|
|
139
|
+
|
|
140
|
+
For a mirador that updates while you keep coding in the terminal, run the watch loop in a
|
|
141
|
+
spare terminal and open `mirador.html` on a second monitor (or just use `uscha mirador --watch`):
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# Windows: powershell -NoProfile -File <skill-dir>\mirador-watch.ps1 -Interval 30
|
|
145
|
+
# Unix: bash <skill-dir>/mirador-watch.sh 30
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
It re-renders `mirador.html` every N seconds (default 30) from the current ledger, rendered
|
|
149
|
+
with a matching `<meta http-equiv="refresh">` so the open page reloads on its own — **no
|
|
150
|
+
server**. It is only as live as the **ledger**: the picture changes at the dev-loop's
|
|
151
|
+
measured checkpoints (snapshots, gates, `readiness --record`), not per keystroke. Honest by
|
|
152
|
+
design — it shows measured state, which changes at measured moments.
|
|
153
|
+
|
|
154
|
+
## Session telemetry — sidecar contract
|
|
155
|
+
|
|
156
|
+
`.uscha/telemetry.jsonl` is an **append-only** file, one JSON object per session/run:
|
|
157
|
+
|
|
158
|
+
```jsonl
|
|
159
|
+
{"at": "2026-07-05T23:40:00Z", "model": "claude-opus-4-8", "tokens_in": 240000, "tokens_out": 41000, "ms": 4200000, "by_model": [{"model": "claude-opus-4-8", "tokens_in": 240000, "tokens_out": 41000}], "note": "mirador build"}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`effort` and `note` are **optional** and are NOT produced by `telemetry-extract.py` (a Claude
|
|
163
|
+
Code transcript carries no reliable effort label) — add them by hand if you want them; the
|
|
164
|
+
strip shows `—` when `effort` is absent. `by_model` is per-**tokens** (session-level `ms` only).
|
|
165
|
+
|
|
166
|
+
- **Who writes it:** the AGENT / operator, NEVER the engine (the engine is model-agnostic
|
|
167
|
+
and cannot see tokens). Two honest sources:
|
|
168
|
+
- **`telemetry-extract.py <transcript.jsonl>`** (shipped in this skill folder): parses a
|
|
169
|
+
Claude Code session transcript — each assistant turn carries a `usage` block
|
|
170
|
+
(`input_tokens` / `cache_*_input_tokens` / `output_tokens`) and a `model` — sums per
|
|
171
|
+
model, computes wall time from the timestamps, and appends one line (with a `by_model`
|
|
172
|
+
breakdown). Real, vendor-native data. Best-effort: unknown/older schemas degrade, never
|
|
173
|
+
crash; no usage found → nothing appended.
|
|
174
|
+
- **Manual append**: paste the session's numbers from Claude Code's own cost view.
|
|
175
|
+
- **Persistence:** the file itself IS the history (portable, diffable, greppable). Add it to
|
|
176
|
+
the project's `.gitignore` — it is per-machine telemetry, not repo state. (A pure-client
|
|
177
|
+
alternative is `localStorage` inside `mirador.html`, but the sidecar survives regeneration,
|
|
178
|
+
so it is the default.)
|
|
179
|
+
- **Boundary (non-negotiable):** this is the ONLY place vendor-narrated numbers enter the
|
|
180
|
+
mirador. They are shown, never gated, never fed into readiness — telemetry answers "what
|
|
181
|
+
did it cost", the measured panels answer "is it correct". Keep them apart.
|
|
182
|
+
|
|
183
|
+
## Rules
|
|
184
|
+
|
|
185
|
+
- **Zero computation in the skill.** The numbers come from the ledger. If a panel looks
|
|
186
|
+
empty, it's because the engine doesn't have that source yet (truth-pass), not because
|
|
187
|
+
painting it was missed.
|
|
188
|
+
- **Read-only.** The skill does not run gates or modify the ledger. `dashboard` is
|
|
189
|
+
read-only; the only one that writes (opt-in) is `readiness --record`, and that is the
|
|
190
|
+
loop's decision, not this skill's.
|
|
191
|
+
- **`mirador.html` is a generated artifact** — suggest adding it to the project's
|
|
192
|
+
`.gitignore`; it regenerates whenever you want.
|
|
@@ -94,10 +94,13 @@ def main():
|
|
|
94
94
|
help="path to mirador.template.html (default: the sibling template)")
|
|
95
95
|
ap.add_argument("--out", default="mirador.html")
|
|
96
96
|
ap.add_argument("--sidecar", default=os.path.join(".uscha", "telemetry.jsonl"))
|
|
97
|
-
ap.add_argument("--refresh", type=int, default=
|
|
98
|
-
help="
|
|
97
|
+
ap.add_argument("--refresh", type=int, default=10,
|
|
98
|
+
help="auto-reload the open tab every N seconds so a SINGLE tab stays live "
|
|
99
|
+
"(0 = frozen snapshot; default 10)")
|
|
99
100
|
ap.add_argument("--no-open", action="store_true",
|
|
100
101
|
help="write the file but do not open it in a browser")
|
|
102
|
+
ap.add_argument("--open", dest="force_open", action="store_true",
|
|
103
|
+
help="open the browser even if the file already existed (the tab was closed)")
|
|
101
104
|
args = ap.parse_args()
|
|
102
105
|
|
|
103
106
|
try:
|
|
@@ -127,10 +130,12 @@ def main():
|
|
|
127
130
|
out = re.sub(r"/\*MIRADOR_DATA_START\*/.*?/\*MIRADOR_DATA_END\*/",
|
|
128
131
|
lambda m: payload, tpl, count=1, flags=re.S)
|
|
129
132
|
if args.refresh and args.refresh > 0:
|
|
130
|
-
#
|
|
133
|
+
# a meta-refresh so the ONE open tab reloads itself in place (on by default) --
|
|
134
|
+
# pass --refresh 0 for a frozen snapshot
|
|
131
135
|
out = out.replace("</head>",
|
|
132
136
|
f'<meta http-equiv="refresh" content="{args.refresh}">\n</head>', 1)
|
|
133
|
-
|
|
137
|
+
# capture BEFORE writing: auto-open fires only when the mirador is FIRST materialized
|
|
138
|
+
pre_existed = os.path.exists(args.out)
|
|
134
139
|
with open(args.out, "w", encoding="utf-8") as f:
|
|
135
140
|
f.write(out)
|
|
136
141
|
score = (data.get("readiness") or {}).get("score")
|
|
@@ -139,10 +144,13 @@ def main():
|
|
|
139
144
|
print(f"[mirador-render] readiness {score} | telemetry {'on' if tel else 'off'} | "
|
|
140
145
|
f"refresh {args.refresh or 'off'}")
|
|
141
146
|
print(f"[mirador-render] OPEN IT: {out_abs}")
|
|
142
|
-
# Auto-open
|
|
143
|
-
#
|
|
144
|
-
#
|
|
145
|
-
|
|
147
|
+
# Auto-open ONLY the first time the file is created. Repeated renders (the agent per
|
|
148
|
+
# pass, or a watch loop) rewrite the SAME file, and the meta-refresh reloads the already-
|
|
149
|
+
# open tab in place -- so a re-render never spawns a new browser tab (kit 1.51.2; 1.41.3
|
|
150
|
+
# gated this on --refresh, which spammed a tab per one-shot re-render). `pre_existed`
|
|
151
|
+
# tracks the FILE, not a live tab, so --open forces a reopen when the tab was closed;
|
|
152
|
+
# --no-open suppresses everywhere and wins over it. The OPEN IT path is always printed.
|
|
153
|
+
if not args.no_open and (args.force_open or not pre_existed):
|
|
146
154
|
_open_best_effort(out_abs)
|
|
147
155
|
return 0
|
|
148
156
|
|
|
@@ -18,6 +18,46 @@ disable-model-invocation: false
|
|
|
18
18
|
opposite. The system already runs; its observable behavior is the ground truth. **You do
|
|
19
19
|
not invent anything — you characterize what is already there, as facts.**
|
|
20
20
|
|
|
21
|
+
## Orientation markers (non-negotiable)
|
|
22
|
+
|
|
23
|
+
The operator must never have to ask "where am I?" or "what happens now?". Two markers, always.
|
|
24
|
+
They are navigation, not ceremony: one line per turn, one block at the end.
|
|
25
|
+
|
|
26
|
+
**Open every turn with a breadcrumb**, then the content:
|
|
27
|
+
|
|
28
|
+
`[uscha · reverse-discovery · <step> → <target>]`
|
|
29
|
+
|
|
30
|
+
- `<step>` — `Q<n>` for a question, `pass <n>` for a loop iteration, `step <n>` otherwise.
|
|
31
|
+
Count what has actually happened. **Never write a denominator** (`Q4/12`): this phase
|
|
32
|
+
converges, its length is not known in advance, and an invented total is exactly the kind of
|
|
33
|
+
narrated number the method forbids. **When the ledger already measures the count** (the QA
|
|
34
|
+
loop's `loop_count`), use the measured number — never keep a parallel tally of your own.
|
|
35
|
+
- `<target>` — the artifact this turn feeds (`SPEC`, `ADR-003`, `ACCEPTANCE`, `LEDGER`,
|
|
36
|
+
`RECEIVED`, ...). Drop `→ <target>` only when the turn genuinely feeds none.
|
|
37
|
+
|
|
38
|
+
**Close with the close block ONCE, when the skill finishes** — not on every turn. Ending
|
|
39
|
+
without it is a defect, even when the phase converged cleanly:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
[uscha · reverse-discovery · CLOSED]
|
|
43
|
+
Produced: <files actually written, or "nothing">
|
|
44
|
+
Blocks: <what stands between here and the next phase, or "nothing">
|
|
45
|
+
Next: <the next action, and why it is that one>
|
|
46
|
+
Run: <the exact command or skill to invoke>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
This is **not** the implementation handoff some skills also emit: that one is a prompt for
|
|
50
|
+
whoever implements next, this one is navigation for the human operator, and both can appear.
|
|
51
|
+
|
|
52
|
+
`Blocks` and `Next` are **derived from the state you just produced** — never copied from a
|
|
53
|
+
fixed route, **including any `Flow:` line in this file**. Those lines are the nominal path;
|
|
54
|
+
open ADR experiments, an unclosed spike, an unapproved golden or a red gate all change what
|
|
55
|
+
genuinely comes next, and the derived answer wins. If the next phase cannot start yet, name it
|
|
56
|
+
and say exactly what unblocks it.
|
|
57
|
+
|
|
58
|
+
Keep the CONTENT in the conversation's language, but keep the labels (`CLOSED`, `Produced`,
|
|
59
|
+
`Blocks`, `Next`, `Run`) verbatim — they are the method's vocabulary and the smoke checks them.
|
|
60
|
+
|
|
21
61
|
## The one non-negotiable: produce ONLY facts
|
|
22
62
|
|
|
23
63
|
A system map (from static analysis) and a golden suite (byte-captured) are FACTS —
|
|
@@ -94,6 +134,8 @@ Flow (migration): `uscha-reverse-discovery` (facts) → human writes SPEC + `/us
|
|
|
94
134
|
module decisions) → `/uscha-devloop` (restructure; `golden-diff` + `ApplicationModules.verify()`
|
|
95
135
|
stay green the whole way) → readiness + human gate.
|
|
96
136
|
|
|
137
|
+
That route is the **nominal** one, not the answer: the `Next:`/`Run:` you emit in the close block are DERIVED from the state you actually produced, and override it whenever an open experiment, an unclosed spike, an unapproved golden or a red gate stands in between.
|
|
138
|
+
|
|
97
139
|
## Relationship to the other skills
|
|
98
140
|
|
|
99
141
|
- **discovery** (greenfield): you PROPOSE the shape from an idea. **reverse-discovery**
|