feat(i18n): tools + landing page + doorstop generator in English
Validate / build-test (macos-latest) (push) Failing after 2s
Validate / build-test (windows-latest) (push) Failing after 16s
Validate / build-test (ubuntu-latest) (push) Successful in 18s
Validate / reports (push) Successful in 52s

Phase 1 of full English translation:
- generate_doorstop_items.py: all 55 items (SG/SYS/SWE/SA/SWA) rewritten in English
- generate_landing_page.py: full UI labels, KPI cards, section headings in English
- traceability.py: docstring, error messages, HTML headers in English
- generate_test_report.py: report content + table headers in English
- All 55 markdown items in safety/sg/, reqs/, arch/ regenerated in English

Still to come:
- demo-epb filled Word docs (PID, plans, safety, manuals, audit artefacts)
- Code comments + test names + CI workflow step names
- README + dev-process repo templates
This commit is contained in:
Stefan Lohmaier
2026-05-12 03:28:54 -07:00
parent 542a358abc
commit a47e0aed3e
61 changed files with 805 additions and 803 deletions
+21 -21
View File
@@ -1,17 +1,17 @@
#!/usr/bin/env python3
"""
Traceability-Werkzeug fuer demo-epb.
Traceability tool for demo-epb.
Liest Markdown-Items aus safety/sg, reqs/sys, reqs/swe, arch/sys, arch/swe und
verifiziert die Traceability-Kette:
Reads Markdown items from safety/sg, reqs/sys, reqs/swe, arch/sys, arch/swe and
verifies the traceability chain:
SG <-- SYS <-- SA
<-- SWE <-- SWA <-- Code (@arch)
<-- Tests (@reqs)
Subcommands:
check Validiert Konsistenz, exit 1 bei Fehlern
publish DIR Schreibt HTML + JSON nach DIR/
check Validates consistency, exits 1 on errors
publish DIR Writes HTML + JSON to DIR/
Run:
python3 tools/traceability.py check
@@ -160,27 +160,27 @@ def check_code_test_mapping(items: dict[str, Item]) -> list[str]:
src = REPO / src_rel
arch_tags, _ = extract_tags(src)
if swa_id not in arch_tags:
errors.append(f"{src_rel}: header @arch enthaelt {swa_id} nicht "
f"(gefunden: {arch_tags or ''})")
errors.append(f"{src_rel}: header @arch does not contain {swa_id} "
f"(found: {arch_tags or ''})")
# For each test, verify @reqs covers the SWE that the corresponding SWA links to
for test_file, swa_id in IMPLEMENTED_TESTS.items():
test_path = REPO / "tests" / "unit" / test_file
_, reqs_in_test = extract_tags(test_path)
if not reqs_in_test:
errors.append(f"tests/unit/{test_file}: kein @reqs Tag im Header")
errors.append(f"tests/unit/{test_file}: no @reqs tag in header")
continue
swa = items.get(swa_id)
if swa is None:
errors.append(f"tests/unit/{test_file}: referenziertes "
f"{swa_id} nicht gefunden")
errors.append(f"tests/unit/{test_file}: referenced "
f"{swa_id} not found")
continue
swa_swe = set(swa.links)
test_swe = set(reqs_in_test)
missing = swa_swe - test_swe
if missing:
errors.append(f"tests/unit/{test_file}: deckt nicht alle SWE "
f"der {swa_id} ab — fehlend: {sorted(missing)}")
errors.append(f"tests/unit/{test_file}: does not cover all SWE of "
f"{swa_id} — missing: {sorted(missing)}")
return errors
@@ -241,7 +241,7 @@ def cmd_check(items: dict[str, Item]) -> int:
for e in errors:
print(f" - {e}")
return 1
print("OK — Traceability vollstaendig (SG → SYS → SA, SWE → SWA → Code+Test).")
print("OK — Traceability complete (SG → SYS → SA, SWE → SWA → Code+Test).")
return 0
@@ -314,7 +314,7 @@ def cmd_publish(items: dict[str, Item], out_dir: Path) -> int:
".missing{color:#c00}",
"</style></head><body>",
"<h1>demo-epb — Traceability Matrix</h1>",
"<p>Vollstaendige Kette: <code>SG → SYS → SA, SWE → SWA → Code (@arch) + Test (@reqs)</code></p>",
"<p>Complete chain: <code>SG → SYS → SA, SWE → SWA → Code (@arch) + Test (@reqs)</code></p>",
"<p>",
]
for p, _, label in SOURCES:
@@ -325,9 +325,9 @@ def cmd_publish(items: dict[str, Item], out_dir: Path) -> int:
parts.append("<table>")
parts.append(
"<tr><th>Safety Goal</th><th>System-Requirement</th>"
"<th>System-Arch</th><th>Software-Req</th>"
"<th>Software-Arch</th><th>Code</th><th>Test</th></tr>"
"<tr><th>Safety Goal</th><th>System Requirement</th>"
"<th>System Arch</th><th>Software Req</th>"
"<th>Software Arch</th><th>Code</th><th>Test</th></tr>"
)
def cell_items(ids: list[str]) -> str:
@@ -377,8 +377,8 @@ def cmd_publish(items: dict[str, Item], out_dir: Path) -> int:
parts.append("</table>")
# Code/Test details
parts.append("<h2>Code → Architektur</h2>")
parts.append("<table><tr><th>Datei</th><th>@arch</th><th>@reqs</th></tr>")
parts.append("<h2>Code → Architecture</h2>")
parts.append("<table><tr><th>File</th><th>@arch</th><th>@reqs</th></tr>")
for swa_id, src_rel in IMPLEMENTED_SWA.items():
arch, reqs = extract_tags(REPO / src_rel)
parts.append(
@@ -388,8 +388,8 @@ def cmd_publish(items: dict[str, Item], out_dir: Path) -> int:
)
parts.append("</table>")
parts.append("<h2>Test → Anforderungen</h2>")
parts.append("<table><tr><th>Test-Datei</th><th>Decklt SWA</th><th>@reqs</th></tr>")
parts.append("<h2>Test → Requirements</h2>")
parts.append("<table><tr><th>Test file</th><th>Covers SWA</th><th>@reqs</th></tr>")
for test_file, swa_id in IMPLEMENTED_TESTS.items():
_, reqs = extract_tags(REPO / "tests" / "unit" / test_file)
parts.append(