feat(pipeline): store MCP fields (assertion, pass/fail criteria, check_type) in generation_metadata
- Add assertion, pass_criteria, fail_criteria, check_type to AtomicControlCandidate dataclass - Parse MCP fields from LLM output in _process_pass0b_control - Store MCP fields in generation_metadata JSON for later use by MCP scanner - Fields default to empty when not present (backward-compatible with old prompts) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -215,6 +215,11 @@ class AtomicControlCandidate:
|
|||||||
domain: str = ""
|
domain: str = ""
|
||||||
source_regulation: str = ""
|
source_regulation: str = ""
|
||||||
source_article: str = ""
|
source_article: str = ""
|
||||||
|
# MCP-taugliche Felder
|
||||||
|
assertion: str = ""
|
||||||
|
pass_criteria: list = field(default_factory=list)
|
||||||
|
fail_criteria: list = field(default_factory=list)
|
||||||
|
check_type: str = ""
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
return {
|
return {
|
||||||
@@ -229,6 +234,10 @@ class AtomicControlCandidate:
|
|||||||
"severity": self.severity,
|
"severity": self.severity,
|
||||||
"category": self.category,
|
"category": self.category,
|
||||||
"domain": self.domain,
|
"domain": self.domain,
|
||||||
|
"assertion": self.assertion,
|
||||||
|
"pass_criteria": self.pass_criteria,
|
||||||
|
"fail_criteria": self.fail_criteria,
|
||||||
|
"check_type": self.check_type,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2114,12 +2123,16 @@ Quellreferenz: {source_ref}
|
|||||||
Antworte als JSON:
|
Antworte als JSON:
|
||||||
{{
|
{{
|
||||||
"title": "Kurzer Titel (max 80 Zeichen, deutsch, HANDLUNG enthalten)",
|
"title": "Kurzer Titel (max 80 Zeichen, deutsch, HANDLUNG enthalten)",
|
||||||
|
"assertion": "Eine einzige pruefbare Aussage (wird als MCP-Suchanfrage verwendet)",
|
||||||
"objective": "Was muss erreicht werden? (1-2 Sätze)",
|
"objective": "Was muss erreicht werden? (1-2 Sätze)",
|
||||||
"requirements": ["Konkrete Anforderung 1", "Anforderung 2"],
|
"requirements": ["Konkrete Anforderung 1", "Anforderung 2"],
|
||||||
"test_procedure": ["Prüfschritt 1", "Prüfschritt 2"],
|
"test_procedure": ["Prüfschritt 1", "Prüfschritt 2"],
|
||||||
"evidence": ["Nachweis/Dokument/Artefakt 1", "Nachweis 2"],
|
"evidence": ["Nachweis/Dokument/Artefakt 1", "Nachweis 2"],
|
||||||
|
"pass_criteria": ["Wann gilt dieses Control als erfuellt?"],
|
||||||
|
"fail_criteria": ["Wann gilt dieses Control als nicht erfuellt?"],
|
||||||
"severity": "critical|high|medium|low",
|
"severity": "critical|high|medium|low",
|
||||||
"category": "security|privacy|governance|operations|finance|reporting",
|
"category": "security|privacy|governance|operations|finance|reporting",
|
||||||
|
"check_type": "technical_config_check|document_clause_check|code_pattern_check|evidence_check|interview_required",
|
||||||
"merge_key": "action_type:normalized_object:control_phase"
|
"merge_key": "action_type:normalized_object:control_phase"
|
||||||
}}"""
|
}}"""
|
||||||
|
|
||||||
@@ -2206,12 +2219,16 @@ Antworte als JSON-Objekt. Fuer JEDE Pflicht ein Key (die Pflicht-ID):
|
|||||||
Jedes Control hat dieses Format:
|
Jedes Control hat dieses Format:
|
||||||
{{
|
{{
|
||||||
"title": "Kurzer Titel (max 80 Zeichen, deutsch, HANDLUNG enthalten)",
|
"title": "Kurzer Titel (max 80 Zeichen, deutsch, HANDLUNG enthalten)",
|
||||||
|
"assertion": "Eine einzige pruefbare Aussage (wird als MCP-Suchanfrage verwendet)",
|
||||||
"objective": "Was muss erreicht werden? (1-2 Sätze)",
|
"objective": "Was muss erreicht werden? (1-2 Sätze)",
|
||||||
"requirements": ["Konkrete Anforderung 1", "Anforderung 2"],
|
"requirements": ["Konkrete Anforderung 1", "Anforderung 2"],
|
||||||
"test_procedure": ["Prüfschritt 1", "Prüfschritt 2"],
|
"test_procedure": ["Prüfschritt 1", "Prüfschritt 2"],
|
||||||
"evidence": ["Nachweis/Dokument/Artefakt 1", "Nachweis 2"],
|
"evidence": ["Nachweis/Dokument/Artefakt 1", "Nachweis 2"],
|
||||||
|
"pass_criteria": ["Wann gilt dieses Control als erfuellt?"],
|
||||||
|
"fail_criteria": ["Wann gilt dieses Control als nicht erfuellt?"],
|
||||||
"severity": "critical|high|medium|low",
|
"severity": "critical|high|medium|low",
|
||||||
"category": "security|privacy|governance|operations|finance|reporting",
|
"category": "security|privacy|governance|operations|finance|reporting",
|
||||||
|
"check_type": "technical_config_check|document_clause_check|code_pattern_check|evidence_check|interview_required",
|
||||||
"merge_key": "action_type:normalized_object:control_phase"
|
"merge_key": "action_type:normalized_object:control_phase"
|
||||||
}}"""
|
}}"""
|
||||||
|
|
||||||
@@ -2950,6 +2967,10 @@ class DecompositionPass:
|
|||||||
parsed.get("severity", obl["parent_severity"])
|
parsed.get("severity", obl["parent_severity"])
|
||||||
),
|
),
|
||||||
category=parsed.get("category", obl["parent_category"]),
|
category=parsed.get("category", obl["parent_category"]),
|
||||||
|
assertion=parsed.get("assertion", "")[:500],
|
||||||
|
pass_criteria=_ensure_list(parsed.get("pass_criteria", [])),
|
||||||
|
fail_criteria=_ensure_list(parsed.get("fail_criteria", [])),
|
||||||
|
check_type=parsed.get("check_type", ""),
|
||||||
)
|
)
|
||||||
# Store merge_key from LLM output in metadata
|
# Store merge_key from LLM output in metadata
|
||||||
llm_merge_key = parsed.get("merge_key", "")
|
llm_merge_key = parsed.get("merge_key", "")
|
||||||
@@ -3412,6 +3433,11 @@ class DecompositionPass:
|
|||||||
"framework_domain": getattr(atomic, "_framework_domain", None),
|
"framework_domain": getattr(atomic, "_framework_domain", None),
|
||||||
"framework_subcontrol_id": getattr(atomic, "_framework_subcontrol_id", None),
|
"framework_subcontrol_id": getattr(atomic, "_framework_subcontrol_id", None),
|
||||||
"decomposition_source": getattr(atomic, "_decomposition_source", "direct"),
|
"decomposition_source": getattr(atomic, "_decomposition_source", "direct"),
|
||||||
|
# MCP-taugliche Felder
|
||||||
|
"assertion": atomic.assertion or "",
|
||||||
|
"pass_criteria": atomic.pass_criteria or [],
|
||||||
|
"fail_criteria": atomic.fail_criteria or [],
|
||||||
|
"check_type": atomic.check_type or "",
|
||||||
}),
|
}),
|
||||||
"framework_id": "14b1bdd2-abc7-4a43-adae-14471ee5c7cf",
|
"framework_id": "14b1bdd2-abc7-4a43-adae-14471ee5c7cf",
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user