@andresmassello/uscha 1.94.0 → 1.95.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 +2 -2
- package/package.json +1 -1
- package/uscha-kit/.claude/skills/uscha-devloop/qa_ledger.py +72 -58
- package/uscha-kit/.claude-plugin/plugin.json +1 -1
- package/uscha-kit/.codex-plugin/plugin.json +1 -1
- package/uscha-kit/README.md +1 -1
- package/uscha-kit/VERSION +1 -1
- package/uscha-kit/skills/uscha-devloop/qa_ledger.py +72 -58
- package/uscha-kit/uscha.config.json +1 -1
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ Requires **Python 3.8+** on the machine (the engine is Python stdlib — no pip
|
|
|
40
40
|
runtime dependencies). The npm package is a thin router; the canonical installer is
|
|
41
41
|
`uscha-kit/install-uscha.py`.
|
|
42
42
|
|
|
43
|
-
**Kit v1.
|
|
43
|
+
**Kit v1.95.0** <!-- uscha:version --> · [uscha.dev](https://uscha.dev) ·
|
|
44
44
|
[changelog](https://github.com/andresmassello/uscha/blob/main/uscha-kit/CHANGELOG.md)
|
|
45
45
|
(the per-release changelogs live in the repo, not in the npm tarball)
|
|
46
46
|
|
|
@@ -85,7 +85,7 @@ automatic tool can perform: a human verdict.
|
|
|
85
85
|
from the compiled code: 0.828 measured (12 archetypes) — names AND behaviour
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
**What each arrow is, in the engine (kit 1.
|
|
88
|
+
**What each arrow is, in the engine (kit 1.95.0, 53 subcommands, all measured):**
|
|
89
89
|
|
|
90
90
|
| Leg | Subcommands | What it establishes |
|
|
91
91
|
|---|---|---|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@andresmassello/uscha",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.95.0",
|
|
4
4
|
"description": "Spec-driven development for LLM coding agents: 9 skills + a stdlib evidence engine. Facts block, guesses advise; the human approves.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Andres Massello",
|
|
@@ -206,17 +206,51 @@ def _repo_cfg(ledger, name):
|
|
|
206
206
|
# measurement: coverage
|
|
207
207
|
# --------------------------------------------------------------------------- #
|
|
208
208
|
def _jacoco_line_counter(xml_path):
|
|
209
|
-
"""Return (missed, covered) for the report-level LINE counter
|
|
209
|
+
"""Return (missed, covered) for the report-level LINE counter, or None when the report
|
|
210
|
+
could not be READ. The distinction is the whole point: a report that measured nothing
|
|
211
|
+
must never be summed as (0, 0) — that is an invented number, and with one module's XML
|
|
212
|
+
truncated mid-write it made the surviving modules' percentage look like the project's
|
|
213
|
+
(audit 1.94.1). Absence is never invented as a number — the rule `cobertura_coverage`
|
|
214
|
+
already states, applied to the JaCoCo readers too. A report with no LINE counter at all
|
|
215
|
+
is a real, readable zero and stays (0, 0)."""
|
|
210
216
|
try:
|
|
211
217
|
root = _parse_xml(xml_path).getroot()
|
|
212
|
-
except ET.ParseError:
|
|
213
|
-
return
|
|
218
|
+
except (ET.ParseError, OSError, ReportTooLarge):
|
|
219
|
+
return None
|
|
214
220
|
for c in root.findall("counter"):
|
|
215
221
|
if c.get("type") == "LINE":
|
|
216
|
-
|
|
222
|
+
try:
|
|
223
|
+
return int(c.get("missed", 0)), int(c.get("covered", 0))
|
|
224
|
+
except (TypeError, ValueError):
|
|
225
|
+
return None # a counter that is not a number measured nothing
|
|
217
226
|
return 0, 0
|
|
218
227
|
|
|
219
228
|
|
|
229
|
+
def _jacoco_result(files):
|
|
230
|
+
"""Sum the LINE counters of `files`, or report the WHOLE reading unmeasured. Shared by
|
|
231
|
+
maven/gradle/ant: three hand-copied versions of this sum is how one of them would drift.
|
|
232
|
+
|
|
233
|
+
ONE unreadable report makes the reading unmeasured, and an unmeasured reading is
|
|
234
|
+
(0, 0, 0.0) -- not the survivors' percentage with a false flag beside it. Every other
|
|
235
|
+
reader in this file returns pct 0.0 whenever report_found is False, and readers of the
|
|
236
|
+
result rely on it: `readiness` scores coverage as pct/threshold WITHOUT consulting
|
|
237
|
+
report_found, and `snapshot` prints and persists the pct next to the flag. Handing them
|
|
238
|
+
the surviving modules' number would score a project on a question nobody asked
|
|
239
|
+
(audit 1.94.1). The report paths are still listed -- the operator needs to know which
|
|
240
|
+
files were looked at."""
|
|
241
|
+
parsed = [_jacoco_line_counter(f) for f in files]
|
|
242
|
+
reports = [f.replace("\\", "/") for f in files]
|
|
243
|
+
if not files or any(p is None for p in parsed):
|
|
244
|
+
return {"covered": 0, "missed": 0, "pct": 0.0, "report_found": False,
|
|
245
|
+
"reports": reports}
|
|
246
|
+
missed = sum(p[0] for p in parsed)
|
|
247
|
+
covered = sum(p[1] for p in parsed)
|
|
248
|
+
total = missed + covered
|
|
249
|
+
pct = round(covered / total * 100, 2) if total else 0.0
|
|
250
|
+
return {"covered": covered, "missed": missed, "pct": pct,
|
|
251
|
+
"report_found": True, "reports": reports}
|
|
252
|
+
|
|
253
|
+
|
|
220
254
|
def maven_coverage(repo_path):
|
|
221
255
|
"""
|
|
222
256
|
Prefer an aggregate report if present, else sum per-module reports.
|
|
@@ -231,16 +265,7 @@ def maven_coverage(repo_path):
|
|
|
231
265
|
files = glob.glob(os.path.join(repo_path, "**", "target", "site",
|
|
232
266
|
"jacoco", "jacoco.xml"),
|
|
233
267
|
recursive=True)
|
|
234
|
-
|
|
235
|
-
for f in files:
|
|
236
|
-
m, c = _jacoco_line_counter(f)
|
|
237
|
-
missed += m
|
|
238
|
-
covered += c
|
|
239
|
-
total = missed + covered
|
|
240
|
-
pct = round(covered / total * 100, 2) if total else 0.0
|
|
241
|
-
return {"covered": covered, "missed": missed, "pct": pct,
|
|
242
|
-
"report_found": bool(files),
|
|
243
|
-
"reports": [f.replace("\\", "/") for f in files]}
|
|
268
|
+
return _jacoco_result(files)
|
|
244
269
|
|
|
245
270
|
|
|
246
271
|
def flutter_coverage(repo_path):
|
|
@@ -343,16 +368,7 @@ def gradle_coverage(repo_path):
|
|
|
343
368
|
if not files:
|
|
344
369
|
files = glob.glob(os.path.join(repo_path, "**", "build", "reports",
|
|
345
370
|
"jacoco", "jacoco.xml"), recursive=True)
|
|
346
|
-
|
|
347
|
-
for f in files:
|
|
348
|
-
m, c = _jacoco_line_counter(f)
|
|
349
|
-
missed += m
|
|
350
|
-
covered += c
|
|
351
|
-
total = missed + covered
|
|
352
|
-
pct = round(covered / total * 100, 2) if total else 0.0
|
|
353
|
-
return {"covered": covered, "missed": missed, "pct": pct,
|
|
354
|
-
"report_found": bool(files),
|
|
355
|
-
"reports": [f.replace("\\", "/") for f in files]}
|
|
371
|
+
return _jacoco_result(files)
|
|
356
372
|
|
|
357
373
|
|
|
358
374
|
def ant_coverage(repo_path):
|
|
@@ -360,16 +376,7 @@ def ant_coverage(repo_path):
|
|
|
360
376
|
report task writes wherever the build file says -- so the report is discovered
|
|
361
377
|
RECURSIVELY by name instead of guessing one convention."""
|
|
362
378
|
files = _ant_reports(repo_path, "jacoco.xml")
|
|
363
|
-
|
|
364
|
-
for f in files:
|
|
365
|
-
m, c = _jacoco_line_counter(f)
|
|
366
|
-
missed += m
|
|
367
|
-
covered += c
|
|
368
|
-
total = missed + covered
|
|
369
|
-
pct = round(covered / total * 100, 2) if total else 0.0
|
|
370
|
-
return {"covered": covered, "missed": missed, "pct": pct,
|
|
371
|
-
"report_found": bool(files),
|
|
372
|
-
"reports": [f.replace("\\", "/") for f in files]}
|
|
379
|
+
return _jacoco_result(files)
|
|
373
380
|
|
|
374
381
|
|
|
375
382
|
def coverage(repo_path, repo_type):
|
|
@@ -1276,7 +1283,15 @@ def _mk_id(tool, rule, fname, line, granularity):
|
|
|
1276
1283
|
|
|
1277
1284
|
def _find_all(base, patterns, explicit):
|
|
1278
1285
|
if explicit:
|
|
1279
|
-
|
|
1286
|
+
if not os.path.exists(explicit):
|
|
1287
|
+
# An EXPLICIT path is a claim the operator made about where the report is. When
|
|
1288
|
+
# it is not there, the honest reading is a typo or a build that never wrote it --
|
|
1289
|
+
# not "this linter has no findings". Returning [] made ingest-gate log nothing
|
|
1290
|
+
# and exit 0, so a mistyped --ruff read as a clean gate (audit 1.94.1). Same
|
|
1291
|
+
# fail-closed exit an unparseable report already gets, with the path named.
|
|
1292
|
+
_invalid_static_report(explicit, "linter",
|
|
1293
|
+
"no such file (explicit path given, nothing to ingest)")
|
|
1294
|
+
return [explicit]
|
|
1280
1295
|
found = []
|
|
1281
1296
|
for pat in patterns:
|
|
1282
1297
|
found += glob.glob(os.path.join(base, pat), recursive=True)
|
|
@@ -3107,7 +3122,7 @@ def cmd_fastpath_eval(args):
|
|
|
3107
3122
|
sig("configured", False, "defaults.fast_path present and enabled",
|
|
3108
3123
|
"config.defaults.fast_path", False)
|
|
3109
3124
|
else:
|
|
3110
|
-
repo_path =
|
|
3125
|
+
repo_path = _scope_path(ledger, args.repo)
|
|
3111
3126
|
base, base_src = args.base, "--base"
|
|
3112
3127
|
if base:
|
|
3113
3128
|
probe = subprocess.run(["git", "rev-parse", "--verify", base + "^{commit}"],
|
|
@@ -3694,7 +3709,7 @@ def cmd_cleanroom(args):
|
|
|
3694
3709
|
import time
|
|
3695
3710
|
ledger = _load(args.ledger)
|
|
3696
3711
|
_repo_node(ledger, args.repo)
|
|
3697
|
-
repo_path =
|
|
3712
|
+
repo_path = _scope_path(ledger, args.repo)
|
|
3698
3713
|
|
|
3699
3714
|
def git(*a, **kw):
|
|
3700
3715
|
cwd = kw.pop("cwd", repo_path)
|
|
@@ -7038,11 +7053,10 @@ def _struct_distance(a, b):
|
|
|
7038
7053
|
|
|
7039
7054
|
|
|
7040
7055
|
def _oracle_hash(arm_dir):
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
|
|
7044
|
-
|
|
7045
|
-
return None
|
|
7056
|
+
# the arm's withheld oracle, hashed by exact bytes -- an arm whose oracle differs by one
|
|
7057
|
+
# byte is a different experiment (cmd_lang_compare refuses the pair). Same rule, and now the
|
|
7058
|
+
# same code, as a manifest unit: `_sha256_file`.
|
|
7059
|
+
return _sha256_file(os.path.join(arm_dir, "oracle", "ORACLE.json"))
|
|
7046
7060
|
|
|
7047
7061
|
|
|
7048
7062
|
def cmd_lang_compare(args):
|
|
@@ -7533,11 +7547,18 @@ DEFAULT_STATIC_ZERO_AT = 10 # gated-open count at which the static dimension hi
|
|
|
7533
7547
|
BANDS = [(95, "READY"), (80, "RELEASE CANDIDATE"), (50, "IN PROGRESS"), (0, "NOT READY")]
|
|
7534
7548
|
|
|
7535
7549
|
|
|
7536
|
-
def
|
|
7537
|
-
|
|
7550
|
+
def _banded(score, bands):
|
|
7551
|
+
"""The label of the highest floor the score reaches. Every band table ends at floor 0, so
|
|
7552
|
+
the last row IS the default -- named once here instead of being restated as a trailing
|
|
7553
|
+
`return` in four callers, where it read as a fifth band nobody could reach (1.95.0)."""
|
|
7554
|
+
for floor, label in bands:
|
|
7538
7555
|
if score >= floor:
|
|
7539
7556
|
return label
|
|
7540
|
-
return
|
|
7557
|
+
return bands[-1][1]
|
|
7558
|
+
|
|
7559
|
+
|
|
7560
|
+
def _band(score):
|
|
7561
|
+
return _banded(score, BANDS)
|
|
7541
7562
|
|
|
7542
7563
|
|
|
7543
7564
|
_AC_ID = re.compile(r"(?i)^[*_`]*\s*AC[-_]?0*(\d+)\b[*_`]*[\s.:—–·-]*")
|
|
@@ -9201,7 +9222,9 @@ def cmd_top(args):
|
|
|
9201
9222
|
|
|
9202
9223
|
total = len(obligations)
|
|
9203
9224
|
done, fail, quar = _n("MEASURED_PASS"), _n("MEASURED_FAIL"), _n("QUARANTINE")
|
|
9204
|
-
|
|
9225
|
+
# TRACED/TAGGED are declared in TOP_STATES for the renderer and NEVER assigned above
|
|
9226
|
+
# (v0.1 has no source for either), so only UNMEASURED can carry a count here.
|
|
9227
|
+
unmeasured = _n("UNMEASURED")
|
|
9205
9228
|
pct = _top_pct(done, total)
|
|
9206
9229
|
# INV-TOP-06 (ADR-038): DONE never publishes 100% while the seal is MEASURED broken --
|
|
9207
9230
|
# every criterion green against evidence that no longer belongs to this code state is
|
|
@@ -9765,17 +9788,11 @@ _FUNC_RE = re.compile(
|
|
|
9765
9788
|
|
|
9766
9789
|
|
|
9767
9790
|
def _simplicity_band(score):
|
|
9768
|
-
|
|
9769
|
-
if score >= floor:
|
|
9770
|
-
return label
|
|
9771
|
-
return "OVERBUILT"
|
|
9791
|
+
return _banded(score, SIMPLICITY_BANDS)
|
|
9772
9792
|
|
|
9773
9793
|
|
|
9774
9794
|
def _rebuild_band(score):
|
|
9775
|
-
|
|
9776
|
-
if score >= floor:
|
|
9777
|
-
return label
|
|
9778
|
-
return "DIVERGE"
|
|
9795
|
+
return _banded(score, REBUILD_BANDS)
|
|
9779
9796
|
|
|
9780
9797
|
|
|
9781
9798
|
def _test_file_set(repo_path, repo_type):
|
|
@@ -10334,10 +10351,7 @@ _WASTE_COMMENT = ("//", "#", "*", "--", "/*", "*/", '"""', "'''", ";;", "<!--")
|
|
|
10334
10351
|
|
|
10335
10352
|
|
|
10336
10353
|
def _waste_band(score):
|
|
10337
|
-
|
|
10338
|
-
if score >= floor:
|
|
10339
|
-
return label
|
|
10340
|
-
return "WASTEFUL"
|
|
10354
|
+
return _banded(score, WASTE_BANDS)
|
|
10341
10355
|
|
|
10342
10356
|
|
|
10343
10357
|
def _path_allowed(rel, allow_paths):
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
3
|
"name": "uscha",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.95.0",
|
|
5
5
|
"displayName": "Uscha",
|
|
6
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, 53 subcommands + universal installer + npm/npx router). Facts block, guesses advise; the human approves.",
|
|
7
7
|
"author": {
|
package/uscha-kit/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# uscha-kit
|
|
2
2
|
|
|
3
|
-
**Kit version:** v1.
|
|
3
|
+
**Kit version:** v1.95.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.
|
|
1
|
+
uscha-kit 1.95.0
|
|
@@ -206,17 +206,51 @@ def _repo_cfg(ledger, name):
|
|
|
206
206
|
# measurement: coverage
|
|
207
207
|
# --------------------------------------------------------------------------- #
|
|
208
208
|
def _jacoco_line_counter(xml_path):
|
|
209
|
-
"""Return (missed, covered) for the report-level LINE counter
|
|
209
|
+
"""Return (missed, covered) for the report-level LINE counter, or None when the report
|
|
210
|
+
could not be READ. The distinction is the whole point: a report that measured nothing
|
|
211
|
+
must never be summed as (0, 0) — that is an invented number, and with one module's XML
|
|
212
|
+
truncated mid-write it made the surviving modules' percentage look like the project's
|
|
213
|
+
(audit 1.94.1). Absence is never invented as a number — the rule `cobertura_coverage`
|
|
214
|
+
already states, applied to the JaCoCo readers too. A report with no LINE counter at all
|
|
215
|
+
is a real, readable zero and stays (0, 0)."""
|
|
210
216
|
try:
|
|
211
217
|
root = _parse_xml(xml_path).getroot()
|
|
212
|
-
except ET.ParseError:
|
|
213
|
-
return
|
|
218
|
+
except (ET.ParseError, OSError, ReportTooLarge):
|
|
219
|
+
return None
|
|
214
220
|
for c in root.findall("counter"):
|
|
215
221
|
if c.get("type") == "LINE":
|
|
216
|
-
|
|
222
|
+
try:
|
|
223
|
+
return int(c.get("missed", 0)), int(c.get("covered", 0))
|
|
224
|
+
except (TypeError, ValueError):
|
|
225
|
+
return None # a counter that is not a number measured nothing
|
|
217
226
|
return 0, 0
|
|
218
227
|
|
|
219
228
|
|
|
229
|
+
def _jacoco_result(files):
|
|
230
|
+
"""Sum the LINE counters of `files`, or report the WHOLE reading unmeasured. Shared by
|
|
231
|
+
maven/gradle/ant: three hand-copied versions of this sum is how one of them would drift.
|
|
232
|
+
|
|
233
|
+
ONE unreadable report makes the reading unmeasured, and an unmeasured reading is
|
|
234
|
+
(0, 0, 0.0) -- not the survivors' percentage with a false flag beside it. Every other
|
|
235
|
+
reader in this file returns pct 0.0 whenever report_found is False, and readers of the
|
|
236
|
+
result rely on it: `readiness` scores coverage as pct/threshold WITHOUT consulting
|
|
237
|
+
report_found, and `snapshot` prints and persists the pct next to the flag. Handing them
|
|
238
|
+
the surviving modules' number would score a project on a question nobody asked
|
|
239
|
+
(audit 1.94.1). The report paths are still listed -- the operator needs to know which
|
|
240
|
+
files were looked at."""
|
|
241
|
+
parsed = [_jacoco_line_counter(f) for f in files]
|
|
242
|
+
reports = [f.replace("\\", "/") for f in files]
|
|
243
|
+
if not files or any(p is None for p in parsed):
|
|
244
|
+
return {"covered": 0, "missed": 0, "pct": 0.0, "report_found": False,
|
|
245
|
+
"reports": reports}
|
|
246
|
+
missed = sum(p[0] for p in parsed)
|
|
247
|
+
covered = sum(p[1] for p in parsed)
|
|
248
|
+
total = missed + covered
|
|
249
|
+
pct = round(covered / total * 100, 2) if total else 0.0
|
|
250
|
+
return {"covered": covered, "missed": missed, "pct": pct,
|
|
251
|
+
"report_found": True, "reports": reports}
|
|
252
|
+
|
|
253
|
+
|
|
220
254
|
def maven_coverage(repo_path):
|
|
221
255
|
"""
|
|
222
256
|
Prefer an aggregate report if present, else sum per-module reports.
|
|
@@ -231,16 +265,7 @@ def maven_coverage(repo_path):
|
|
|
231
265
|
files = glob.glob(os.path.join(repo_path, "**", "target", "site",
|
|
232
266
|
"jacoco", "jacoco.xml"),
|
|
233
267
|
recursive=True)
|
|
234
|
-
|
|
235
|
-
for f in files:
|
|
236
|
-
m, c = _jacoco_line_counter(f)
|
|
237
|
-
missed += m
|
|
238
|
-
covered += c
|
|
239
|
-
total = missed + covered
|
|
240
|
-
pct = round(covered / total * 100, 2) if total else 0.0
|
|
241
|
-
return {"covered": covered, "missed": missed, "pct": pct,
|
|
242
|
-
"report_found": bool(files),
|
|
243
|
-
"reports": [f.replace("\\", "/") for f in files]}
|
|
268
|
+
return _jacoco_result(files)
|
|
244
269
|
|
|
245
270
|
|
|
246
271
|
def flutter_coverage(repo_path):
|
|
@@ -343,16 +368,7 @@ def gradle_coverage(repo_path):
|
|
|
343
368
|
if not files:
|
|
344
369
|
files = glob.glob(os.path.join(repo_path, "**", "build", "reports",
|
|
345
370
|
"jacoco", "jacoco.xml"), recursive=True)
|
|
346
|
-
|
|
347
|
-
for f in files:
|
|
348
|
-
m, c = _jacoco_line_counter(f)
|
|
349
|
-
missed += m
|
|
350
|
-
covered += c
|
|
351
|
-
total = missed + covered
|
|
352
|
-
pct = round(covered / total * 100, 2) if total else 0.0
|
|
353
|
-
return {"covered": covered, "missed": missed, "pct": pct,
|
|
354
|
-
"report_found": bool(files),
|
|
355
|
-
"reports": [f.replace("\\", "/") for f in files]}
|
|
371
|
+
return _jacoco_result(files)
|
|
356
372
|
|
|
357
373
|
|
|
358
374
|
def ant_coverage(repo_path):
|
|
@@ -360,16 +376,7 @@ def ant_coverage(repo_path):
|
|
|
360
376
|
report task writes wherever the build file says -- so the report is discovered
|
|
361
377
|
RECURSIVELY by name instead of guessing one convention."""
|
|
362
378
|
files = _ant_reports(repo_path, "jacoco.xml")
|
|
363
|
-
|
|
364
|
-
for f in files:
|
|
365
|
-
m, c = _jacoco_line_counter(f)
|
|
366
|
-
missed += m
|
|
367
|
-
covered += c
|
|
368
|
-
total = missed + covered
|
|
369
|
-
pct = round(covered / total * 100, 2) if total else 0.0
|
|
370
|
-
return {"covered": covered, "missed": missed, "pct": pct,
|
|
371
|
-
"report_found": bool(files),
|
|
372
|
-
"reports": [f.replace("\\", "/") for f in files]}
|
|
379
|
+
return _jacoco_result(files)
|
|
373
380
|
|
|
374
381
|
|
|
375
382
|
def coverage(repo_path, repo_type):
|
|
@@ -1276,7 +1283,15 @@ def _mk_id(tool, rule, fname, line, granularity):
|
|
|
1276
1283
|
|
|
1277
1284
|
def _find_all(base, patterns, explicit):
|
|
1278
1285
|
if explicit:
|
|
1279
|
-
|
|
1286
|
+
if not os.path.exists(explicit):
|
|
1287
|
+
# An EXPLICIT path is a claim the operator made about where the report is. When
|
|
1288
|
+
# it is not there, the honest reading is a typo or a build that never wrote it --
|
|
1289
|
+
# not "this linter has no findings". Returning [] made ingest-gate log nothing
|
|
1290
|
+
# and exit 0, so a mistyped --ruff read as a clean gate (audit 1.94.1). Same
|
|
1291
|
+
# fail-closed exit an unparseable report already gets, with the path named.
|
|
1292
|
+
_invalid_static_report(explicit, "linter",
|
|
1293
|
+
"no such file (explicit path given, nothing to ingest)")
|
|
1294
|
+
return [explicit]
|
|
1280
1295
|
found = []
|
|
1281
1296
|
for pat in patterns:
|
|
1282
1297
|
found += glob.glob(os.path.join(base, pat), recursive=True)
|
|
@@ -3107,7 +3122,7 @@ def cmd_fastpath_eval(args):
|
|
|
3107
3122
|
sig("configured", False, "defaults.fast_path present and enabled",
|
|
3108
3123
|
"config.defaults.fast_path", False)
|
|
3109
3124
|
else:
|
|
3110
|
-
repo_path =
|
|
3125
|
+
repo_path = _scope_path(ledger, args.repo)
|
|
3111
3126
|
base, base_src = args.base, "--base"
|
|
3112
3127
|
if base:
|
|
3113
3128
|
probe = subprocess.run(["git", "rev-parse", "--verify", base + "^{commit}"],
|
|
@@ -3694,7 +3709,7 @@ def cmd_cleanroom(args):
|
|
|
3694
3709
|
import time
|
|
3695
3710
|
ledger = _load(args.ledger)
|
|
3696
3711
|
_repo_node(ledger, args.repo)
|
|
3697
|
-
repo_path =
|
|
3712
|
+
repo_path = _scope_path(ledger, args.repo)
|
|
3698
3713
|
|
|
3699
3714
|
def git(*a, **kw):
|
|
3700
3715
|
cwd = kw.pop("cwd", repo_path)
|
|
@@ -7038,11 +7053,10 @@ def _struct_distance(a, b):
|
|
|
7038
7053
|
|
|
7039
7054
|
|
|
7040
7055
|
def _oracle_hash(arm_dir):
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
|
|
7044
|
-
|
|
7045
|
-
return None
|
|
7056
|
+
# the arm's withheld oracle, hashed by exact bytes -- an arm whose oracle differs by one
|
|
7057
|
+
# byte is a different experiment (cmd_lang_compare refuses the pair). Same rule, and now the
|
|
7058
|
+
# same code, as a manifest unit: `_sha256_file`.
|
|
7059
|
+
return _sha256_file(os.path.join(arm_dir, "oracle", "ORACLE.json"))
|
|
7046
7060
|
|
|
7047
7061
|
|
|
7048
7062
|
def cmd_lang_compare(args):
|
|
@@ -7533,11 +7547,18 @@ DEFAULT_STATIC_ZERO_AT = 10 # gated-open count at which the static dimension hi
|
|
|
7533
7547
|
BANDS = [(95, "READY"), (80, "RELEASE CANDIDATE"), (50, "IN PROGRESS"), (0, "NOT READY")]
|
|
7534
7548
|
|
|
7535
7549
|
|
|
7536
|
-
def
|
|
7537
|
-
|
|
7550
|
+
def _banded(score, bands):
|
|
7551
|
+
"""The label of the highest floor the score reaches. Every band table ends at floor 0, so
|
|
7552
|
+
the last row IS the default -- named once here instead of being restated as a trailing
|
|
7553
|
+
`return` in four callers, where it read as a fifth band nobody could reach (1.95.0)."""
|
|
7554
|
+
for floor, label in bands:
|
|
7538
7555
|
if score >= floor:
|
|
7539
7556
|
return label
|
|
7540
|
-
return
|
|
7557
|
+
return bands[-1][1]
|
|
7558
|
+
|
|
7559
|
+
|
|
7560
|
+
def _band(score):
|
|
7561
|
+
return _banded(score, BANDS)
|
|
7541
7562
|
|
|
7542
7563
|
|
|
7543
7564
|
_AC_ID = re.compile(r"(?i)^[*_`]*\s*AC[-_]?0*(\d+)\b[*_`]*[\s.:—–·-]*")
|
|
@@ -9201,7 +9222,9 @@ def cmd_top(args):
|
|
|
9201
9222
|
|
|
9202
9223
|
total = len(obligations)
|
|
9203
9224
|
done, fail, quar = _n("MEASURED_PASS"), _n("MEASURED_FAIL"), _n("QUARANTINE")
|
|
9204
|
-
|
|
9225
|
+
# TRACED/TAGGED are declared in TOP_STATES for the renderer and NEVER assigned above
|
|
9226
|
+
# (v0.1 has no source for either), so only UNMEASURED can carry a count here.
|
|
9227
|
+
unmeasured = _n("UNMEASURED")
|
|
9205
9228
|
pct = _top_pct(done, total)
|
|
9206
9229
|
# INV-TOP-06 (ADR-038): DONE never publishes 100% while the seal is MEASURED broken --
|
|
9207
9230
|
# every criterion green against evidence that no longer belongs to this code state is
|
|
@@ -9765,17 +9788,11 @@ _FUNC_RE = re.compile(
|
|
|
9765
9788
|
|
|
9766
9789
|
|
|
9767
9790
|
def _simplicity_band(score):
|
|
9768
|
-
|
|
9769
|
-
if score >= floor:
|
|
9770
|
-
return label
|
|
9771
|
-
return "OVERBUILT"
|
|
9791
|
+
return _banded(score, SIMPLICITY_BANDS)
|
|
9772
9792
|
|
|
9773
9793
|
|
|
9774
9794
|
def _rebuild_band(score):
|
|
9775
|
-
|
|
9776
|
-
if score >= floor:
|
|
9777
|
-
return label
|
|
9778
|
-
return "DIVERGE"
|
|
9795
|
+
return _banded(score, REBUILD_BANDS)
|
|
9779
9796
|
|
|
9780
9797
|
|
|
9781
9798
|
def _test_file_set(repo_path, repo_type):
|
|
@@ -10334,10 +10351,7 @@ _WASTE_COMMENT = ("//", "#", "*", "--", "/*", "*/", '"""', "'''", ";;", "<!--")
|
|
|
10334
10351
|
|
|
10335
10352
|
|
|
10336
10353
|
def _waste_band(score):
|
|
10337
|
-
|
|
10338
|
-
if score >= floor:
|
|
10339
|
-
return label
|
|
10340
|
-
return "WASTEFUL"
|
|
10354
|
+
return _banded(score, WASTE_BANDS)
|
|
10341
10355
|
|
|
10342
10356
|
|
|
10343
10357
|
def _path_allowed(rel, allow_paths):
|