78f0ffa9de
Roadmap item 4. After WHAT applies / WHAT is missing / WHICH first, the GF asks HOW. The Implementation Playbook renders, for one capability, the full journey — why / which regulations it closes / tools / process / evidence / controls — and chains the Optimization Roadmap into per-measure playbooks. Another renderer over the same Capability spine (ADR-003/004), not a new engine: ~95% of the data already exists, it just needs a different rendering. - compliance/playbook/: build_playbook() + playbooks_for_plan() (chains optimization -> playbook, acyclic; reuses leverage for "closes which regulations"). Capabilities without curated content render as honest status:missing stubs — the content-owed signal. - knowledge/implementation_playbooks/: curated knowledge layer (Reasoning Knowledge Acquisition), two deep expert drafts (SBOM, CVD/PSIRT, status draft, expert-draft-not-normative) + README. The bottleneck is now CONTENT, not software; Playbook (own knowledge) != regulatory domain. - ADR-004: Implementation Playbooks = renderer + knowledge layer; content is the bottleneck. - reference suite: "Implementation Playbook" section renders the SBOM journey + Roadmap->Playbook table (high-leverage caps flagged "fehlt (Inhalt)" — content backlog, highest leverage first). - refactor: extracted markdown helpers to reference_scenarios/_helpers.py to keep generate.py under the 500-LOC budget. 9 playbook tests (40 with optimization+transition+company), mypy --strict clean, check-loc 0. Product code with no app caller + knowledge/ADR/reference = non-runtime -> no deploy (ADR-001). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
62 lines
2.0 KiB
Python
62 lines
2.0 KiB
Python
# ruff: noqa
|
|
# mypy: ignore-errors
|
|
"""Rendering helpers for the Reference Scenario Suite generator.
|
|
|
|
Holds the shared mutable output buffers (OUT, ROLLUP) and the small markdown helpers so the
|
|
generator script (`generate.py`) stays under the LOC budget. Not product code; not imported by
|
|
the app — only by the generator (run via `PYTHONPATH=. python3 reference_scenarios/generate.py`).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from typing import List, Tuple
|
|
|
|
Row = Tuple[str, str, str]
|
|
OUT: List[str] = []
|
|
ROLLUP: List[str] = []
|
|
|
|
|
|
def w(s: str = "") -> None:
|
|
OUT.append(s)
|
|
|
|
|
|
def coverage_table(rows: List[Row]) -> None:
|
|
w("**Architecture Coverage**")
|
|
w("")
|
|
w("| Layer | Status | Hinweis |")
|
|
w("|---|---|---|")
|
|
for layer, status, note in rows:
|
|
w("| %s | **%s** | %s |" % (layer, status, note))
|
|
ROLLUP.append(status)
|
|
w("")
|
|
|
|
|
|
def reg_map_block(rmap) -> None:
|
|
w("**Expected Regulatory Map**")
|
|
w("")
|
|
w("> " + rmap.executive_summary)
|
|
w("")
|
|
for v in rmap.applicable_regulations:
|
|
obs = ", ".join(o.obligation_id for o in v.obligations) or v.obligations_note
|
|
w("- **%s** (%s) — Pflichten: %s" % (v.regulation_id, v.name, obs))
|
|
for u in rmap.uncertain_regulations:
|
|
w("- _unsicher_ %s — fehlt: %s" % (u.regulation_id, ", ".join(u.missing_facts) or "-"))
|
|
for ov in rmap.overlaps:
|
|
w("- Overlap %s: %s" % (ov.overlap_group_id, ", ".join(ov.shared_obligations)))
|
|
for ev, ids in rmap.shared_evidence.items():
|
|
w("- 1 Nachweis `%s` => %d Pflichten" % (ev, len(ids)))
|
|
w("")
|
|
|
|
|
|
def unsupported_block(rmap) -> None:
|
|
w("**Expected Unsupported Domains**")
|
|
w("")
|
|
if not rmap.unsupported_domains:
|
|
w("- keine — alle getriggerten Domaenen sind im Korpus")
|
|
for d in rmap.unsupported_domains:
|
|
w("- `%s` (Trigger: %s) -> %s" % (d.domain, d.trigger, d.note))
|
|
w("")
|
|
|
|
|
|
def interp_status(verdict_value: str) -> str:
|
|
return "PARTIAL" if verdict_value in ("uncertain", "unsupported") else "PASS"
|