bin/publish-reports-entrypoint.py
#!/usr/bin/env python3
"""Materialize the meaning-first reports entrypoint in a Runtime web tree.
Rendering stays in Engineering Tools. Runtime owns the publish location and
the small, explicit projection of runtime evidence into that location.
"""
from __future__ import annotations
import argparse
import json
import shutil
import subprocess
import sys
from pathlib import Path
DEFAULT_RUNTIME_ROOT = Path(__file__).resolve().parents[1]
REPORT_NAMES = (
"SE-0056-phase-5-validation.json",
"SE-0056-traceability-validation.json",
"SE-0069-link-validation-report.json",
"SE-0069-link-validation-report.md",
"SE-0070-context-impact-validation.json",
"SE-0071-regression-evidence.json",
)
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--engineering-tools-root", type=Path, required=True)
parser.add_argument("--runtime-root", type=Path, default=DEFAULT_RUNTIME_ROOT,
help="Runtime-Wurzel für Evidenz und Eingabemodell")
parser.add_argument("--output-root", type=Path, required=True,
help="Runtime web/reports directory")
parser.add_argument("--target-runtime", default="",
help="Zielumgebung der veröffentlichten Reports")
parser.add_argument("--input", type=Path,
default=None)
args = parser.parse_args()
runtime_root = args.runtime_root.expanduser().resolve()
tools_root = args.engineering_tools_root.expanduser().resolve()
publisher = tools_root / "97-documentation" / "publish-semantic-landing.py"
if not publisher.is_file():
parser.error(f"Semantischer Publisher fehlt: {publisher}")
input_path = (args.input or runtime_root / "reports" / "SE-0057-semantic-publisher-input.json").expanduser().resolve()
if not input_path.is_file():
parser.error(f"Eingabemodell fehlt: {input_path}")
work_item = json.loads(input_path.read_text(encoding="utf-8")).get("workItem", "SE-0065")
if not isinstance(work_item, str) or not work_item:
parser.error("Eingabemodell enthält kein gültiges Work Item")
output_root = args.output_root.expanduser().resolve()
output_root.mkdir(parents=True, exist_ok=True)
technical = output_root / "technical-reports"
technical.mkdir(parents=True, exist_ok=True)
for name in REPORT_NAMES:
source = runtime_root / "reports" / name
if not source.is_file():
parser.error(f"Runtime-Evidenz fehlt: {source}")
shutil.copyfile(source, technical / name)
command = [
sys.executable, str(publisher), str(input_path), str(output_root / "index.html"),
"--report", str(runtime_root / "reports" / f"{work_item}-reports-entrypoint-validation.json"),
"--link-report", str(runtime_root / "reports" / f"{work_item}-reports-entrypoint-links.json"),
"--link-markdown-report", str(runtime_root / "reports" / f"{work_item}-reports-entrypoint-links.md"),
"--timestamp", "1970-01-01T00:00:00Z",
"--target-runtime", args.target_runtime,
"--code-view-directory", str(output_root / "code"),
"--code-source", f"engineering-tools={tools_root}",
"--test-source", f"engineering-tools={tools_root / '98-tests'}",
"--test-source", f"runtime={runtime_root / 'test'}",
]
completed = subprocess.run(command, text=True, capture_output=True)
if completed.stdout:
print(completed.stdout, end="")
if completed.returncode:
if completed.stderr:
print(completed.stderr, file=sys.stderr, end="")
return completed.returncode
validation_path = runtime_root / "reports" / f"{work_item}-reports-entrypoint-validation.json"
validation = json.loads(validation_path.read_text(encoding="utf-8"))
validation["output"] = "web/reports/index.html"
validation_path.write_text(json.dumps(validation, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
evidence = {
"schemaVersion": "1.0",
"workItem": work_item,
"status": "PASSED",
"entrypoint": "/reports/",
"publishedFile": "web/reports/index.html",
"renderer": "engineering-tools:97-documentation/publish-semantic-landing.py",
"materializer": "runtime:bin/publish-reports-entrypoint.py",
"technicalReports": list(REPORT_NAMES),
}
(runtime_root / "reports" / f"{work_item}-reports-entrypoint-evidence.json").write_text(
json.dumps(evidence, ensure_ascii=False, indent=2) + "\n", encoding="utf-8"
)
return 0
if __name__ == "__main__":
raise SystemExit(main())