@andresmassello/uscha 1.40.2 → 1.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/bin/uscha.js +19 -7
- package/package.json +1 -1
- package/uscha-kit/.claude/skills/uscha-adr-refine/SKILL.md +2 -2
- package/uscha-kit/.claude/skills/uscha-devloop/SKILL.md +3 -1
- package/uscha-kit/.claude/skills/uscha-devloop/qa_ledger.py +729 -155
- package/uscha-kit/.claude/skills/uscha-mirador/SKILL.md +22 -7
- package/uscha-kit/.claude/skills/uscha-mirador/mirador-render.py +44 -5
- package/uscha-kit/.claude/skills/uscha-mirador/mirador-watch.ps1 +1 -1
- package/uscha-kit/.claude/skills/uscha-mirador/mirador-watch.sh +1 -1
- package/uscha-kit/.claude/skills/uscha-mirador/mirador.template.html +666 -586
- package/uscha-kit/.claude-plugin/plugin.json +1 -1
- package/uscha-kit/.codex-plugin/plugin.json +1 -1
- package/uscha-kit/CHANGELOG-1.41.0.md +18 -0
- package/uscha-kit/CHANGELOG-1.41.1.md +53 -0
- package/uscha-kit/CHANGELOG-1.41.2.md +34 -0
- package/uscha-kit/CHANGELOG-1.41.3.md +30 -0
- package/uscha-kit/CHANGELOG-1.42.0.md +41 -0
- package/uscha-kit/CHANGELOG-1.43.0.md +37 -0
- package/uscha-kit/INSTALL.md +120 -101
- package/uscha-kit/README.md +24 -13
- package/uscha-kit/VERSION +1 -1
- package/uscha-kit/WORKBENCH.md +19 -5
- package/uscha-kit/hooks/block-approved-writes.py +25 -0
- package/uscha-kit/install-uscha.py +534 -267
- package/uscha-kit/skills/uscha-adr-refine/SKILL.md +2 -2
- package/uscha-kit/skills/uscha-devloop/SKILL.md +3 -1
- package/uscha-kit/skills/uscha-devloop/qa_ledger.py +729 -155
- package/uscha-kit/skills/uscha-mirador/SKILL.md +22 -7
- package/uscha-kit/skills/uscha-mirador/mirador-render.py +44 -5
- package/uscha-kit/skills/uscha-mirador/mirador-watch.ps1 +1 -1
- package/uscha-kit/skills/uscha-mirador/mirador-watch.sh +1 -1
- package/uscha-kit/skills/uscha-mirador/mirador.template.html +666 -586
- package/uscha-kit/templates/CONSTITUTION.md +4 -4
- package/uscha-kit/templates/docs/adr/README.md +19 -19
- package/uscha-kit/tests/ledger-integrity-regressions.py +136 -0
- package/uscha-kit/tests/smoke-engine.sh +1312 -29
- package/uscha-kit/uscha.config.json +1 -1
- package/uscha-kit/workbench-doctor.sh +47 -3
|
@@ -75,23 +75,38 @@ wires the JSON the engine emits into the template. Read-only.
|
|
|
75
75
|
this for a pure measured view.
|
|
76
76
|
|
|
77
77
|
4. **Render `mirador.html`** with the standalone renderer — it runs `dashboard --json`,
|
|
78
|
-
merges the sidecar telemetry if present, injects `const DATA`,
|
|
78
|
+
merges the sidecar telemetry if present, injects `const DATA`, writes the file, prints its
|
|
79
|
+
absolute path (`OPEN IT: ...`), and opens it in the default browser. From the project root,
|
|
80
|
+
with no long paths — `--engine` and `--template` default to the renderer's sibling skill
|
|
81
|
+
files (kit 1.41.2):
|
|
79
82
|
```bash
|
|
80
|
-
python3 <skill-dir>/mirador-render.py --
|
|
81
|
-
--template <skill-dir>/mirador.template.html --out mirador.html
|
|
83
|
+
python3 <skill-dir>/mirador-render.py --ledger QA-LEDGER.json
|
|
82
84
|
```
|
|
83
85
|
The engine stays model-agnostic — telemetry is merged by the renderer (the adapter), NOT
|
|
84
86
|
by `dashboard`. If the ledger is missing, warn and stop (run `uscha-devloop` first). For
|
|
85
87
|
the time-lapse, `qa_ledger.py readiness --record` (opt-in) fills the history prospectively.
|
|
86
88
|
|
|
87
|
-
5. **
|
|
88
|
-
`
|
|
89
|
-
|
|
89
|
+
5. **Where to look:** the renderer already opened `mirador.html` and printed its absolute path
|
|
90
|
+
on the `OPEN IT:` line — surface that path to the operator. Pass `--no-open` to write the
|
|
91
|
+
file without opening a browser (headless/CI, or the watch loop below, which passes it).
|
|
92
|
+
|
|
93
|
+
## For a human at a terminal: `uscha mirador`
|
|
94
|
+
|
|
95
|
+
The one-liner above is what THIS skill runs. A human who just wants the dashboard — without a
|
|
96
|
+
Claude Code session — has a zero-friction verb instead (kit 1.43.0): from the project root,
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
uscha mirador # render + open, defaults to the QA-LEDGER.json convention
|
|
100
|
+
uscha mirador --watch # live second-screen view (auto-refresh, one self-reloading tab)
|
|
101
|
+
npx @andresmassello/uscha mirador # same, no install
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
No python, no paths: the verb resolves the engine, template and ledger on its own.
|
|
90
105
|
|
|
91
106
|
## Live second-screen view
|
|
92
107
|
|
|
93
108
|
For a mirador that updates while you keep coding in the terminal, run the watch loop in a
|
|
94
|
-
spare terminal and open `mirador.html` on a second monitor:
|
|
109
|
+
spare terminal and open `mirador.html` on a second monitor (or just use `uscha mirador --watch`):
|
|
95
110
|
|
|
96
111
|
```bash
|
|
97
112
|
# Windows: powershell -NoProfile -File <skill-dir>\mirador-watch.ps1 -Interval 30
|
|
@@ -59,15 +59,45 @@ def aggregate_telemetry(path):
|
|
|
59
59
|
"model": model, "effort": effort, "by_model": by_model}
|
|
60
60
|
|
|
61
61
|
|
|
62
|
+
def _json_for_html_script(value):
|
|
63
|
+
"""Serialize JSON without allowing data to terminate the enclosing script."""
|
|
64
|
+
return (json.dumps(value, ensure_ascii=False)
|
|
65
|
+
.replace("&", r"\u0026")
|
|
66
|
+
.replace("<", r"\u003c")
|
|
67
|
+
.replace(">", r"\u003e")
|
|
68
|
+
.replace("\u2028", r"\u2028")
|
|
69
|
+
.replace("\u2029", r"\u2029"))
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _open_best_effort(path):
|
|
73
|
+
"""Open the rendered file in the default browser; never fail (headless/CI)."""
|
|
74
|
+
try:
|
|
75
|
+
if sys.platform.startswith("win"):
|
|
76
|
+
os.startfile(path) # type: ignore[attr-defined] # Windows-only
|
|
77
|
+
elif sys.platform == "darwin":
|
|
78
|
+
subprocess.Popen(["open", path])
|
|
79
|
+
else:
|
|
80
|
+
subprocess.Popen(["xdg-open", path])
|
|
81
|
+
except Exception:
|
|
82
|
+
pass # the absolute path was already printed
|
|
83
|
+
|
|
84
|
+
|
|
62
85
|
def main():
|
|
86
|
+
here = os.path.dirname(os.path.abspath(__file__))
|
|
63
87
|
ap = argparse.ArgumentParser(description="render mirador.html from the ledger (+ optional vendor telemetry)")
|
|
64
|
-
|
|
88
|
+
# engine + template default to the SIBLING skill files, so from any project you can just
|
|
89
|
+
# run this script (or `/uscha-mirador`) with no long paths (kit 1.41.2).
|
|
90
|
+
ap.add_argument("--engine", default=os.path.join(here, os.pardir, "uscha-devloop", "qa_ledger.py"),
|
|
91
|
+
help="path to qa_ledger.py (default: the sibling uscha-devloop engine)")
|
|
65
92
|
ap.add_argument("--ledger", default="QA-LEDGER.json")
|
|
66
|
-
ap.add_argument("--template",
|
|
93
|
+
ap.add_argument("--template", default=os.path.join(here, "mirador.template.html"),
|
|
94
|
+
help="path to mirador.template.html (default: the sibling template)")
|
|
67
95
|
ap.add_argument("--out", default="mirador.html")
|
|
68
96
|
ap.add_argument("--sidecar", default=os.path.join(".uscha", "telemetry.jsonl"))
|
|
69
97
|
ap.add_argument("--refresh", type=int, default=0,
|
|
70
98
|
help="if >0, the page auto-reloads every N seconds (live second-screen view)")
|
|
99
|
+
ap.add_argument("--no-open", action="store_true",
|
|
100
|
+
help="write the file but do not open it in a browser")
|
|
71
101
|
args = ap.parse_args()
|
|
72
102
|
|
|
73
103
|
try:
|
|
@@ -93,18 +123,27 @@ def main():
|
|
|
93
123
|
print(f"[mirador-render] cannot read template {args.template}: {e}", file=sys.stderr)
|
|
94
124
|
return 1
|
|
95
125
|
payload = ("/*MIRADOR_DATA_START*/\nconst DATA = "
|
|
96
|
-
+
|
|
126
|
+
+ _json_for_html_script(data) + ";\n/*MIRADOR_DATA_END*/")
|
|
97
127
|
out = re.sub(r"/\*MIRADOR_DATA_START\*/.*?/\*MIRADOR_DATA_END\*/",
|
|
98
128
|
lambda m: payload, tpl, count=1, flags=re.S)
|
|
99
129
|
if args.refresh and args.refresh > 0:
|
|
100
130
|
# opt-in live reload: a meta-refresh, injected only when watching
|
|
101
131
|
out = out.replace("</head>",
|
|
102
132
|
f'<meta http-equiv="refresh" content="{args.refresh}">\n</head>', 1)
|
|
133
|
+
live = bool(args.refresh and args.refresh > 0)
|
|
103
134
|
with open(args.out, "w", encoding="utf-8") as f:
|
|
104
135
|
f.write(out)
|
|
105
136
|
score = (data.get("readiness") or {}).get("score")
|
|
106
|
-
|
|
107
|
-
|
|
137
|
+
out_abs = os.path.abspath(args.out)
|
|
138
|
+
print(f"[mirador-render] wrote {out_abs}")
|
|
139
|
+
print(f"[mirador-render] readiness {score} | telemetry {'on' if tel else 'off'} | "
|
|
140
|
+
f"refresh {args.refresh or 'off'}")
|
|
141
|
+
print(f"[mirador-render] OPEN IT: {out_abs}")
|
|
142
|
+
# Auto-open only a ONE-SHOT view. In live mode (--refresh) the page carries its own
|
|
143
|
+
# meta-refresh and reloads in the SAME tab, so opening on every render cycle would
|
|
144
|
+
# spawn a new browser tab each time (kit 1.41.3). Open it once by hand and let it live.
|
|
145
|
+
if not args.no_open and not live:
|
|
146
|
+
_open_best_effort(out_abs)
|
|
108
147
|
return 0
|
|
109
148
|
|
|
110
149
|
|
|
@@ -16,7 +16,7 @@ $out = if ($env:OUT) { $env:OUT } else { "mirador.html" }
|
|
|
16
16
|
$py = if ($env:PYTHON) { $env:PYTHON } else { "python" }
|
|
17
17
|
Write-Host "mirador-watch: regenerating $out every ${Interval}s (Ctrl-C to stop). Open $out in a browser."
|
|
18
18
|
while ($true) {
|
|
19
|
-
& $py (Join-Path $here "mirador-render.py") --engine $engine --ledger $ledger --template $template --out $out --refresh $Interval
|
|
19
|
+
& $py (Join-Path $here "mirador-render.py") --engine $engine --ledger $ledger --template $template --out $out --refresh $Interval --no-open
|
|
20
20
|
if ($LASTEXITCODE -ne 0) { Write-Host "mirador-watch: render failed (ledger missing? run uscha-devloop first) -- retrying" }
|
|
21
21
|
Start-Sleep -Seconds $Interval
|
|
22
22
|
}
|
|
@@ -20,7 +20,7 @@ command -v "$PY" >/dev/null 2>&1 || PY=python
|
|
|
20
20
|
echo "mirador-watch: regenerating $OUT every ${INTERVAL}s (Ctrl-C to stop). Open $OUT in a browser."
|
|
21
21
|
while true; do
|
|
22
22
|
"$PY" "$HERE/mirador-render.py" --engine "$ENGINE" --ledger "$LEDGER" \
|
|
23
|
-
--template "$TEMPLATE" --out "$OUT" --refresh "$INTERVAL" || \
|
|
23
|
+
--template "$TEMPLATE" --out "$OUT" --refresh "$INTERVAL" --no-open || \
|
|
24
24
|
echo "mirador-watch: render failed (ledger missing? run uscha-devloop first) -- retrying"
|
|
25
25
|
sleep "$INTERVAL"
|
|
26
26
|
done
|