Files
aigc-home/calliope-backend/scripts/audit_library_documents.py
T

314 lines
14 KiB
Python

"Compare exported source-only documentation with repository bytes, without services."
from __future__ import annotations
import argparse
import copy
import hashlib
import json
from collections import Counter
from pathlib import Path
def audit(repo: Path, directory: Path) -> dict:
manifest = json.loads((directory / "manifest.json").read_text(encoding="utf-8"))
sources = {
p.relative_to(repo).as_posix()
for p in (repo / "example_ComfyUI_workflows").rglob("*")
if p.is_file()
}
assert {e["path"] for e in manifest} == sources
assert len(manifest) == len(sources)
files = []
for entry in manifest:
raw = (repo / entry["path"]).read_bytes()
source = json.loads(raw.decode("utf-8-sig"))
doc = json.loads((directory / entry["document"]).read_text(encoding="utf-8"))
assert hashlib.sha1(raw).hexdigest() == entry["source_sha"]
assert doc["source_review"]["source_sha"] == entry["source_sha"]
nodes = {}
source_links = []
def visit(graph, scope=""):
ui = "nodes" in graph
rows = graph["nodes"] if ui else [dict(n, id=k) for k, n in graph.items()]
for node in rows:
nid = scope + str(node["id"])
nodes[nid] = (
node["widgets_values"]
if ui and "widgets_values" in node
else ([] if ui else node["inputs"])
)
if not ui:
source_links.extend(
{
"scope": scope,
"node_id": nid,
"field": key,
"upstream_node_id": str(value[0]),
"output_slot": value[1],
}
for key, value in node["inputs"].items()
if isinstance(value, list) and len(value) == 2
)
source_links.extend({"scope": scope, "link": link} for link in graph.get("links", []))
for sub in graph.get("definitions", {}).get("subgraphs", []):
visit(sub, scope + sub["id"] + "/")
visit(source)
assert doc["source_links"] == source_links
assert {n["node_id"]: n["source_values"] for n in doc["source_nodes"]} == nodes
for param in doc["params"]:
assert param["default"] == nodes[param["node_id"]][param["field"]]
assert param["unit"] is None
assert param["min"] is None and param["max"] is None
for note in doc["source_notes"]:
assert note["content"] == nodes[note["node_id"]]
checked_fields = doc["source_review"].get("reviewed_named_fields", [])
assert len({(f["node_id"], f["field"]) for f in checked_fields}) == len(checked_fields)
for field in checked_fields:
assert field["source_value"] == nodes[field["node_id"]][field["field"]]
fourth = doc["source_review"].get("fourth_review")
if fourth:
assert fourth["operation_check"] in doc["steps"]
assert {(f["node_id"], f["field"]) for f in checked_fields} == {
(p["node_id"], p["field"]) for p in doc["params"]
}
semantic = doc["source_review"].get("semantic_review")
if semantic:
assert semantic["batch"] == "HEL-892-third"
assert semantic["operation_check"] in doc["steps"]
assert semantic["conclusions"] and semantic["unknowns"]
assert {(f["node_id"], f["field"]) for f in checked_fields} == {
(p["node_id"], p["field"]) for p in doc["params"]
}
for kind in ("nodes", "notes"):
for ref in semantic["evidence_refs"][kind]:
key, index = ref["pointer"].strip("/").split("/")
assert doc[key][int(index)]["node_id"] == ref["node_id"]
assert semantic["mechanical_inventory"] == {
"named_value_count": len(doc["params"]),
"note_count": len(doc["source_notes"]),
"link_count": len(doc["source_links"]),
"position_widget_node_count": len(
doc["source_review"]["evidence"]["unnamed_widget_node_ids"]
),
}
if not checked_fields:
assert semantic["named_parameter_finding"] == ("未发现可由源文件确认的具名参数")
assert doc["status"] == {"imported": True, "doc_done": False, "exec_verified": False}
assert doc["source_review"]["complete"] is False
files.append(
{
"path": entry["path"],
"source_sha": entry["source_sha"],
"document": entry["document"],
"state": entry["state"],
"manual_scope": doc["source_review"]["scope"],
"purpose": doc["purpose"],
"source_specific_instruction": doc["steps"][0],
"source_evidence": doc["source_review"]["evidence"],
"unconfirmed": doc["source_review"]["unconfirmed"],
"reviewed_named_fields": checked_fields,
"semantic_review": semantic,
}
)
return {
"files": files,
"total": len(files),
"source_structure_purpose_partially_reviewed": len(files),
"full_documents_completed": 0,
"files_with_selected_named_fields_reviewed": sum(
bool(f["reviewed_named_fields"]) for f in files
),
"selected_named_fields_reviewed": sum(len(f["reviewed_named_fields"]) for f in files),
"real_executions": 0,
"states": dict(Counter(f["state"] for f in files)),
"named_values_preserved": sum(f["source_evidence"]["named_value_count"] for f in files),
"unnamed_widget_nodes": sum(
len(f["source_evidence"]["unnamed_widget_node_ids"]) for f in files
),
"semantic_batch_files": sum(bool(f["semantic_review"]) for f in files),
"semantic_batch_without_named_fields": sum(
bool(f["semantic_review"]) and not f["reviewed_named_fields"] for f in files
),
"semantic_batch_named_fields": sum(
len(f["reviewed_named_fields"]) for f in files if f["semantic_review"]
),
"named_values_without_manual_field_review": sum(
f["source_evidence"]["named_value_count"] - len(f["reviewed_named_fields"])
for f in files
),
"named_values_without_verified_units_ranges_effects": sum(
f["source_evidence"]["named_value_count"] for f in files
),
"scope_limit": "人工结论与机械原值清单分开;源语义局部审校非完整说明定稿",
}
def audit_partition(repo: Path, report: dict, partition_path: Path) -> dict:
partition = json.loads(partition_path.read_text(encoding="utf-8"))
prior, added = partition["prior_16"], partition["new_140"]
prior_paths = {e["path"] for e in prior}
added_paths = {e["path"] for e in added}
assert len(prior) == len(prior_paths) == 16
assert len(added) == len(added_paths) == 140
assert prior_paths.isdisjoint(added_paths)
assert prior_paths | added_paths == {f["path"] for f in report["files"]}
reviews = json.loads(
(repo / ("calliope-backend/src/calliope/comfyui/source_reviews.json")).read_text(
encoding="utf-8"
)
)
for entry in prior:
# The third-batch snapshot remains immutable historical evidence.
# Reconstruct its exact payload, excluding only the explicit batch-four delta.
review = copy.deepcopy(reviews[entry["path"]])
fourth = review.pop("fourth_review", None)
if fourth:
fourth_fields = {tuple(k) for k in fourth["fields"]}
review["reviewed_named_fields"] = [
f
for f in review["reviewed_named_fields"]
if (f["node_id"], f["field"]) not in fourth_fields
]
assert review["reviewed_named_fields"] == entry["reviewed_named_fields"]
assert (
hashlib.sha256(
json.dumps(review, ensure_ascii=False, sort_keys=True).encode()
).hexdigest()
== entry["review_sha256"]
)
by_path = {f["path"]: f for f in report["files"]}
for entry in prior + added:
assert entry["source_sha"] == by_path[entry["path"]]["source_sha"]
assert all(by_path[p]["semantic_review"] for p in added_paths)
assert all(not by_path[p]["semantic_review"] for p in prior_paths)
return {
"prior_files": 16,
"prior_named_fields": 42,
"new_files": 140,
"new_named_fields": report["semantic_batch_named_fields"],
"new_without_named_fields": report["semantic_batch_without_named_fields"],
"disjoint_complete_sha_verified": True,
"prior_review_payloads_unchanged": True,
}
def audit_fourth(repo: Path, report: dict, partition_path: Path) -> dict:
partition = json.loads(partition_path.read_text(encoding="utf-8"))
mechanical = {tuple(k) for k in partition["mechanical_1227"]}
prior = {tuple(k) for k in partition["prior_542"]}
added = {tuple(k) for k in partition["added_685"]}
assert len(mechanical) == len(partition["mechanical_1227"]) == 1227
assert len(prior) == len(partition["prior_542"]) == 542
assert len(added) == len(partition["added_685"]) == 685
assert prior.isdisjoint(added) and prior | added == mechanical
assert len({k[0] for k in added}) == 16
reviews = json.loads(
(repo / ("calliope-backend/src/calliope/comfyui/source_reviews.json")).read_text(
encoding="utf-8"
)
)
current_ids, checked_added, categories = set(), set(), Counter()
for path, original in reviews.items():
review = copy.deepcopy(original)
fourth = review.pop("fourth_review", None)
fields = review["reviewed_named_fields"]
current_ids.update((path, f["node_id"], f["field"]) for f in fields)
if fourth:
raw = (repo / path).read_bytes()
source = json.loads(raw.decode("utf-8-sig"))
assert hashlib.sha1(raw).hexdigest() == review["source_sha"]
new_fields = [f for f in fields if (path, f["node_id"], f["field"]) in added]
assert {(f["node_id"], f["field"]) for f in new_fields} == {
tuple(k) for k in fourth["fields"]
}
for f in new_fields:
assert f["source_path"] == path and f["source_sha"] == review["source_sha"]
value = source
for part in f["source_pointer"].strip("/").split("/"):
part = part.replace("~1", "/").replace("~0", "~")
value = value[int(part)] if isinstance(value, list) else value[part]
assert json.dumps(value, sort_keys=True) == json.dumps(
f["source_value"], sort_keys=True
)
nid = f["node_id"]
if "nodes" in source:
node = next(n for n in source["nodes"] if str(n["id"]) == nid)
assert f["class_type"] == node["type"]
for direction, endpoint in (("incoming", 3), ("outgoing", 1)):
actual = [
{"pointer": f"/links/{i}", "link": link}
for i, link in enumerate(source.get("links", []))
if str(link[endpoint]) == nid
]
assert f["connections"][direction] == actual
else:
assert f["class_type"] == source[nid]["class_type"]
assert f["connections"]["incoming"] == [
{"field": k, "link": v} for k, v in source[nid]["inputs"].items()
if isinstance(v, list)
]
assert f["connections"]["outgoing"] == [
{"node_id": target, "field": k, "link": v}
for target, n in source.items() for k, v in n["inputs"].items()
if isinstance(v, list) and len(v) == 2 and v[0] == nid
]
assert f["category"] in {
"runtime_parameter",
"frontend_state",
"current_value_only",
"semantic_unknown",
}
assert f["label"] and f["operation_check"] and f["connections"]
categories[f["category"]] += 1
checked_added.add((path, f["node_id"], f["field"]))
assert fourth["classification_counts"] == dict(
Counter(f["category"] for f in new_fields)
)
review["reviewed_named_fields"] = [
f for f in fields if (path, f["node_id"], f["field"]) not in added
]
assert (
hashlib.sha256(
json.dumps(review, ensure_ascii=False, sort_keys=True).encode()
).hexdigest()
== partition["prior_review_sha256"][path]
)
assert current_ids == mechanical and checked_added == added
assert report["selected_named_fields_reviewed"] == 1227
return {
"mechanical_values_checked": 1227,
"prior_reviewed": 542,
"added_reviewed": 685,
"new_files": 16,
"classification_counts_new": dict(categories),
"duplicates": 0,
"prior_156_payloads_preserved": True,
"added_fields_with_runtime_source_use": categories["runtime_parameter"],
"added_fields_without_confirmed_runtime_meaning": 685 - categories["runtime_parameter"],
"verified_units_ranges_effects": 0,
"full_documents_completed": 0,
"real_executions": 0,
}
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--repo", type=Path, required=True)
parser.add_argument("--documents", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--partition", type=Path)
parser.add_argument("--fourth-partition", type=Path)
args = parser.parse_args()
report = audit(args.repo, args.documents)
if args.partition:
report["partition"] = audit_partition(args.repo, report, args.partition)
if args.fourth_partition:
report["fourth_partition"] = audit_fourth(args.repo, report, args.fourth_partition)
args.output.write_text(
json.dumps(report, ensure_ascii=False, indent=2) + "\n", encoding="utf-8"
)
print(json.dumps({k: v for k, v in report.items() if k != "files"}, ensure_ascii=False))