@andresmassello/uscha 1.72.0 → 1.74.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 +531 -0
- package/uscha-kit/.claude-plugin/plugin.json +2 -2
- 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/reports/junit/.bootstrap-cases.json +1 -0
- package/uscha-kit/reports/junit/.compile-cases.json +1 -0
- package/uscha-kit/skills/uscha-devloop/qa_ledger.py +531 -0
- 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.74.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
|
|
|
@@ -76,7 +76,7 @@ and see which file, which test, and when.
|
|
|
76
76
|
| `/uscha-mirador` | Bird's-eye HTML dashboard: readiness, trail, acceptance, loops |
|
|
77
77
|
| `/uscha-status` | One-line progress readout, in chat |
|
|
78
78
|
|
|
79
|
-
**A measurement engine** (`qa_ledger.py`,
|
|
79
|
+
**A measurement engine** (`qa_ledger.py`, 46 subcommands, Python stdlib) that ingests
|
|
80
80
|
evidence from **11 language stacks** — maven, gradle, ant, python, node, go, rust, dotnet,
|
|
81
81
|
cpp, swift, flutter — and computes a readiness score with hard caps and visible provenance.
|
|
82
82
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@andresmassello/uscha",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.74.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",
|
|
@@ -4965,6 +4965,495 @@ def cmd_ir_render(args):
|
|
|
4965
4965
|
sys.exit(0)
|
|
4966
4966
|
|
|
4967
4967
|
|
|
4968
|
+
# --------------------------------------------------------------------------- #
|
|
4969
|
+
# compiler contract (Diamond M3: the LLM is a compiler with a validated output
|
|
4970
|
+
# contract. The engine VALIDATES and INGESTS compilations; it NEVER compiles and
|
|
4971
|
+
# never calls a model. Only mechanical violations gate; every statistic is
|
|
4972
|
+
# advisory (INV-ADVISORY-01). ADR-016.)
|
|
4973
|
+
# --------------------------------------------------------------------------- #
|
|
4974
|
+
COMPILE_SCHEMA = "compile/0.1"
|
|
4975
|
+
COMPILE_REQUIRED = ("schema_version", "canonical_ir", "target_stack", "source",
|
|
4976
|
+
"tests", "trace_manifest", "unresolved_intent",
|
|
4977
|
+
"compilation_report")
|
|
4978
|
+
# The seal covers the load-bearing contract, NOT compilation_report: model, versions and
|
|
4979
|
+
# timestamps legitimately vary and never change WHAT was compiled. A hand edit of the
|
|
4980
|
+
# substance (source/tests/manifest/unresolved_intent) after production must trip the seal.
|
|
4981
|
+
COMPILE_SEALED = ("schema_version", "canonical_ir", "target_stack",
|
|
4982
|
+
"implementation_constraints", "source", "tests",
|
|
4983
|
+
"trace_manifest", "unresolved_intent")
|
|
4984
|
+
# Advisory degeneracy dial: a manifest of >=2 units where EVERY unit claims >= this share
|
|
4985
|
+
# of ALL IR nodes is "everything traces to everything" -- no unit discriminates. ADVISORY
|
|
4986
|
+
# ONLY: printed, never gates. The exact value is a reporting choice, not a contract,
|
|
4987
|
+
# precisely because it can never block (a threshold on a smell would be a judgment).
|
|
4988
|
+
_COMPILE_DEGENERATE_FANOUT = 0.8
|
|
4989
|
+
|
|
4990
|
+
|
|
4991
|
+
def _compile_seal(c):
|
|
4992
|
+
return _integrity_hash({k: c.get(k) for k in COMPILE_SEALED})
|
|
4993
|
+
|
|
4994
|
+
|
|
4995
|
+
def _sha256_file(path):
|
|
4996
|
+
try:
|
|
4997
|
+
with open(path, "rb") as fh:
|
|
4998
|
+
return hashlib.sha256(fh.read()).hexdigest()
|
|
4999
|
+
except OSError:
|
|
5000
|
+
return None
|
|
5001
|
+
|
|
5002
|
+
|
|
5003
|
+
def _contained_unit(base, unit):
|
|
5004
|
+
"""A compilation's units must be RELATIVE paths CONTAINED within the compilation
|
|
5005
|
+
directory: the manifest references what was compiled, and what was compiled lives with
|
|
5006
|
+
the compilation. An absolute path or a `..` escape lets a manifest name any file on the
|
|
5007
|
+
filesystem as a "source" unit and pass on that file's hash -- exactly the "manifest
|
|
5008
|
+
cannot lie about what was compiled" guarantee, defeated. Returns the resolved path, or
|
|
5009
|
+
None if the unit is absolute or escapes `base`. Both sides are `realpath`-normalized
|
|
5010
|
+
before comparison -- the Windows 8.3 short-path trap this repo already paid for once
|
|
5011
|
+
(a file INSIDE a tree judged outside it) applies to any containment check."""
|
|
5012
|
+
if os.path.isabs(unit):
|
|
5013
|
+
return None
|
|
5014
|
+
full = os.path.realpath(os.path.join(base, unit.replace("/", os.sep)))
|
|
5015
|
+
root = os.path.realpath(base)
|
|
5016
|
+
if full == root or full.startswith(root + os.sep):
|
|
5017
|
+
return full
|
|
5018
|
+
return None
|
|
5019
|
+
|
|
5020
|
+
|
|
5021
|
+
def _load_ir_at(path):
|
|
5022
|
+
"""Strict IR loader for an ARBITRARY IR.json. The repo's own ir/ is gitignored (a
|
|
5023
|
+
regenerable index), so the M3 reference IR is a committed fixture loaded here with the
|
|
5024
|
+
same posture as _load_ir: an unknown schema or a broken/hand-edited seal is refused,
|
|
5025
|
+
never mis-read. Returns (graph, errors); graph None when the file is absent."""
|
|
5026
|
+
if not os.path.isfile(path):
|
|
5027
|
+
return None, ["no reference IR at %s" % path]
|
|
5028
|
+
try:
|
|
5029
|
+
with open(path, encoding="utf-8-sig") as fh:
|
|
5030
|
+
g = json.load(fh)
|
|
5031
|
+
except (OSError, ValueError) as exc:
|
|
5032
|
+
return {}, ["unreadable: %s" % exc]
|
|
5033
|
+
if g.get("schema_version") != IR_SCHEMA:
|
|
5034
|
+
return g, ["schema_version %r != %r (an IR version this engine does not know is "
|
|
5035
|
+
"refused, not read)" % (g.get("schema_version"), IR_SCHEMA)]
|
|
5036
|
+
if not isinstance(g.get("nodes"), list) or not isinstance(g.get("edges"), list):
|
|
5037
|
+
return g, ["nodes/edges missing or not lists"]
|
|
5038
|
+
if g.get("_integrity") != _ir_seal(g):
|
|
5039
|
+
return g, ["reference IR integrity seal does not match -- it was hand-edited "
|
|
5040
|
+
"(regenerate via ir-extract)"]
|
|
5041
|
+
return g, []
|
|
5042
|
+
|
|
5043
|
+
|
|
5044
|
+
def _validate_compilation(comp_path, ir_graph):
|
|
5045
|
+
"""The deterministic checker (ADR-016). Returns (blocking_errors, advisory).
|
|
5046
|
+
|
|
5047
|
+
BLOCKS only on FACTS: unknown schema, a missing/mistyped section, a broken seal, an
|
|
5048
|
+
ir_hash that does not match the reference IR, a trace_manifest id that is not an IR
|
|
5049
|
+
node, a unit whose file is absent or whose hash does not match the bytes on disk, a
|
|
5050
|
+
malformed unresolved_intent entry. Every STATISTIC (fan-out degeneracy, empty/generic
|
|
5051
|
+
unresolved_intent, coverage) is advisory and can NEVER change the outcome -- a
|
|
5052
|
+
threshold on a smell is a judgment, and no judgment gates (INV-ADVISORY-01)."""
|
|
5053
|
+
errors, advisory = [], {}
|
|
5054
|
+
base = os.path.dirname(os.path.abspath(comp_path))
|
|
5055
|
+
try:
|
|
5056
|
+
with open(comp_path, encoding="utf-8-sig") as fh:
|
|
5057
|
+
c = json.load(fh)
|
|
5058
|
+
except (OSError, ValueError) as exc:
|
|
5059
|
+
return ["unreadable compilation: %s" % exc], advisory
|
|
5060
|
+
if c.get("schema_version") != COMPILE_SCHEMA:
|
|
5061
|
+
return ["schema_version %r != %r (a contract version this engine does not know is "
|
|
5062
|
+
"refused, not read)" % (c.get("schema_version"), COMPILE_SCHEMA)], advisory
|
|
5063
|
+
for k in COMPILE_REQUIRED:
|
|
5064
|
+
if k not in c:
|
|
5065
|
+
errors.append("required section missing: %s" % k)
|
|
5066
|
+
if errors:
|
|
5067
|
+
return errors, advisory
|
|
5068
|
+
for k, typ in (("source", list), ("tests", list), ("trace_manifest", list),
|
|
5069
|
+
("unresolved_intent", list), ("canonical_ir", dict),
|
|
5070
|
+
("compilation_report", dict)):
|
|
5071
|
+
if not isinstance(c.get(k), typ):
|
|
5072
|
+
errors.append("%s must be a %s" % (k, typ.__name__))
|
|
5073
|
+
if errors:
|
|
5074
|
+
return errors, advisory
|
|
5075
|
+
# ELEMENT shapes, checked before any `.get` on them: an adversarial/buggy compiler that
|
|
5076
|
+
# emits a list of strings (or a non-list `implements`) is a mechanical violation -> exit
|
|
5077
|
+
# 2 with a named fault, NEVER an AttributeError traceback (exit 1). This is the trust
|
|
5078
|
+
# boundary the contract exists to defend; the loops below assume dict elements.
|
|
5079
|
+
for k in ("source", "tests"):
|
|
5080
|
+
for i, u in enumerate(c.get(k)):
|
|
5081
|
+
if not isinstance(u, dict):
|
|
5082
|
+
errors.append("%s[%d] must be an object with unit/sha256" % (k, i))
|
|
5083
|
+
for i, e in enumerate(c.get("trace_manifest")):
|
|
5084
|
+
if not isinstance(e, dict):
|
|
5085
|
+
errors.append("trace_manifest[%d] must be an object with unit/implements" % i)
|
|
5086
|
+
elif not isinstance(e.get("implements"), list):
|
|
5087
|
+
errors.append("trace_manifest[%d].implements must be a list of IR node ids" % i)
|
|
5088
|
+
for i, ui in enumerate(c.get("unresolved_intent")):
|
|
5089
|
+
if not isinstance(ui, dict):
|
|
5090
|
+
errors.append("unresolved_intent[%d] must be an object with ir_region/decision"
|
|
5091
|
+
% i)
|
|
5092
|
+
if errors:
|
|
5093
|
+
return errors, advisory
|
|
5094
|
+
if c.get("_integrity") != _compile_seal(c):
|
|
5095
|
+
errors.append("compilation integrity seal does not match -- source/tests/manifest/"
|
|
5096
|
+
"unresolved_intent was hand-edited after production")
|
|
5097
|
+
# the compilation NAMES which IR it compiled; a stale or foreign ir_hash is refused --
|
|
5098
|
+
# a compilation cannot be measured against a graph this repo does not reproduce.
|
|
5099
|
+
ir_seal = ir_graph.get("_integrity")
|
|
5100
|
+
named = (c.get("canonical_ir") or {}).get("ir_hash")
|
|
5101
|
+
if named != ir_seal:
|
|
5102
|
+
errors.append("canonical_ir.ir_hash %s.. does not match the reference IR seal %s.. "
|
|
5103
|
+
"-- a stale or foreign IR is refused, never assumed"
|
|
5104
|
+
% (str(named)[:12], str(ir_seal)[:12]))
|
|
5105
|
+
node_ids = {nd["id"] for nd in ir_graph.get("nodes") or []}
|
|
5106
|
+
# units resolve on disk and their hashes match the bytes: the manifest cannot lie about
|
|
5107
|
+
# what was compiled.
|
|
5108
|
+
units = {}
|
|
5109
|
+
for section in ("source", "tests"):
|
|
5110
|
+
for u in c.get(section) or []:
|
|
5111
|
+
unit, want = u.get("unit"), u.get("sha256")
|
|
5112
|
+
if not unit:
|
|
5113
|
+
errors.append("%s entry without a unit path" % section)
|
|
5114
|
+
continue
|
|
5115
|
+
# source classification is sticky: a unit listed in BOTH source and tests stays
|
|
5116
|
+
# source, so the degeneracy detector (over source units) cannot be dodged by also
|
|
5117
|
+
# listing a source file under tests. Advisory-only, but the detector stays honest.
|
|
5118
|
+
if units.get(unit) != "source":
|
|
5119
|
+
units[unit] = section
|
|
5120
|
+
full = _contained_unit(base, unit)
|
|
5121
|
+
if full is None:
|
|
5122
|
+
errors.append("%s unit escapes the compilation directory -- a relative, "
|
|
5123
|
+
"contained path is required (the manifest references what was "
|
|
5124
|
+
"compiled): %s" % (section, unit))
|
|
5125
|
+
continue
|
|
5126
|
+
got = _sha256_file(full)
|
|
5127
|
+
if got is None:
|
|
5128
|
+
errors.append("%s unit missing on disk: %s" % (section, unit))
|
|
5129
|
+
elif got != want:
|
|
5130
|
+
errors.append("%s unit hash mismatch (manifest lies about the bytes): %s"
|
|
5131
|
+
% (section, unit))
|
|
5132
|
+
# every manifest id is an IR node (THE named mechanical violation); every manifest unit
|
|
5133
|
+
# is a real source/test unit.
|
|
5134
|
+
for entry in c.get("trace_manifest") or []:
|
|
5135
|
+
unit = entry.get("unit")
|
|
5136
|
+
if unit not in units:
|
|
5137
|
+
errors.append("trace_manifest unit is not a declared source/test unit: %s" % unit)
|
|
5138
|
+
for nid in entry.get("implements") or []:
|
|
5139
|
+
if nid not in node_ids:
|
|
5140
|
+
errors.append("trace_manifest implements an id that is not an IR node: %s"
|
|
5141
|
+
% nid)
|
|
5142
|
+
# unresolved_intent SHAPE blocks; its richness (count, specificity) is advisory only.
|
|
5143
|
+
for ui in c.get("unresolved_intent") or []:
|
|
5144
|
+
if not ui.get("ir_region") or not ui.get("decision"):
|
|
5145
|
+
errors.append("unresolved_intent entry missing ir_region or decision")
|
|
5146
|
+
# ---- ADVISORY (computed always, gates never) ----
|
|
5147
|
+
manifest_units = {e.get("unit") for e in c.get("trace_manifest") or []}
|
|
5148
|
+
per_unit = [len(e.get("implements") or []) for e in c.get("trace_manifest") or []]
|
|
5149
|
+
total_nodes = len(node_ids) or 1
|
|
5150
|
+
mean_fanout = (sum(per_unit) / len(per_unit)) if per_unit else 0.0
|
|
5151
|
+
covered = {nid for e in c.get("trace_manifest") or []
|
|
5152
|
+
for nid in (e.get("implements") or []) if nid in node_ids}
|
|
5153
|
+
# Degeneracy is a property of the SOURCE units: >=2 source units that EACH claim >= the
|
|
5154
|
+
# threshold share of all nodes -> the manifest cannot tell you which code implements
|
|
5155
|
+
# which intent (everything traces to everything). Min-based, not mean-based, and over
|
|
5156
|
+
# source only: one comprehensive source file legitimately implements a whole tiny
|
|
5157
|
+
# package, and tests naturally exercise everything, so neither is a degeneracy signal.
|
|
5158
|
+
source_units = {u for u, s in units.items() if s == "source"}
|
|
5159
|
+
src_fanout = [len(e.get("implements") or []) for e in c.get("trace_manifest") or []
|
|
5160
|
+
if e.get("unit") in source_units]
|
|
5161
|
+
advisory = {
|
|
5162
|
+
"trace_units": len(manifest_units),
|
|
5163
|
+
"mean_nodes_per_unit": round(mean_fanout, 3),
|
|
5164
|
+
"node_coverage": round(len(covered) / total_nodes, 3),
|
|
5165
|
+
"unexplained_units": sorted(u for u in units if u not in manifest_units),
|
|
5166
|
+
"unresolved_intent_count": len(c.get("unresolved_intent") or []),
|
|
5167
|
+
"degenerate": len(src_fanout) >= 2 and all(
|
|
5168
|
+
(pu / total_nodes) >= _COMPILE_DEGENERATE_FANOUT for pu in src_fanout),
|
|
5169
|
+
"empty_unresolved": len(c.get("unresolved_intent") or []) == 0,
|
|
5170
|
+
}
|
|
5171
|
+
return errors, advisory
|
|
5172
|
+
|
|
5173
|
+
|
|
5174
|
+
def _print_compile_advisory(advisory):
|
|
5175
|
+
if not advisory:
|
|
5176
|
+
return
|
|
5177
|
+
print(" advisory (never gates): coverage %.2f, mean %.2f nodes/unit, %d unresolved_intent%s"
|
|
5178
|
+
% (advisory.get("node_coverage", 0.0), advisory.get("mean_nodes_per_unit", 0.0),
|
|
5179
|
+
advisory.get("unresolved_intent_count", 0),
|
|
5180
|
+
", DEGENERATE manifest" if advisory.get("degenerate") else ""))
|
|
5181
|
+
if advisory.get("empty_unresolved"):
|
|
5182
|
+
print(" advisory: unresolved_intent is EMPTY -- suspicious (a compiler that made no "
|
|
5183
|
+
"choices is rare); reported, never blocked")
|
|
5184
|
+
for u in advisory.get("unexplained_units") or []:
|
|
5185
|
+
print(" advisory: %s has no trace_manifest entry -- unexplained by construction" % u)
|
|
5186
|
+
|
|
5187
|
+
|
|
5188
|
+
def cmd_compile_validate(args):
|
|
5189
|
+
ir_graph, ir_errors = _load_ir_at(args.ir)
|
|
5190
|
+
if ir_graph is None or ir_errors:
|
|
5191
|
+
for e in ir_errors:
|
|
5192
|
+
print("[qa_ledger] compile-validate: reference IR: %s" % e, file=sys.stderr)
|
|
5193
|
+
sys.exit(2)
|
|
5194
|
+
errors, advisory = _validate_compilation(args.compilation, ir_graph)
|
|
5195
|
+
if args.json:
|
|
5196
|
+
print(json.dumps({"compilation": args.compilation, "ir": args.ir,
|
|
5197
|
+
"valid": not errors, "errors": errors, "advisory": advisory},
|
|
5198
|
+
indent=2, ensure_ascii=False))
|
|
5199
|
+
elif errors:
|
|
5200
|
+
# diagnostics to stderr (Unix convention, and consistent with compile-ingest); the
|
|
5201
|
+
# machine signal is the exit code. stdout stays clean for the VALID payload path.
|
|
5202
|
+
print("COMPILE-VALIDATE %s: REFUSED (%d mechanical violation(s))"
|
|
5203
|
+
% (args.compilation, len(errors)), file=sys.stderr)
|
|
5204
|
+
for e in errors:
|
|
5205
|
+
print(" x %s" % e, file=sys.stderr)
|
|
5206
|
+
else:
|
|
5207
|
+
print("COMPILE-VALIDATE %s: VALID (contract conformant)" % args.compilation)
|
|
5208
|
+
_print_compile_advisory(advisory)
|
|
5209
|
+
sys.exit(2 if errors else 0)
|
|
5210
|
+
|
|
5211
|
+
|
|
5212
|
+
def cmd_compile_ingest(args):
|
|
5213
|
+
"""Record a VALIDATED compilation into the ledger (ADR-016). Ingesting an invalid
|
|
5214
|
+
compilation is a refusal. unresolved_intent becomes append-only, content-addressed
|
|
5215
|
+
UINT objects + an ISSUES-DEFERRED.md mirror (the house convention `fix` uses); the
|
|
5216
|
+
by-construction unexplained_code is the set of units with no trace_manifest entry."""
|
|
5217
|
+
ledger = _load(args.ledger)
|
|
5218
|
+
_repo_node(ledger, args.repo)
|
|
5219
|
+
repo_path = _scope_path(ledger, args.repo)
|
|
5220
|
+
ir_graph, ir_errors = _load_ir_at(args.ir)
|
|
5221
|
+
if ir_graph is None or ir_errors:
|
|
5222
|
+
for e in ir_errors:
|
|
5223
|
+
print("[qa_ledger] compile-ingest: reference IR: %s" % e, file=sys.stderr)
|
|
5224
|
+
sys.exit(2)
|
|
5225
|
+
errors, advisory = _validate_compilation(args.compilation, ir_graph)
|
|
5226
|
+
if errors:
|
|
5227
|
+
print("[qa_ledger] compile-ingest: REFUSED -- ingesting an invalid compilation is a "
|
|
5228
|
+
"refusal (%d mechanical violation(s)); run compile-validate." % len(errors),
|
|
5229
|
+
file=sys.stderr)
|
|
5230
|
+
for e in errors:
|
|
5231
|
+
print(" x %s" % e, file=sys.stderr)
|
|
5232
|
+
sys.exit(2)
|
|
5233
|
+
with open(args.compilation, encoding="utf-8-sig") as fh:
|
|
5234
|
+
c = json.load(fh)
|
|
5235
|
+
comp_seal = c.get("_integrity")
|
|
5236
|
+
uints, seen_uint = [], set()
|
|
5237
|
+
for ui in c.get("unresolved_intent") or []:
|
|
5238
|
+
uid = "UINT-" + hashlib.sha256(
|
|
5239
|
+
(ui.get("ir_region", "") + "\n" + ui.get("decision", "")).encode("utf-8")
|
|
5240
|
+
).hexdigest()[:12]
|
|
5241
|
+
# content-addressed: two entries that resolve to the same id ARE the same intent gap
|
|
5242
|
+
# (same ir_region + decision), deduped within this ingest just as across ingests --
|
|
5243
|
+
# otherwise ISSUES-DEFERRED and the ledger record carry the id twice.
|
|
5244
|
+
if uid in seen_uint:
|
|
5245
|
+
continue
|
|
5246
|
+
seen_uint.add(uid)
|
|
5247
|
+
uints.append({"id": uid, "ir_region": ui.get("ir_region"),
|
|
5248
|
+
"decision": ui.get("decision"), "rationale": ui.get("rationale", "")})
|
|
5249
|
+
comp_rec = {"id": comp_seal[:12], "repo": args.repo,
|
|
5250
|
+
"ir_hash": (c.get("canonical_ir") or {}).get("ir_hash"),
|
|
5251
|
+
"model": (c.get("compilation_report") or {}).get("model"),
|
|
5252
|
+
"target_stack": c.get("target_stack"), "seal": comp_seal,
|
|
5253
|
+
"unexplained_units": advisory.get("unexplained_units") or [],
|
|
5254
|
+
"node_coverage": advisory.get("node_coverage"),
|
|
5255
|
+
"unresolved_intent": uints, "at": _now()}
|
|
5256
|
+
comps = ledger.setdefault("compilations", [])
|
|
5257
|
+
# re-ingest is idempotent PER REPO: the seal is the identity within a repo, and a
|
|
5258
|
+
# byte-identical compilation has nothing to supersede. The compilations list is flat and
|
|
5259
|
+
# cross-repo, so the supersede check MUST be scoped by repo -- otherwise two repos that
|
|
5260
|
+
# legitimately produce the same compilation (a shared/small canonical package -- exactly
|
|
5261
|
+
# this milestone's own fixtures) collide, and the second repo's first ingest is dropped
|
|
5262
|
+
# as a false "superseded". A CHANGED compilation reseals -> a new record. Never a dup.
|
|
5263
|
+
superseded = any(x.get("seal") == comp_seal and x.get("repo") == args.repo for x in comps)
|
|
5264
|
+
if not superseded:
|
|
5265
|
+
comps.append(comp_rec)
|
|
5266
|
+
_save(args.ledger, ledger)
|
|
5267
|
+
new_items = []
|
|
5268
|
+
if uints:
|
|
5269
|
+
dpath = os.path.join(repo_path, ISSUES_DEFERRED_FILE)
|
|
5270
|
+
existing = ""
|
|
5271
|
+
if os.path.isfile(dpath):
|
|
5272
|
+
with open(dpath, encoding="utf-8-sig", errors="replace") as fh:
|
|
5273
|
+
existing = fh.read()
|
|
5274
|
+
add = [u for u in uints if u["id"] not in existing]
|
|
5275
|
+
if add:
|
|
5276
|
+
with open(dpath, "a", encoding="utf-8", newline="\n") as fh:
|
|
5277
|
+
if existing and not existing.endswith("\n"):
|
|
5278
|
+
fh.write("\n")
|
|
5279
|
+
for u in add:
|
|
5280
|
+
fh.write("- [ ] %s (unresolved_intent): %s -- the compiler decided "
|
|
5281
|
+
"'%s' on its own; a candidate canonical improvement (ADR-016)\n"
|
|
5282
|
+
% (u["id"], u["ir_region"], u["decision"]))
|
|
5283
|
+
new_items = [u["id"] for u in add]
|
|
5284
|
+
out = {"repo": args.repo, "compilation": comp_rec["id"], "superseded": superseded,
|
|
5285
|
+
"unresolved_intent": [u["id"] for u in uints],
|
|
5286
|
+
"issues_deferred_new": new_items,
|
|
5287
|
+
"unexplained_units": comp_rec["unexplained_units"]}
|
|
5288
|
+
if args.json:
|
|
5289
|
+
print(json.dumps(out, indent=2, ensure_ascii=False))
|
|
5290
|
+
else:
|
|
5291
|
+
print("COMPILE-INGEST %s: compilation %s%s"
|
|
5292
|
+
% (args.repo, comp_rec["id"],
|
|
5293
|
+
" (byte-identical to a prior ingest -- nothing superseded)"
|
|
5294
|
+
if superseded else ""))
|
|
5295
|
+
print(" %d unresolved_intent -> %d new %s item(s); %d unexplained unit(s)"
|
|
5296
|
+
% (len(uints), len(new_items), ISSUES_DEFERRED_FILE,
|
|
5297
|
+
len(comp_rec["unexplained_units"])))
|
|
5298
|
+
sys.exit(0)
|
|
5299
|
+
|
|
5300
|
+
|
|
5301
|
+
# --------------------------------------------------------------------------- #
|
|
5302
|
+
# bootstrap (Diamond M4: a bounded subsystem's identity is carried by its
|
|
5303
|
+
# canonical package + a WITHHELD oracle, not by its implementation. The oracle
|
|
5304
|
+
# runner is a measured fact and decides "same system"; variance is advisory
|
|
5305
|
+
# evidence that the implementations genuinely differ. ADR-017.)
|
|
5306
|
+
# --------------------------------------------------------------------------- #
|
|
5307
|
+
_BOOTSTRAP_CASE_TIMEOUT = 15 # a compiled hook must decide fast
|
|
5308
|
+
|
|
5309
|
+
|
|
5310
|
+
def _run_oracle_case(impl_path, case):
|
|
5311
|
+
"""Run ONE withheld oracle case against a compiled implementation: feed the case's stdin
|
|
5312
|
+
(raw_stdin verbatim if present, else json.dumps(payload)) to `python <impl>`, and compare
|
|
5313
|
+
the process exit code to `expected_exit`. Deterministic execution -- the oracle is a
|
|
5314
|
+
`measured` fact, never an LLM judgment. Returns a per-case result dict."""
|
|
5315
|
+
if "raw_stdin" in case:
|
|
5316
|
+
stdin = case["raw_stdin"]
|
|
5317
|
+
else:
|
|
5318
|
+
stdin = json.dumps(case.get("payload"))
|
|
5319
|
+
try:
|
|
5320
|
+
r = subprocess.run([sys.executable, impl_path], input=stdin, capture_output=True,
|
|
5321
|
+
text=True, encoding="utf-8", errors="replace",
|
|
5322
|
+
timeout=_BOOTSTRAP_CASE_TIMEOUT)
|
|
5323
|
+
got, err = r.returncode, None
|
|
5324
|
+
except subprocess.TimeoutExpired:
|
|
5325
|
+
got, err = None, "timeout"
|
|
5326
|
+
except OSError as exc:
|
|
5327
|
+
got, err = None, "could not run impl: %s" % exc
|
|
5328
|
+
want = case.get("expected_exit")
|
|
5329
|
+
return {"name": case.get("name"), "expected": want, "got": got,
|
|
5330
|
+
"ok": (err is None and got == want), "error": err}
|
|
5331
|
+
|
|
5332
|
+
|
|
5333
|
+
def cmd_bootstrap_oracle(args):
|
|
5334
|
+
"""Run a WITHHELD oracle suite (ADR-017) against a compiled implementation. The oracle
|
|
5335
|
+
predates and is physically separate from every compiler input; this runner is the
|
|
5336
|
+
maker!=checker wall made executable. Exit 0 iff every case matches its expected exit,
|
|
5337
|
+
else 1 -- a measured behavioural fact about whether this implementation is the same
|
|
5338
|
+
system. It runs the implementation as a subprocess and consults no model."""
|
|
5339
|
+
try:
|
|
5340
|
+
with open(args.oracle, encoding="utf-8-sig") as fh:
|
|
5341
|
+
oracle = json.load(fh)
|
|
5342
|
+
except (OSError, ValueError) as exc:
|
|
5343
|
+
print("[qa_ledger] bootstrap-oracle: unreadable oracle %s: %s" % (args.oracle, exc),
|
|
5344
|
+
file=sys.stderr)
|
|
5345
|
+
sys.exit(2)
|
|
5346
|
+
cases = oracle.get("cases")
|
|
5347
|
+
if not isinstance(cases, list) or not cases:
|
|
5348
|
+
print("[qa_ledger] bootstrap-oracle: oracle has no cases", file=sys.stderr)
|
|
5349
|
+
sys.exit(2)
|
|
5350
|
+
if not os.path.isfile(args.impl):
|
|
5351
|
+
print("[qa_ledger] bootstrap-oracle: no implementation at %s" % args.impl,
|
|
5352
|
+
file=sys.stderr)
|
|
5353
|
+
sys.exit(2)
|
|
5354
|
+
results = [_run_oracle_case(args.impl, c) for c in cases]
|
|
5355
|
+
passed = sum(1 for r in results if r["ok"])
|
|
5356
|
+
failed = [r for r in results if not r["ok"]]
|
|
5357
|
+
report = {"impl": args.impl, "oracle": args.oracle, "total": len(results),
|
|
5358
|
+
"passed": passed, "failed": len(failed),
|
|
5359
|
+
"oracle_green": not failed, "results": results}
|
|
5360
|
+
if args.ledger and args.repo:
|
|
5361
|
+
ledger = _load(args.ledger)
|
|
5362
|
+
_repo_node(ledger, args.repo)
|
|
5363
|
+
rec = {"impl": os.path.basename(args.impl), "oracle": os.path.basename(args.oracle),
|
|
5364
|
+
"total": len(results), "passed": passed, "failed": len(failed),
|
|
5365
|
+
"oracle_green": not failed,
|
|
5366
|
+
"failing": [r["name"] for r in failed], "at": _now()}
|
|
5367
|
+
ledger.setdefault("bootstrap_oracle", []).append(rec)
|
|
5368
|
+
_save(args.ledger, ledger)
|
|
5369
|
+
if args.json:
|
|
5370
|
+
print(json.dumps(report, indent=2, ensure_ascii=False))
|
|
5371
|
+
else:
|
|
5372
|
+
print("BOOTSTRAP-ORACLE %s: %d/%d cases pass -- %s"
|
|
5373
|
+
% (os.path.basename(args.impl), passed, len(results),
|
|
5374
|
+
"ORACLE GREEN (same system on this suite)" if not failed
|
|
5375
|
+
else "ORACLE RED (%d divergence(s))" % len(failed)))
|
|
5376
|
+
for r in failed:
|
|
5377
|
+
print(" x %s: expected exit %s, got %s%s"
|
|
5378
|
+
% (r["name"], r["expected"], r["got"],
|
|
5379
|
+
" (%s)" % r["error"] if r["error"] else ""))
|
|
5380
|
+
sys.exit(0 if not failed else 1)
|
|
5381
|
+
|
|
5382
|
+
|
|
5383
|
+
def _impl_metrics(path):
|
|
5384
|
+
"""Structural fingerprint of one implementation: physical LOC, AST node count, function
|
|
5385
|
+
and class counts, and the set of imported top-level modules. Deterministic; no judgment."""
|
|
5386
|
+
try:
|
|
5387
|
+
with open(path, encoding="utf-8", errors="replace") as fh:
|
|
5388
|
+
src = fh.read()
|
|
5389
|
+
except OSError as exc:
|
|
5390
|
+
return {"path": path, "error": "unreadable: %s" % exc}
|
|
5391
|
+
loc = sum(1 for ln in src.splitlines() if ln.strip())
|
|
5392
|
+
try:
|
|
5393
|
+
tree = ast.parse(src)
|
|
5394
|
+
except SyntaxError as exc:
|
|
5395
|
+
return {"path": path, "loc": loc, "error": "unparseable: %s" % exc}
|
|
5396
|
+
funcs = classes = nodes = 0
|
|
5397
|
+
imports = set()
|
|
5398
|
+
for nd in ast.walk(tree):
|
|
5399
|
+
nodes += 1
|
|
5400
|
+
if isinstance(nd, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
5401
|
+
funcs += 1
|
|
5402
|
+
elif isinstance(nd, ast.ClassDef):
|
|
5403
|
+
classes += 1
|
|
5404
|
+
elif isinstance(nd, ast.Import):
|
|
5405
|
+
for a in nd.names:
|
|
5406
|
+
imports.add(a.name.split(".")[0])
|
|
5407
|
+
elif isinstance(nd, ast.ImportFrom):
|
|
5408
|
+
if nd.module:
|
|
5409
|
+
imports.add(nd.module.split(".")[0])
|
|
5410
|
+
return {"path": path, "loc": loc, "ast_nodes": nodes, "functions": funcs,
|
|
5411
|
+
"classes": classes, "imports": sorted(imports),
|
|
5412
|
+
"sha256": hashlib.sha256(src.encode("utf-8")).hexdigest()}
|
|
5413
|
+
|
|
5414
|
+
|
|
5415
|
+
def cmd_bootstrap_variance(args):
|
|
5416
|
+
"""Prove independent compilations of the same canonical package genuinely DIFFER (ADR-017).
|
|
5417
|
+
Reports per-implementation structural metrics and pairwise divergence. ADVISORY: variance
|
|
5418
|
+
is evidence the implementations differ, never a certificate of 'same system' (only the
|
|
5419
|
+
oracle certifies that) and never a gate -- it cannot change an exit code."""
|
|
5420
|
+
metrics = [_impl_metrics(p) for p in args.impls]
|
|
5421
|
+
pairs = []
|
|
5422
|
+
good = [m for m in metrics if "error" not in m]
|
|
5423
|
+
for i in range(len(good)):
|
|
5424
|
+
for j in range(i + 1, len(good)):
|
|
5425
|
+
a, b = good[i], good[j]
|
|
5426
|
+
ia, ib = set(a["imports"]), set(b["imports"])
|
|
5427
|
+
jac = (len(ia & ib) / len(ia | ib)) if (ia or ib) else 1.0
|
|
5428
|
+
pairs.append({"a": os.path.basename(a["path"]), "b": os.path.basename(b["path"]),
|
|
5429
|
+
"byte_identical": a["sha256"] == b["sha256"],
|
|
5430
|
+
"loc_delta": abs(a["loc"] - b["loc"]),
|
|
5431
|
+
"ast_node_delta": abs(a["ast_nodes"] - b["ast_nodes"]),
|
|
5432
|
+
"function_delta": abs(a["functions"] - b["functions"]),
|
|
5433
|
+
"import_jaccard": round(jac, 3)})
|
|
5434
|
+
all_distinct = all(not p["byte_identical"] for p in pairs) if pairs else None
|
|
5435
|
+
report = {"implementations": metrics, "pairs": pairs, "all_distinct": all_distinct,
|
|
5436
|
+
"advisory": True}
|
|
5437
|
+
if args.json:
|
|
5438
|
+
print(json.dumps(report, indent=2, ensure_ascii=False))
|
|
5439
|
+
else:
|
|
5440
|
+
for m in metrics:
|
|
5441
|
+
if "error" in m:
|
|
5442
|
+
print("VARIANCE %s: %s" % (os.path.basename(m["path"]), m["error"]))
|
|
5443
|
+
else:
|
|
5444
|
+
print("VARIANCE %s: %d loc, %d ast-nodes, %d fn, %d cls, imports=%s"
|
|
5445
|
+
% (os.path.basename(m["path"]), m["loc"], m["ast_nodes"],
|
|
5446
|
+
m["functions"], m["classes"], ",".join(m["imports"]) or "-"))
|
|
5447
|
+
for p in pairs:
|
|
5448
|
+
print(" %s vs %s: %s | dloc=%d dnodes=%d import_jaccard=%.2f"
|
|
5449
|
+
% (p["a"], p["b"], "IDENTICAL" if p["byte_identical"] else "distinct",
|
|
5450
|
+
p["loc_delta"], p["ast_node_delta"], p["import_jaccard"]))
|
|
5451
|
+
if all_distinct is not None:
|
|
5452
|
+
print(" all implementations distinct: %s (advisory, never gates)"
|
|
5453
|
+
% ("yes" if all_distinct else "NO -- convergence, a weak result"))
|
|
5454
|
+
sys.exit(0)
|
|
5455
|
+
|
|
5456
|
+
|
|
4968
5457
|
# --------------------------------------------------------------------------- #
|
|
4969
5458
|
# facts (T0 / SYSTEM-FACTS: public claims become compiled artifacts of repo
|
|
4970
5459
|
# facts -- Diamond applied to Diamond. ADR-012.)
|
|
@@ -9035,6 +9524,48 @@ def build_parser():
|
|
|
9035
9524
|
pir.add_argument("--repo", required=True)
|
|
9036
9525
|
pir.set_defaults(func=cmd_ir_render)
|
|
9037
9526
|
|
|
9527
|
+
pcmv = sub.add_parser(
|
|
9528
|
+
"compile-validate",
|
|
9529
|
+
help="validate a COMPILATION.json against a reference IR (ADR-016); only mechanical "
|
|
9530
|
+
"violations gate, degeneracy stats are advisory and NEVER block")
|
|
9531
|
+
pcmv.add_argument("--ir", required=True,
|
|
9532
|
+
help="the reference IR.json the compilation targets")
|
|
9533
|
+
pcmv.add_argument("--compilation", required=True, help="path to COMPILATION.json")
|
|
9534
|
+
pcmv.add_argument("--json", action="store_true")
|
|
9535
|
+
pcmv.set_defaults(func=cmd_compile_validate)
|
|
9536
|
+
|
|
9537
|
+
pcmi = sub.add_parser(
|
|
9538
|
+
"compile-ingest",
|
|
9539
|
+
help="record a VALIDATED compilation into the ledger (ADR-016): by-construction "
|
|
9540
|
+
"unexplained_code + unresolved_intent as append-only UINT objects + backlog")
|
|
9541
|
+
pcmi.add_argument("--ledger", default="QA-LEDGER.json")
|
|
9542
|
+
pcmi.add_argument("--repo", required=True)
|
|
9543
|
+
pcmi.add_argument("--ir", required=True,
|
|
9544
|
+
help="the reference IR.json the compilation targets")
|
|
9545
|
+
pcmi.add_argument("--compilation", required=True, help="path to COMPILATION.json")
|
|
9546
|
+
pcmi.add_argument("--json", action="store_true")
|
|
9547
|
+
pcmi.set_defaults(func=cmd_compile_ingest)
|
|
9548
|
+
|
|
9549
|
+
pbo = sub.add_parser(
|
|
9550
|
+
"bootstrap-oracle",
|
|
9551
|
+
help="run a WITHHELD oracle suite against a compiled implementation (ADR-017); exit 0 "
|
|
9552
|
+
"iff every case matches its expected exit -- the maker!=checker wall, executable")
|
|
9553
|
+
pbo.add_argument("--impl", required=True, help="the compiled implementation to run")
|
|
9554
|
+
pbo.add_argument("--oracle", required=True, help="the withheld ORACLE.json case suite")
|
|
9555
|
+
pbo.add_argument("--ledger", default=None, help="optional: persist the measured result")
|
|
9556
|
+
pbo.add_argument("--repo", default=None, help="repo scope when --ledger is given")
|
|
9557
|
+
pbo.add_argument("--json", action="store_true")
|
|
9558
|
+
pbo.set_defaults(func=cmd_bootstrap_oracle)
|
|
9559
|
+
|
|
9560
|
+
pbv = sub.add_parser(
|
|
9561
|
+
"bootstrap-variance",
|
|
9562
|
+
help="structural metrics + pairwise divergence proving independent compilations "
|
|
9563
|
+
"genuinely differ (ADR-017); ADVISORY evidence, never a gate")
|
|
9564
|
+
pbv.add_argument("--impls", required=True, nargs="+",
|
|
9565
|
+
help="two or more compiled implementations to compare")
|
|
9566
|
+
pbv.add_argument("--json", action="store_true")
|
|
9567
|
+
pbv.set_defaults(func=cmd_bootstrap_variance)
|
|
9568
|
+
|
|
9038
9569
|
pcr = sub.add_parser("cleanroom",
|
|
9039
9570
|
help="run a command against a CLEAN checkout of one commit in a throwaway worktree (ADR-008)")
|
|
9040
9571
|
pcr.add_argument("--ledger", default="QA-LEDGER.json")
|
|
@@ -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.
|
|
4
|
+
"version": "1.74.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,
|
|
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, 46 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"
|
package/uscha-kit/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# uscha-kit
|
|
2
2
|
|
|
3
|
-
**Kit version:** v1.
|
|
3
|
+
**Kit version:** v1.74.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.74.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"AC-BS-01": true, "AC-BS-02": true, "AC-BS-03": true, "AC-BS-04": true, "AC-BS-05": true, "AC-BS-06": true}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"AC-CC-01": true, "AC-CC-02": true, "AC-CC-03": true, "AC-CC-04": true, "AC-CC-05": true, "AC-CC-06": true, "AC-CC-07": true}
|
|
@@ -4965,6 +4965,495 @@ def cmd_ir_render(args):
|
|
|
4965
4965
|
sys.exit(0)
|
|
4966
4966
|
|
|
4967
4967
|
|
|
4968
|
+
# --------------------------------------------------------------------------- #
|
|
4969
|
+
# compiler contract (Diamond M3: the LLM is a compiler with a validated output
|
|
4970
|
+
# contract. The engine VALIDATES and INGESTS compilations; it NEVER compiles and
|
|
4971
|
+
# never calls a model. Only mechanical violations gate; every statistic is
|
|
4972
|
+
# advisory (INV-ADVISORY-01). ADR-016.)
|
|
4973
|
+
# --------------------------------------------------------------------------- #
|
|
4974
|
+
COMPILE_SCHEMA = "compile/0.1"
|
|
4975
|
+
COMPILE_REQUIRED = ("schema_version", "canonical_ir", "target_stack", "source",
|
|
4976
|
+
"tests", "trace_manifest", "unresolved_intent",
|
|
4977
|
+
"compilation_report")
|
|
4978
|
+
# The seal covers the load-bearing contract, NOT compilation_report: model, versions and
|
|
4979
|
+
# timestamps legitimately vary and never change WHAT was compiled. A hand edit of the
|
|
4980
|
+
# substance (source/tests/manifest/unresolved_intent) after production must trip the seal.
|
|
4981
|
+
COMPILE_SEALED = ("schema_version", "canonical_ir", "target_stack",
|
|
4982
|
+
"implementation_constraints", "source", "tests",
|
|
4983
|
+
"trace_manifest", "unresolved_intent")
|
|
4984
|
+
# Advisory degeneracy dial: a manifest of >=2 units where EVERY unit claims >= this share
|
|
4985
|
+
# of ALL IR nodes is "everything traces to everything" -- no unit discriminates. ADVISORY
|
|
4986
|
+
# ONLY: printed, never gates. The exact value is a reporting choice, not a contract,
|
|
4987
|
+
# precisely because it can never block (a threshold on a smell would be a judgment).
|
|
4988
|
+
_COMPILE_DEGENERATE_FANOUT = 0.8
|
|
4989
|
+
|
|
4990
|
+
|
|
4991
|
+
def _compile_seal(c):
|
|
4992
|
+
return _integrity_hash({k: c.get(k) for k in COMPILE_SEALED})
|
|
4993
|
+
|
|
4994
|
+
|
|
4995
|
+
def _sha256_file(path):
|
|
4996
|
+
try:
|
|
4997
|
+
with open(path, "rb") as fh:
|
|
4998
|
+
return hashlib.sha256(fh.read()).hexdigest()
|
|
4999
|
+
except OSError:
|
|
5000
|
+
return None
|
|
5001
|
+
|
|
5002
|
+
|
|
5003
|
+
def _contained_unit(base, unit):
|
|
5004
|
+
"""A compilation's units must be RELATIVE paths CONTAINED within the compilation
|
|
5005
|
+
directory: the manifest references what was compiled, and what was compiled lives with
|
|
5006
|
+
the compilation. An absolute path or a `..` escape lets a manifest name any file on the
|
|
5007
|
+
filesystem as a "source" unit and pass on that file's hash -- exactly the "manifest
|
|
5008
|
+
cannot lie about what was compiled" guarantee, defeated. Returns the resolved path, or
|
|
5009
|
+
None if the unit is absolute or escapes `base`. Both sides are `realpath`-normalized
|
|
5010
|
+
before comparison -- the Windows 8.3 short-path trap this repo already paid for once
|
|
5011
|
+
(a file INSIDE a tree judged outside it) applies to any containment check."""
|
|
5012
|
+
if os.path.isabs(unit):
|
|
5013
|
+
return None
|
|
5014
|
+
full = os.path.realpath(os.path.join(base, unit.replace("/", os.sep)))
|
|
5015
|
+
root = os.path.realpath(base)
|
|
5016
|
+
if full == root or full.startswith(root + os.sep):
|
|
5017
|
+
return full
|
|
5018
|
+
return None
|
|
5019
|
+
|
|
5020
|
+
|
|
5021
|
+
def _load_ir_at(path):
|
|
5022
|
+
"""Strict IR loader for an ARBITRARY IR.json. The repo's own ir/ is gitignored (a
|
|
5023
|
+
regenerable index), so the M3 reference IR is a committed fixture loaded here with the
|
|
5024
|
+
same posture as _load_ir: an unknown schema or a broken/hand-edited seal is refused,
|
|
5025
|
+
never mis-read. Returns (graph, errors); graph None when the file is absent."""
|
|
5026
|
+
if not os.path.isfile(path):
|
|
5027
|
+
return None, ["no reference IR at %s" % path]
|
|
5028
|
+
try:
|
|
5029
|
+
with open(path, encoding="utf-8-sig") as fh:
|
|
5030
|
+
g = json.load(fh)
|
|
5031
|
+
except (OSError, ValueError) as exc:
|
|
5032
|
+
return {}, ["unreadable: %s" % exc]
|
|
5033
|
+
if g.get("schema_version") != IR_SCHEMA:
|
|
5034
|
+
return g, ["schema_version %r != %r (an IR version this engine does not know is "
|
|
5035
|
+
"refused, not read)" % (g.get("schema_version"), IR_SCHEMA)]
|
|
5036
|
+
if not isinstance(g.get("nodes"), list) or not isinstance(g.get("edges"), list):
|
|
5037
|
+
return g, ["nodes/edges missing or not lists"]
|
|
5038
|
+
if g.get("_integrity") != _ir_seal(g):
|
|
5039
|
+
return g, ["reference IR integrity seal does not match -- it was hand-edited "
|
|
5040
|
+
"(regenerate via ir-extract)"]
|
|
5041
|
+
return g, []
|
|
5042
|
+
|
|
5043
|
+
|
|
5044
|
+
def _validate_compilation(comp_path, ir_graph):
|
|
5045
|
+
"""The deterministic checker (ADR-016). Returns (blocking_errors, advisory).
|
|
5046
|
+
|
|
5047
|
+
BLOCKS only on FACTS: unknown schema, a missing/mistyped section, a broken seal, an
|
|
5048
|
+
ir_hash that does not match the reference IR, a trace_manifest id that is not an IR
|
|
5049
|
+
node, a unit whose file is absent or whose hash does not match the bytes on disk, a
|
|
5050
|
+
malformed unresolved_intent entry. Every STATISTIC (fan-out degeneracy, empty/generic
|
|
5051
|
+
unresolved_intent, coverage) is advisory and can NEVER change the outcome -- a
|
|
5052
|
+
threshold on a smell is a judgment, and no judgment gates (INV-ADVISORY-01)."""
|
|
5053
|
+
errors, advisory = [], {}
|
|
5054
|
+
base = os.path.dirname(os.path.abspath(comp_path))
|
|
5055
|
+
try:
|
|
5056
|
+
with open(comp_path, encoding="utf-8-sig") as fh:
|
|
5057
|
+
c = json.load(fh)
|
|
5058
|
+
except (OSError, ValueError) as exc:
|
|
5059
|
+
return ["unreadable compilation: %s" % exc], advisory
|
|
5060
|
+
if c.get("schema_version") != COMPILE_SCHEMA:
|
|
5061
|
+
return ["schema_version %r != %r (a contract version this engine does not know is "
|
|
5062
|
+
"refused, not read)" % (c.get("schema_version"), COMPILE_SCHEMA)], advisory
|
|
5063
|
+
for k in COMPILE_REQUIRED:
|
|
5064
|
+
if k not in c:
|
|
5065
|
+
errors.append("required section missing: %s" % k)
|
|
5066
|
+
if errors:
|
|
5067
|
+
return errors, advisory
|
|
5068
|
+
for k, typ in (("source", list), ("tests", list), ("trace_manifest", list),
|
|
5069
|
+
("unresolved_intent", list), ("canonical_ir", dict),
|
|
5070
|
+
("compilation_report", dict)):
|
|
5071
|
+
if not isinstance(c.get(k), typ):
|
|
5072
|
+
errors.append("%s must be a %s" % (k, typ.__name__))
|
|
5073
|
+
if errors:
|
|
5074
|
+
return errors, advisory
|
|
5075
|
+
# ELEMENT shapes, checked before any `.get` on them: an adversarial/buggy compiler that
|
|
5076
|
+
# emits a list of strings (or a non-list `implements`) is a mechanical violation -> exit
|
|
5077
|
+
# 2 with a named fault, NEVER an AttributeError traceback (exit 1). This is the trust
|
|
5078
|
+
# boundary the contract exists to defend; the loops below assume dict elements.
|
|
5079
|
+
for k in ("source", "tests"):
|
|
5080
|
+
for i, u in enumerate(c.get(k)):
|
|
5081
|
+
if not isinstance(u, dict):
|
|
5082
|
+
errors.append("%s[%d] must be an object with unit/sha256" % (k, i))
|
|
5083
|
+
for i, e in enumerate(c.get("trace_manifest")):
|
|
5084
|
+
if not isinstance(e, dict):
|
|
5085
|
+
errors.append("trace_manifest[%d] must be an object with unit/implements" % i)
|
|
5086
|
+
elif not isinstance(e.get("implements"), list):
|
|
5087
|
+
errors.append("trace_manifest[%d].implements must be a list of IR node ids" % i)
|
|
5088
|
+
for i, ui in enumerate(c.get("unresolved_intent")):
|
|
5089
|
+
if not isinstance(ui, dict):
|
|
5090
|
+
errors.append("unresolved_intent[%d] must be an object with ir_region/decision"
|
|
5091
|
+
% i)
|
|
5092
|
+
if errors:
|
|
5093
|
+
return errors, advisory
|
|
5094
|
+
if c.get("_integrity") != _compile_seal(c):
|
|
5095
|
+
errors.append("compilation integrity seal does not match -- source/tests/manifest/"
|
|
5096
|
+
"unresolved_intent was hand-edited after production")
|
|
5097
|
+
# the compilation NAMES which IR it compiled; a stale or foreign ir_hash is refused --
|
|
5098
|
+
# a compilation cannot be measured against a graph this repo does not reproduce.
|
|
5099
|
+
ir_seal = ir_graph.get("_integrity")
|
|
5100
|
+
named = (c.get("canonical_ir") or {}).get("ir_hash")
|
|
5101
|
+
if named != ir_seal:
|
|
5102
|
+
errors.append("canonical_ir.ir_hash %s.. does not match the reference IR seal %s.. "
|
|
5103
|
+
"-- a stale or foreign IR is refused, never assumed"
|
|
5104
|
+
% (str(named)[:12], str(ir_seal)[:12]))
|
|
5105
|
+
node_ids = {nd["id"] for nd in ir_graph.get("nodes") or []}
|
|
5106
|
+
# units resolve on disk and their hashes match the bytes: the manifest cannot lie about
|
|
5107
|
+
# what was compiled.
|
|
5108
|
+
units = {}
|
|
5109
|
+
for section in ("source", "tests"):
|
|
5110
|
+
for u in c.get(section) or []:
|
|
5111
|
+
unit, want = u.get("unit"), u.get("sha256")
|
|
5112
|
+
if not unit:
|
|
5113
|
+
errors.append("%s entry without a unit path" % section)
|
|
5114
|
+
continue
|
|
5115
|
+
# source classification is sticky: a unit listed in BOTH source and tests stays
|
|
5116
|
+
# source, so the degeneracy detector (over source units) cannot be dodged by also
|
|
5117
|
+
# listing a source file under tests. Advisory-only, but the detector stays honest.
|
|
5118
|
+
if units.get(unit) != "source":
|
|
5119
|
+
units[unit] = section
|
|
5120
|
+
full = _contained_unit(base, unit)
|
|
5121
|
+
if full is None:
|
|
5122
|
+
errors.append("%s unit escapes the compilation directory -- a relative, "
|
|
5123
|
+
"contained path is required (the manifest references what was "
|
|
5124
|
+
"compiled): %s" % (section, unit))
|
|
5125
|
+
continue
|
|
5126
|
+
got = _sha256_file(full)
|
|
5127
|
+
if got is None:
|
|
5128
|
+
errors.append("%s unit missing on disk: %s" % (section, unit))
|
|
5129
|
+
elif got != want:
|
|
5130
|
+
errors.append("%s unit hash mismatch (manifest lies about the bytes): %s"
|
|
5131
|
+
% (section, unit))
|
|
5132
|
+
# every manifest id is an IR node (THE named mechanical violation); every manifest unit
|
|
5133
|
+
# is a real source/test unit.
|
|
5134
|
+
for entry in c.get("trace_manifest") or []:
|
|
5135
|
+
unit = entry.get("unit")
|
|
5136
|
+
if unit not in units:
|
|
5137
|
+
errors.append("trace_manifest unit is not a declared source/test unit: %s" % unit)
|
|
5138
|
+
for nid in entry.get("implements") or []:
|
|
5139
|
+
if nid not in node_ids:
|
|
5140
|
+
errors.append("trace_manifest implements an id that is not an IR node: %s"
|
|
5141
|
+
% nid)
|
|
5142
|
+
# unresolved_intent SHAPE blocks; its richness (count, specificity) is advisory only.
|
|
5143
|
+
for ui in c.get("unresolved_intent") or []:
|
|
5144
|
+
if not ui.get("ir_region") or not ui.get("decision"):
|
|
5145
|
+
errors.append("unresolved_intent entry missing ir_region or decision")
|
|
5146
|
+
# ---- ADVISORY (computed always, gates never) ----
|
|
5147
|
+
manifest_units = {e.get("unit") for e in c.get("trace_manifest") or []}
|
|
5148
|
+
per_unit = [len(e.get("implements") or []) for e in c.get("trace_manifest") or []]
|
|
5149
|
+
total_nodes = len(node_ids) or 1
|
|
5150
|
+
mean_fanout = (sum(per_unit) / len(per_unit)) if per_unit else 0.0
|
|
5151
|
+
covered = {nid for e in c.get("trace_manifest") or []
|
|
5152
|
+
for nid in (e.get("implements") or []) if nid in node_ids}
|
|
5153
|
+
# Degeneracy is a property of the SOURCE units: >=2 source units that EACH claim >= the
|
|
5154
|
+
# threshold share of all nodes -> the manifest cannot tell you which code implements
|
|
5155
|
+
# which intent (everything traces to everything). Min-based, not mean-based, and over
|
|
5156
|
+
# source only: one comprehensive source file legitimately implements a whole tiny
|
|
5157
|
+
# package, and tests naturally exercise everything, so neither is a degeneracy signal.
|
|
5158
|
+
source_units = {u for u, s in units.items() if s == "source"}
|
|
5159
|
+
src_fanout = [len(e.get("implements") or []) for e in c.get("trace_manifest") or []
|
|
5160
|
+
if e.get("unit") in source_units]
|
|
5161
|
+
advisory = {
|
|
5162
|
+
"trace_units": len(manifest_units),
|
|
5163
|
+
"mean_nodes_per_unit": round(mean_fanout, 3),
|
|
5164
|
+
"node_coverage": round(len(covered) / total_nodes, 3),
|
|
5165
|
+
"unexplained_units": sorted(u for u in units if u not in manifest_units),
|
|
5166
|
+
"unresolved_intent_count": len(c.get("unresolved_intent") or []),
|
|
5167
|
+
"degenerate": len(src_fanout) >= 2 and all(
|
|
5168
|
+
(pu / total_nodes) >= _COMPILE_DEGENERATE_FANOUT for pu in src_fanout),
|
|
5169
|
+
"empty_unresolved": len(c.get("unresolved_intent") or []) == 0,
|
|
5170
|
+
}
|
|
5171
|
+
return errors, advisory
|
|
5172
|
+
|
|
5173
|
+
|
|
5174
|
+
def _print_compile_advisory(advisory):
|
|
5175
|
+
if not advisory:
|
|
5176
|
+
return
|
|
5177
|
+
print(" advisory (never gates): coverage %.2f, mean %.2f nodes/unit, %d unresolved_intent%s"
|
|
5178
|
+
% (advisory.get("node_coverage", 0.0), advisory.get("mean_nodes_per_unit", 0.0),
|
|
5179
|
+
advisory.get("unresolved_intent_count", 0),
|
|
5180
|
+
", DEGENERATE manifest" if advisory.get("degenerate") else ""))
|
|
5181
|
+
if advisory.get("empty_unresolved"):
|
|
5182
|
+
print(" advisory: unresolved_intent is EMPTY -- suspicious (a compiler that made no "
|
|
5183
|
+
"choices is rare); reported, never blocked")
|
|
5184
|
+
for u in advisory.get("unexplained_units") or []:
|
|
5185
|
+
print(" advisory: %s has no trace_manifest entry -- unexplained by construction" % u)
|
|
5186
|
+
|
|
5187
|
+
|
|
5188
|
+
def cmd_compile_validate(args):
|
|
5189
|
+
ir_graph, ir_errors = _load_ir_at(args.ir)
|
|
5190
|
+
if ir_graph is None or ir_errors:
|
|
5191
|
+
for e in ir_errors:
|
|
5192
|
+
print("[qa_ledger] compile-validate: reference IR: %s" % e, file=sys.stderr)
|
|
5193
|
+
sys.exit(2)
|
|
5194
|
+
errors, advisory = _validate_compilation(args.compilation, ir_graph)
|
|
5195
|
+
if args.json:
|
|
5196
|
+
print(json.dumps({"compilation": args.compilation, "ir": args.ir,
|
|
5197
|
+
"valid": not errors, "errors": errors, "advisory": advisory},
|
|
5198
|
+
indent=2, ensure_ascii=False))
|
|
5199
|
+
elif errors:
|
|
5200
|
+
# diagnostics to stderr (Unix convention, and consistent with compile-ingest); the
|
|
5201
|
+
# machine signal is the exit code. stdout stays clean for the VALID payload path.
|
|
5202
|
+
print("COMPILE-VALIDATE %s: REFUSED (%d mechanical violation(s))"
|
|
5203
|
+
% (args.compilation, len(errors)), file=sys.stderr)
|
|
5204
|
+
for e in errors:
|
|
5205
|
+
print(" x %s" % e, file=sys.stderr)
|
|
5206
|
+
else:
|
|
5207
|
+
print("COMPILE-VALIDATE %s: VALID (contract conformant)" % args.compilation)
|
|
5208
|
+
_print_compile_advisory(advisory)
|
|
5209
|
+
sys.exit(2 if errors else 0)
|
|
5210
|
+
|
|
5211
|
+
|
|
5212
|
+
def cmd_compile_ingest(args):
|
|
5213
|
+
"""Record a VALIDATED compilation into the ledger (ADR-016). Ingesting an invalid
|
|
5214
|
+
compilation is a refusal. unresolved_intent becomes append-only, content-addressed
|
|
5215
|
+
UINT objects + an ISSUES-DEFERRED.md mirror (the house convention `fix` uses); the
|
|
5216
|
+
by-construction unexplained_code is the set of units with no trace_manifest entry."""
|
|
5217
|
+
ledger = _load(args.ledger)
|
|
5218
|
+
_repo_node(ledger, args.repo)
|
|
5219
|
+
repo_path = _scope_path(ledger, args.repo)
|
|
5220
|
+
ir_graph, ir_errors = _load_ir_at(args.ir)
|
|
5221
|
+
if ir_graph is None or ir_errors:
|
|
5222
|
+
for e in ir_errors:
|
|
5223
|
+
print("[qa_ledger] compile-ingest: reference IR: %s" % e, file=sys.stderr)
|
|
5224
|
+
sys.exit(2)
|
|
5225
|
+
errors, advisory = _validate_compilation(args.compilation, ir_graph)
|
|
5226
|
+
if errors:
|
|
5227
|
+
print("[qa_ledger] compile-ingest: REFUSED -- ingesting an invalid compilation is a "
|
|
5228
|
+
"refusal (%d mechanical violation(s)); run compile-validate." % len(errors),
|
|
5229
|
+
file=sys.stderr)
|
|
5230
|
+
for e in errors:
|
|
5231
|
+
print(" x %s" % e, file=sys.stderr)
|
|
5232
|
+
sys.exit(2)
|
|
5233
|
+
with open(args.compilation, encoding="utf-8-sig") as fh:
|
|
5234
|
+
c = json.load(fh)
|
|
5235
|
+
comp_seal = c.get("_integrity")
|
|
5236
|
+
uints, seen_uint = [], set()
|
|
5237
|
+
for ui in c.get("unresolved_intent") or []:
|
|
5238
|
+
uid = "UINT-" + hashlib.sha256(
|
|
5239
|
+
(ui.get("ir_region", "") + "\n" + ui.get("decision", "")).encode("utf-8")
|
|
5240
|
+
).hexdigest()[:12]
|
|
5241
|
+
# content-addressed: two entries that resolve to the same id ARE the same intent gap
|
|
5242
|
+
# (same ir_region + decision), deduped within this ingest just as across ingests --
|
|
5243
|
+
# otherwise ISSUES-DEFERRED and the ledger record carry the id twice.
|
|
5244
|
+
if uid in seen_uint:
|
|
5245
|
+
continue
|
|
5246
|
+
seen_uint.add(uid)
|
|
5247
|
+
uints.append({"id": uid, "ir_region": ui.get("ir_region"),
|
|
5248
|
+
"decision": ui.get("decision"), "rationale": ui.get("rationale", "")})
|
|
5249
|
+
comp_rec = {"id": comp_seal[:12], "repo": args.repo,
|
|
5250
|
+
"ir_hash": (c.get("canonical_ir") or {}).get("ir_hash"),
|
|
5251
|
+
"model": (c.get("compilation_report") or {}).get("model"),
|
|
5252
|
+
"target_stack": c.get("target_stack"), "seal": comp_seal,
|
|
5253
|
+
"unexplained_units": advisory.get("unexplained_units") or [],
|
|
5254
|
+
"node_coverage": advisory.get("node_coverage"),
|
|
5255
|
+
"unresolved_intent": uints, "at": _now()}
|
|
5256
|
+
comps = ledger.setdefault("compilations", [])
|
|
5257
|
+
# re-ingest is idempotent PER REPO: the seal is the identity within a repo, and a
|
|
5258
|
+
# byte-identical compilation has nothing to supersede. The compilations list is flat and
|
|
5259
|
+
# cross-repo, so the supersede check MUST be scoped by repo -- otherwise two repos that
|
|
5260
|
+
# legitimately produce the same compilation (a shared/small canonical package -- exactly
|
|
5261
|
+
# this milestone's own fixtures) collide, and the second repo's first ingest is dropped
|
|
5262
|
+
# as a false "superseded". A CHANGED compilation reseals -> a new record. Never a dup.
|
|
5263
|
+
superseded = any(x.get("seal") == comp_seal and x.get("repo") == args.repo for x in comps)
|
|
5264
|
+
if not superseded:
|
|
5265
|
+
comps.append(comp_rec)
|
|
5266
|
+
_save(args.ledger, ledger)
|
|
5267
|
+
new_items = []
|
|
5268
|
+
if uints:
|
|
5269
|
+
dpath = os.path.join(repo_path, ISSUES_DEFERRED_FILE)
|
|
5270
|
+
existing = ""
|
|
5271
|
+
if os.path.isfile(dpath):
|
|
5272
|
+
with open(dpath, encoding="utf-8-sig", errors="replace") as fh:
|
|
5273
|
+
existing = fh.read()
|
|
5274
|
+
add = [u for u in uints if u["id"] not in existing]
|
|
5275
|
+
if add:
|
|
5276
|
+
with open(dpath, "a", encoding="utf-8", newline="\n") as fh:
|
|
5277
|
+
if existing and not existing.endswith("\n"):
|
|
5278
|
+
fh.write("\n")
|
|
5279
|
+
for u in add:
|
|
5280
|
+
fh.write("- [ ] %s (unresolved_intent): %s -- the compiler decided "
|
|
5281
|
+
"'%s' on its own; a candidate canonical improvement (ADR-016)\n"
|
|
5282
|
+
% (u["id"], u["ir_region"], u["decision"]))
|
|
5283
|
+
new_items = [u["id"] for u in add]
|
|
5284
|
+
out = {"repo": args.repo, "compilation": comp_rec["id"], "superseded": superseded,
|
|
5285
|
+
"unresolved_intent": [u["id"] for u in uints],
|
|
5286
|
+
"issues_deferred_new": new_items,
|
|
5287
|
+
"unexplained_units": comp_rec["unexplained_units"]}
|
|
5288
|
+
if args.json:
|
|
5289
|
+
print(json.dumps(out, indent=2, ensure_ascii=False))
|
|
5290
|
+
else:
|
|
5291
|
+
print("COMPILE-INGEST %s: compilation %s%s"
|
|
5292
|
+
% (args.repo, comp_rec["id"],
|
|
5293
|
+
" (byte-identical to a prior ingest -- nothing superseded)"
|
|
5294
|
+
if superseded else ""))
|
|
5295
|
+
print(" %d unresolved_intent -> %d new %s item(s); %d unexplained unit(s)"
|
|
5296
|
+
% (len(uints), len(new_items), ISSUES_DEFERRED_FILE,
|
|
5297
|
+
len(comp_rec["unexplained_units"])))
|
|
5298
|
+
sys.exit(0)
|
|
5299
|
+
|
|
5300
|
+
|
|
5301
|
+
# --------------------------------------------------------------------------- #
|
|
5302
|
+
# bootstrap (Diamond M4: a bounded subsystem's identity is carried by its
|
|
5303
|
+
# canonical package + a WITHHELD oracle, not by its implementation. The oracle
|
|
5304
|
+
# runner is a measured fact and decides "same system"; variance is advisory
|
|
5305
|
+
# evidence that the implementations genuinely differ. ADR-017.)
|
|
5306
|
+
# --------------------------------------------------------------------------- #
|
|
5307
|
+
_BOOTSTRAP_CASE_TIMEOUT = 15 # a compiled hook must decide fast
|
|
5308
|
+
|
|
5309
|
+
|
|
5310
|
+
def _run_oracle_case(impl_path, case):
|
|
5311
|
+
"""Run ONE withheld oracle case against a compiled implementation: feed the case's stdin
|
|
5312
|
+
(raw_stdin verbatim if present, else json.dumps(payload)) to `python <impl>`, and compare
|
|
5313
|
+
the process exit code to `expected_exit`. Deterministic execution -- the oracle is a
|
|
5314
|
+
`measured` fact, never an LLM judgment. Returns a per-case result dict."""
|
|
5315
|
+
if "raw_stdin" in case:
|
|
5316
|
+
stdin = case["raw_stdin"]
|
|
5317
|
+
else:
|
|
5318
|
+
stdin = json.dumps(case.get("payload"))
|
|
5319
|
+
try:
|
|
5320
|
+
r = subprocess.run([sys.executable, impl_path], input=stdin, capture_output=True,
|
|
5321
|
+
text=True, encoding="utf-8", errors="replace",
|
|
5322
|
+
timeout=_BOOTSTRAP_CASE_TIMEOUT)
|
|
5323
|
+
got, err = r.returncode, None
|
|
5324
|
+
except subprocess.TimeoutExpired:
|
|
5325
|
+
got, err = None, "timeout"
|
|
5326
|
+
except OSError as exc:
|
|
5327
|
+
got, err = None, "could not run impl: %s" % exc
|
|
5328
|
+
want = case.get("expected_exit")
|
|
5329
|
+
return {"name": case.get("name"), "expected": want, "got": got,
|
|
5330
|
+
"ok": (err is None and got == want), "error": err}
|
|
5331
|
+
|
|
5332
|
+
|
|
5333
|
+
def cmd_bootstrap_oracle(args):
|
|
5334
|
+
"""Run a WITHHELD oracle suite (ADR-017) against a compiled implementation. The oracle
|
|
5335
|
+
predates and is physically separate from every compiler input; this runner is the
|
|
5336
|
+
maker!=checker wall made executable. Exit 0 iff every case matches its expected exit,
|
|
5337
|
+
else 1 -- a measured behavioural fact about whether this implementation is the same
|
|
5338
|
+
system. It runs the implementation as a subprocess and consults no model."""
|
|
5339
|
+
try:
|
|
5340
|
+
with open(args.oracle, encoding="utf-8-sig") as fh:
|
|
5341
|
+
oracle = json.load(fh)
|
|
5342
|
+
except (OSError, ValueError) as exc:
|
|
5343
|
+
print("[qa_ledger] bootstrap-oracle: unreadable oracle %s: %s" % (args.oracle, exc),
|
|
5344
|
+
file=sys.stderr)
|
|
5345
|
+
sys.exit(2)
|
|
5346
|
+
cases = oracle.get("cases")
|
|
5347
|
+
if not isinstance(cases, list) or not cases:
|
|
5348
|
+
print("[qa_ledger] bootstrap-oracle: oracle has no cases", file=sys.stderr)
|
|
5349
|
+
sys.exit(2)
|
|
5350
|
+
if not os.path.isfile(args.impl):
|
|
5351
|
+
print("[qa_ledger] bootstrap-oracle: no implementation at %s" % args.impl,
|
|
5352
|
+
file=sys.stderr)
|
|
5353
|
+
sys.exit(2)
|
|
5354
|
+
results = [_run_oracle_case(args.impl, c) for c in cases]
|
|
5355
|
+
passed = sum(1 for r in results if r["ok"])
|
|
5356
|
+
failed = [r for r in results if not r["ok"]]
|
|
5357
|
+
report = {"impl": args.impl, "oracle": args.oracle, "total": len(results),
|
|
5358
|
+
"passed": passed, "failed": len(failed),
|
|
5359
|
+
"oracle_green": not failed, "results": results}
|
|
5360
|
+
if args.ledger and args.repo:
|
|
5361
|
+
ledger = _load(args.ledger)
|
|
5362
|
+
_repo_node(ledger, args.repo)
|
|
5363
|
+
rec = {"impl": os.path.basename(args.impl), "oracle": os.path.basename(args.oracle),
|
|
5364
|
+
"total": len(results), "passed": passed, "failed": len(failed),
|
|
5365
|
+
"oracle_green": not failed,
|
|
5366
|
+
"failing": [r["name"] for r in failed], "at": _now()}
|
|
5367
|
+
ledger.setdefault("bootstrap_oracle", []).append(rec)
|
|
5368
|
+
_save(args.ledger, ledger)
|
|
5369
|
+
if args.json:
|
|
5370
|
+
print(json.dumps(report, indent=2, ensure_ascii=False))
|
|
5371
|
+
else:
|
|
5372
|
+
print("BOOTSTRAP-ORACLE %s: %d/%d cases pass -- %s"
|
|
5373
|
+
% (os.path.basename(args.impl), passed, len(results),
|
|
5374
|
+
"ORACLE GREEN (same system on this suite)" if not failed
|
|
5375
|
+
else "ORACLE RED (%d divergence(s))" % len(failed)))
|
|
5376
|
+
for r in failed:
|
|
5377
|
+
print(" x %s: expected exit %s, got %s%s"
|
|
5378
|
+
% (r["name"], r["expected"], r["got"],
|
|
5379
|
+
" (%s)" % r["error"] if r["error"] else ""))
|
|
5380
|
+
sys.exit(0 if not failed else 1)
|
|
5381
|
+
|
|
5382
|
+
|
|
5383
|
+
def _impl_metrics(path):
|
|
5384
|
+
"""Structural fingerprint of one implementation: physical LOC, AST node count, function
|
|
5385
|
+
and class counts, and the set of imported top-level modules. Deterministic; no judgment."""
|
|
5386
|
+
try:
|
|
5387
|
+
with open(path, encoding="utf-8", errors="replace") as fh:
|
|
5388
|
+
src = fh.read()
|
|
5389
|
+
except OSError as exc:
|
|
5390
|
+
return {"path": path, "error": "unreadable: %s" % exc}
|
|
5391
|
+
loc = sum(1 for ln in src.splitlines() if ln.strip())
|
|
5392
|
+
try:
|
|
5393
|
+
tree = ast.parse(src)
|
|
5394
|
+
except SyntaxError as exc:
|
|
5395
|
+
return {"path": path, "loc": loc, "error": "unparseable: %s" % exc}
|
|
5396
|
+
funcs = classes = nodes = 0
|
|
5397
|
+
imports = set()
|
|
5398
|
+
for nd in ast.walk(tree):
|
|
5399
|
+
nodes += 1
|
|
5400
|
+
if isinstance(nd, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
5401
|
+
funcs += 1
|
|
5402
|
+
elif isinstance(nd, ast.ClassDef):
|
|
5403
|
+
classes += 1
|
|
5404
|
+
elif isinstance(nd, ast.Import):
|
|
5405
|
+
for a in nd.names:
|
|
5406
|
+
imports.add(a.name.split(".")[0])
|
|
5407
|
+
elif isinstance(nd, ast.ImportFrom):
|
|
5408
|
+
if nd.module:
|
|
5409
|
+
imports.add(nd.module.split(".")[0])
|
|
5410
|
+
return {"path": path, "loc": loc, "ast_nodes": nodes, "functions": funcs,
|
|
5411
|
+
"classes": classes, "imports": sorted(imports),
|
|
5412
|
+
"sha256": hashlib.sha256(src.encode("utf-8")).hexdigest()}
|
|
5413
|
+
|
|
5414
|
+
|
|
5415
|
+
def cmd_bootstrap_variance(args):
|
|
5416
|
+
"""Prove independent compilations of the same canonical package genuinely DIFFER (ADR-017).
|
|
5417
|
+
Reports per-implementation structural metrics and pairwise divergence. ADVISORY: variance
|
|
5418
|
+
is evidence the implementations differ, never a certificate of 'same system' (only the
|
|
5419
|
+
oracle certifies that) and never a gate -- it cannot change an exit code."""
|
|
5420
|
+
metrics = [_impl_metrics(p) for p in args.impls]
|
|
5421
|
+
pairs = []
|
|
5422
|
+
good = [m for m in metrics if "error" not in m]
|
|
5423
|
+
for i in range(len(good)):
|
|
5424
|
+
for j in range(i + 1, len(good)):
|
|
5425
|
+
a, b = good[i], good[j]
|
|
5426
|
+
ia, ib = set(a["imports"]), set(b["imports"])
|
|
5427
|
+
jac = (len(ia & ib) / len(ia | ib)) if (ia or ib) else 1.0
|
|
5428
|
+
pairs.append({"a": os.path.basename(a["path"]), "b": os.path.basename(b["path"]),
|
|
5429
|
+
"byte_identical": a["sha256"] == b["sha256"],
|
|
5430
|
+
"loc_delta": abs(a["loc"] - b["loc"]),
|
|
5431
|
+
"ast_node_delta": abs(a["ast_nodes"] - b["ast_nodes"]),
|
|
5432
|
+
"function_delta": abs(a["functions"] - b["functions"]),
|
|
5433
|
+
"import_jaccard": round(jac, 3)})
|
|
5434
|
+
all_distinct = all(not p["byte_identical"] for p in pairs) if pairs else None
|
|
5435
|
+
report = {"implementations": metrics, "pairs": pairs, "all_distinct": all_distinct,
|
|
5436
|
+
"advisory": True}
|
|
5437
|
+
if args.json:
|
|
5438
|
+
print(json.dumps(report, indent=2, ensure_ascii=False))
|
|
5439
|
+
else:
|
|
5440
|
+
for m in metrics:
|
|
5441
|
+
if "error" in m:
|
|
5442
|
+
print("VARIANCE %s: %s" % (os.path.basename(m["path"]), m["error"]))
|
|
5443
|
+
else:
|
|
5444
|
+
print("VARIANCE %s: %d loc, %d ast-nodes, %d fn, %d cls, imports=%s"
|
|
5445
|
+
% (os.path.basename(m["path"]), m["loc"], m["ast_nodes"],
|
|
5446
|
+
m["functions"], m["classes"], ",".join(m["imports"]) or "-"))
|
|
5447
|
+
for p in pairs:
|
|
5448
|
+
print(" %s vs %s: %s | dloc=%d dnodes=%d import_jaccard=%.2f"
|
|
5449
|
+
% (p["a"], p["b"], "IDENTICAL" if p["byte_identical"] else "distinct",
|
|
5450
|
+
p["loc_delta"], p["ast_node_delta"], p["import_jaccard"]))
|
|
5451
|
+
if all_distinct is not None:
|
|
5452
|
+
print(" all implementations distinct: %s (advisory, never gates)"
|
|
5453
|
+
% ("yes" if all_distinct else "NO -- convergence, a weak result"))
|
|
5454
|
+
sys.exit(0)
|
|
5455
|
+
|
|
5456
|
+
|
|
4968
5457
|
# --------------------------------------------------------------------------- #
|
|
4969
5458
|
# facts (T0 / SYSTEM-FACTS: public claims become compiled artifacts of repo
|
|
4970
5459
|
# facts -- Diamond applied to Diamond. ADR-012.)
|
|
@@ -9035,6 +9524,48 @@ def build_parser():
|
|
|
9035
9524
|
pir.add_argument("--repo", required=True)
|
|
9036
9525
|
pir.set_defaults(func=cmd_ir_render)
|
|
9037
9526
|
|
|
9527
|
+
pcmv = sub.add_parser(
|
|
9528
|
+
"compile-validate",
|
|
9529
|
+
help="validate a COMPILATION.json against a reference IR (ADR-016); only mechanical "
|
|
9530
|
+
"violations gate, degeneracy stats are advisory and NEVER block")
|
|
9531
|
+
pcmv.add_argument("--ir", required=True,
|
|
9532
|
+
help="the reference IR.json the compilation targets")
|
|
9533
|
+
pcmv.add_argument("--compilation", required=True, help="path to COMPILATION.json")
|
|
9534
|
+
pcmv.add_argument("--json", action="store_true")
|
|
9535
|
+
pcmv.set_defaults(func=cmd_compile_validate)
|
|
9536
|
+
|
|
9537
|
+
pcmi = sub.add_parser(
|
|
9538
|
+
"compile-ingest",
|
|
9539
|
+
help="record a VALIDATED compilation into the ledger (ADR-016): by-construction "
|
|
9540
|
+
"unexplained_code + unresolved_intent as append-only UINT objects + backlog")
|
|
9541
|
+
pcmi.add_argument("--ledger", default="QA-LEDGER.json")
|
|
9542
|
+
pcmi.add_argument("--repo", required=True)
|
|
9543
|
+
pcmi.add_argument("--ir", required=True,
|
|
9544
|
+
help="the reference IR.json the compilation targets")
|
|
9545
|
+
pcmi.add_argument("--compilation", required=True, help="path to COMPILATION.json")
|
|
9546
|
+
pcmi.add_argument("--json", action="store_true")
|
|
9547
|
+
pcmi.set_defaults(func=cmd_compile_ingest)
|
|
9548
|
+
|
|
9549
|
+
pbo = sub.add_parser(
|
|
9550
|
+
"bootstrap-oracle",
|
|
9551
|
+
help="run a WITHHELD oracle suite against a compiled implementation (ADR-017); exit 0 "
|
|
9552
|
+
"iff every case matches its expected exit -- the maker!=checker wall, executable")
|
|
9553
|
+
pbo.add_argument("--impl", required=True, help="the compiled implementation to run")
|
|
9554
|
+
pbo.add_argument("--oracle", required=True, help="the withheld ORACLE.json case suite")
|
|
9555
|
+
pbo.add_argument("--ledger", default=None, help="optional: persist the measured result")
|
|
9556
|
+
pbo.add_argument("--repo", default=None, help="repo scope when --ledger is given")
|
|
9557
|
+
pbo.add_argument("--json", action="store_true")
|
|
9558
|
+
pbo.set_defaults(func=cmd_bootstrap_oracle)
|
|
9559
|
+
|
|
9560
|
+
pbv = sub.add_parser(
|
|
9561
|
+
"bootstrap-variance",
|
|
9562
|
+
help="structural metrics + pairwise divergence proving independent compilations "
|
|
9563
|
+
"genuinely differ (ADR-017); ADVISORY evidence, never a gate")
|
|
9564
|
+
pbv.add_argument("--impls", required=True, nargs="+",
|
|
9565
|
+
help="two or more compiled implementations to compare")
|
|
9566
|
+
pbv.add_argument("--json", action="store_true")
|
|
9567
|
+
pbv.set_defaults(func=cmd_bootstrap_variance)
|
|
9568
|
+
|
|
9038
9569
|
pcr = sub.add_parser("cleanroom",
|
|
9039
9570
|
help="run a command against a CLEAN checkout of one commit in a throwaway worktree (ADR-008)")
|
|
9040
9571
|
pcr.add_argument("--ledger", default="QA-LEDGER.json")
|