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>
97 lines
4.3 KiB
Python
97 lines
4.3 KiB
Python
"""Implementation Playbook — the Berater renderer ("wie komme ich dort hin?").
|
|
|
|
After the Capability Delta Engine says WHAT is missing and the Optimization renderer says WHICH
|
|
measure first, the Playbook renderer says HOW to implement it. For one capability it assembles the
|
|
full journey from three sources:
|
|
- curated playbook KNOWLEDGE (why / tools / process steps / evidence / how others do it) — the
|
|
Reasoning Knowledge Acquisition layer under `knowledge/implementation_playbooks/`,
|
|
- the regulatory LEVERAGE (which regulations a delivered capability closes) — reused from the
|
|
Optimization renderer,
|
|
- injected Procedure/Control/Evidence links (Execution-owned; empty until linked).
|
|
|
|
Pure, deterministic, computed-not-stored. Chains optimization -> playbook (acyclic). No new corpus,
|
|
no new meta-model class (freeze v1.0). Python 3.9 compatible.
|
|
|
|
The curated content is an EXPERT DRAFT, never a normative requirement. When no playbook knowledge
|
|
exists for a capability yet, the renderer emits a `status: missing` stub — the honest signal that
|
|
the bottleneck is CONTENT (Knowledge Acquisition), not software.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Dict, List, Optional
|
|
|
|
from ..optimization import OptimizationPlan
|
|
from .schemas import Playbook, PlaybookStep
|
|
|
|
_MISSING_WHY = "(Playbook-Inhalt fehlt — Knowledge Acquisition offen.)"
|
|
_DRAFT_DISCLAIMER = (
|
|
"Kuratiertes Experten-Wissen (Erstentwurf), KEINE normative Anforderung. Tools/Schritte sind "
|
|
"Empfehlungen, kein Pflichtkatalog; Controls werden aus der Execution-Schicht injiziert."
|
|
)
|
|
|
|
|
|
def _steps(raw: Any) -> List[PlaybookStep]:
|
|
steps: List[PlaybookStep] = []
|
|
for i, s in enumerate(raw or [], 1):
|
|
steps.append(PlaybookStep(order=i, title=str(s.get("title", "")), detail=str(s.get("detail", ""))))
|
|
return steps
|
|
|
|
|
|
def build_playbook(
|
|
capability_id: str,
|
|
knowledge: Optional[Dict[str, Any]] = None,
|
|
closes_regulations: Optional[List[str]] = None,
|
|
control_links: Optional[List[str]] = None,
|
|
) -> Playbook:
|
|
"""Assemble the implementation journey for ONE capability.
|
|
|
|
`knowledge`: the curated playbook dict (None/empty -> a `missing` stub). `closes_regulations`:
|
|
the regulations a delivered capability closes (leverage, from `covers_targets`). `control_links`:
|
|
Execution-owned control refs, injected (default empty — no Execution data in Reasoning code).
|
|
"""
|
|
closes = sorted(set(closes_regulations or []))
|
|
if not knowledge:
|
|
return Playbook(
|
|
capability_id=capability_id, title=capability_id, why=_MISSING_WHY,
|
|
closes_regulations=closes, leverage=len(closes), controls=list(control_links or []),
|
|
status="missing", disclaimer=_DRAFT_DISCLAIMER,
|
|
)
|
|
return Playbook(
|
|
capability_id=capability_id,
|
|
title=str(knowledge.get("title", capability_id)),
|
|
why=str(knowledge.get("why", "")),
|
|
closes_regulations=closes,
|
|
leverage=len(closes),
|
|
tools=list(knowledge.get("tools", [])),
|
|
process_steps=_steps(knowledge.get("process_steps")),
|
|
expected_evidence=list(knowledge.get("expected_evidence", [])),
|
|
controls=list(control_links or []),
|
|
how_others_do_it=str(knowledge.get("how_others_do_it", "")),
|
|
status=str(knowledge.get("status", "draft")),
|
|
disclaimer=str(knowledge.get("disclaimer", _DRAFT_DISCLAIMER)),
|
|
)
|
|
|
|
|
|
def playbooks_for_plan(
|
|
plan: OptimizationPlan,
|
|
knowledge_by_cap: Dict[str, Dict[str, Any]],
|
|
top_k: Optional[int] = None,
|
|
control_links_by_cap: Optional[Dict[str, List[str]]] = None,
|
|
) -> List[Playbook]:
|
|
"""Render playbooks for the highest-leverage measures of an OptimizationPlan (Roadmap -> How).
|
|
|
|
Walks the ranked measures (top_k, or all) and builds each capability's playbook, using the
|
|
measure's own `covers` as the regulations it closes. Measures without curated knowledge become
|
|
`missing` stubs — surfacing exactly where playbook content is still owed.
|
|
"""
|
|
links = control_links_by_cap or {}
|
|
measures = plan.ranked_measures if top_k is None else plan.ranked_measures[: max(0, top_k)]
|
|
return [
|
|
build_playbook(
|
|
m.capability_id, knowledge_by_cap.get(m.capability_id),
|
|
closes_regulations=m.covers, control_links=links.get(m.capability_id),
|
|
)
|
|
for m in measures
|
|
]
|