Fix Scope evaluation crash: align property names between engine, types, and components
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Failing after 35s
CI / test-python-backend-compliance (push) Successful in 39s
CI / test-python-document-crawler (push) Successful in 27s
CI / test-python-dsms-gateway (push) Successful in 25s
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Failing after 35s
CI / test-python-backend-compliance (push) Successful in 39s
CI / test-python-document-crawler (push) Successful in 27s
CI / test-python-dsms-gateway (push) Successful in 25s
The engine used short property names (risk, complexity, assurance, composite) while the ComplianceScores interface defined (risk_score, complexity_score, assurance_need, composite_score). Components used yet another convention (riskScore, level, hardTriggers). The main crash was DEPTH_LEVEL_COLORS[decision.level] where decision.level was undefined (correct property: decision.determinedLevel). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -446,13 +446,13 @@ export default function ComplianceScopePage() {
|
|||||||
{scopeState.decision && (
|
{scopeState.decision && (
|
||||||
<>
|
<>
|
||||||
<div>
|
<div>
|
||||||
<span className="font-semibold">Level:</span> {scopeState.decision.level}
|
<span className="font-semibold">Level:</span> {scopeState.decision.determinedLevel}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="font-semibold">Score:</span> {scopeState.decision.score}
|
<span className="font-semibold">Score:</span> {scopeState.decision.scores?.composite_score}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="font-semibold">Hard Triggers:</span> {scopeState.decision.hardTriggers.length}
|
<span className="font-semibold">Hard Triggers:</span> {scopeState.decision.triggeredHardTriggers.length}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -99,18 +99,18 @@ export function ScopeDecisionTab({
|
|||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{/* Level Determination */}
|
{/* Level Determination */}
|
||||||
<div className={`${DEPTH_LEVEL_COLORS[decision.level].bg} border-2 ${DEPTH_LEVEL_COLORS[decision.level].border} rounded-xl p-6`}>
|
<div className={`${DEPTH_LEVEL_COLORS[decision.determinedLevel].bg} border-2 ${DEPTH_LEVEL_COLORS[decision.determinedLevel].border} rounded-xl p-6`}>
|
||||||
<div className="flex items-start gap-6">
|
<div className="flex items-start gap-6">
|
||||||
<div className={`flex-shrink-0 w-20 h-20 ${DEPTH_LEVEL_COLORS[decision.level].badge} rounded-xl flex items-center justify-center`}>
|
<div className={`flex-shrink-0 w-20 h-20 ${DEPTH_LEVEL_COLORS[decision.determinedLevel].badge} rounded-xl flex items-center justify-center`}>
|
||||||
<span className={`text-3xl font-bold ${DEPTH_LEVEL_COLORS[decision.level].text}`}>
|
<span className={`text-3xl font-bold ${DEPTH_LEVEL_COLORS[decision.determinedLevel].text}`}>
|
||||||
{decision.level}
|
{decision.determinedLevel}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<h2 className={`text-2xl font-bold ${DEPTH_LEVEL_COLORS[decision.level].text} mb-2`}>
|
<h2 className={`text-2xl font-bold ${DEPTH_LEVEL_COLORS[decision.determinedLevel].text} mb-2`}>
|
||||||
{DEPTH_LEVEL_LABELS[decision.level]}
|
{DEPTH_LEVEL_LABELS[decision.determinedLevel]}
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-gray-700 mb-3">{DEPTH_LEVEL_DESCRIPTIONS[decision.level]}</p>
|
<p className="text-gray-700 mb-3">{DEPTH_LEVEL_DESCRIPTIONS[decision.determinedLevel]}</p>
|
||||||
{decision.reasoning && (
|
{decision.reasoning && (
|
||||||
<p className="text-sm text-gray-600 italic">{decision.reasoning}</p>
|
<p className="text-sm text-gray-600 italic">{decision.reasoning}</p>
|
||||||
)}
|
)}
|
||||||
@@ -123,11 +123,11 @@ export function ScopeDecisionTab({
|
|||||||
<div className="bg-white rounded-xl border border-gray-200 p-6">
|
<div className="bg-white rounded-xl border border-gray-200 p-6">
|
||||||
<h3 className="text-lg font-semibold text-gray-900 mb-4">Score-Analyse</h3>
|
<h3 className="text-lg font-semibold text-gray-900 mb-4">Score-Analyse</h3>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{renderScoreBar('Risiko-Score', decision.scores.riskScore)}
|
{renderScoreBar('Risiko-Score', decision.scores.risk_score)}
|
||||||
{renderScoreBar('Komplexitäts-Score', decision.scores.complexityScore)}
|
{renderScoreBar('Komplexitäts-Score', decision.scores.complexity_score)}
|
||||||
{renderScoreBar('Assurance-Score', decision.scores.assuranceScore)}
|
{renderScoreBar('Assurance-Score', decision.scores.assurance_need)}
|
||||||
<div className="pt-4 border-t border-gray-200">
|
<div className="pt-4 border-t border-gray-200">
|
||||||
{renderScoreBar('Gesamt-Score', decision.scores.compositeScore)}
|
{renderScoreBar('Gesamt-Score', decision.scores.composite_score)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -231,16 +231,14 @@ export function ScopeDecisionTab({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Hard Triggers */}
|
{/* Hard Triggers */}
|
||||||
{decision.hardTriggers && decision.hardTriggers.length > 0 && (
|
{decision.triggeredHardTriggers && decision.triggeredHardTriggers.length > 0 && (
|
||||||
<div className="bg-white rounded-xl border border-gray-200 p-6">
|
<div className="bg-white rounded-xl border border-gray-200 p-6">
|
||||||
<h3 className="text-lg font-semibold text-gray-900 mb-4">Hard-Trigger</h3>
|
<h3 className="text-lg font-semibold text-gray-900 mb-4">Hard-Trigger</h3>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
{decision.hardTriggers.map((trigger, idx) => (
|
{decision.triggeredHardTriggers.map((trigger, idx) => (
|
||||||
<div
|
<div
|
||||||
key={idx}
|
key={idx}
|
||||||
className={`border rounded-lg overflow-hidden ${
|
className="border rounded-lg overflow-hidden border-red-300 bg-red-50"
|
||||||
trigger.matched ? 'border-red-300 bg-red-50' : 'border-gray-200 bg-gray-50'
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -248,17 +246,18 @@ export function ScopeDecisionTab({
|
|||||||
className="w-full px-4 py-3 flex items-center justify-between hover:bg-opacity-80 transition-colors"
|
className="w-full px-4 py-3 flex items-center justify-between hover:bg-opacity-80 transition-colors"
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
{trigger.matched && (
|
<svg className="w-5 h-5 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<svg className="w-5 h-5 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<path
|
||||||
<path
|
strokeLinecap="round"
|
||||||
strokeLinecap="round"
|
strokeLinejoin="round"
|
||||||
strokeLinejoin="round"
|
strokeWidth={2}
|
||||||
strokeWidth={2}
|
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
||||||
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
/>
|
||||||
/>
|
</svg>
|
||||||
</svg>
|
<span className="font-medium text-gray-900">{trigger.description}</span>
|
||||||
)}
|
<span className="text-xs px-2 py-0.5 rounded-full bg-red-200 text-red-800 font-medium">
|
||||||
<span className="font-medium text-gray-900">{trigger.label}</span>
|
Min. {trigger.minimumLevel}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<svg
|
<svg
|
||||||
className={`w-5 h-5 text-gray-500 transition-transform ${
|
className={`w-5 h-5 text-gray-500 transition-transform ${
|
||||||
@@ -279,11 +278,14 @@ export function ScopeDecisionTab({
|
|||||||
<span className="font-medium">Rechtsgrundlage:</span> {trigger.legalReference}
|
<span className="font-medium">Rechtsgrundlage:</span> {trigger.legalReference}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{trigger.matchedValue && (
|
{trigger.category && (
|
||||||
<p className="text-xs text-gray-700">
|
<p className="text-xs text-gray-700">
|
||||||
<span className="font-medium">Erfasster Wert:</span> {trigger.matchedValue}
|
<span className="font-medium">Kategorie:</span> {trigger.category}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
{trigger.requiresDSFA && (
|
||||||
|
<p className="text-xs text-orange-700 font-medium mt-1">DSFA erforderlich</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -65,26 +65,26 @@ export function ScopeOverviewTab({ scopeState, completionStats, onStartProfiling
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const levelColors = DEPTH_LEVEL_COLORS[decision.level]
|
const levelColors = DEPTH_LEVEL_COLORS[decision.determinedLevel]
|
||||||
return (
|
return (
|
||||||
<div className={`${levelColors.bg} border-2 ${levelColors.border} rounded-xl p-8 text-center`}>
|
<div className={`${levelColors.bg} border-2 ${levelColors.border} rounded-xl p-8 text-center`}>
|
||||||
<div className={`inline-flex items-center justify-center w-24 h-24 ${levelColors.badge} rounded-full mb-4`}>
|
<div className={`inline-flex items-center justify-center w-24 h-24 ${levelColors.badge} rounded-full mb-4`}>
|
||||||
<span className={`text-4xl font-bold ${levelColors.text}`}>{decision.level}</span>
|
<span className={`text-4xl font-bold ${levelColors.text}`}>{decision.determinedLevel}</span>
|
||||||
</div>
|
</div>
|
||||||
<h3 className={`text-xl font-semibold ${levelColors.text} mb-2`}>
|
<h3 className={`text-xl font-semibold ${levelColors.text} mb-2`}>
|
||||||
{DEPTH_LEVEL_LABELS[decision.level]}
|
{DEPTH_LEVEL_LABELS[decision.determinedLevel]}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-gray-600">{DEPTH_LEVEL_DESCRIPTIONS[decision.level]}</p>
|
<p className="text-gray-600">{DEPTH_LEVEL_DESCRIPTIONS[decision.determinedLevel]}</p>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderActiveHardTriggers = () => {
|
const renderActiveHardTriggers = () => {
|
||||||
if (!decision?.hardTriggers || decision.hardTriggers.length === 0) {
|
if (!decision?.hardTriggers || decision.triggeredHardTriggers.length === 0) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const activeHardTriggers = decision.hardTriggers.filter((ht) => ht.matched)
|
const activeHardTriggers = decision.triggeredHardTriggers.filter((ht) => ht.matched)
|
||||||
|
|
||||||
if (activeHardTriggers.length === 0) {
|
if (activeHardTriggers.length === 0) {
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -1051,10 +1051,10 @@ export class ComplianceScopeEngine {
|
|||||||
const composite = riskScore * 0.4 + complexityScore * 0.3 + assuranceScore * 0.3
|
const composite = riskScore * 0.4 + complexityScore * 0.3 + assuranceScore * 0.3
|
||||||
|
|
||||||
return {
|
return {
|
||||||
risk: Math.round(riskScore * 10) / 10,
|
risk_score: Math.round(riskScore * 10) / 10,
|
||||||
complexity: Math.round(complexityScore * 10) / 10,
|
complexity_score: Math.round(complexityScore * 10) / 10,
|
||||||
assurance: Math.round(assuranceScore * 10) / 10,
|
assurance_need: Math.round(assuranceScore * 10) / 10,
|
||||||
composite: Math.round(composite * 10) / 10,
|
composite_score: Math.round(composite * 10) / 10,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1276,9 +1276,9 @@ export class ComplianceScopeEngine {
|
|||||||
): ComplianceDepthLevel {
|
): ComplianceDepthLevel {
|
||||||
// Score-basiertes Level
|
// Score-basiertes Level
|
||||||
let levelFromScore: ComplianceDepthLevel
|
let levelFromScore: ComplianceDepthLevel
|
||||||
if (scores.composite <= 25) levelFromScore = 'L1'
|
if (scores.composite_score <= 25) levelFromScore = 'L1'
|
||||||
else if (scores.composite <= 50) levelFromScore = 'L2'
|
else if (scores.composite_score <= 50) levelFromScore = 'L2'
|
||||||
else if (scores.composite <= 75) levelFromScore = 'L3'
|
else if (scores.composite_score <= 75) levelFromScore = 'L3'
|
||||||
else levelFromScore = 'L4'
|
else levelFromScore = 'L4'
|
||||||
|
|
||||||
// Höchstes Level aus Triggers
|
// Höchstes Level aus Triggers
|
||||||
@@ -1650,12 +1650,12 @@ export class ComplianceScopeEngine {
|
|||||||
step: 'score_calculation',
|
step: 'score_calculation',
|
||||||
description: 'Risikobasierte Score-Berechnung aus Profiling-Antworten',
|
description: 'Risikobasierte Score-Berechnung aus Profiling-Antworten',
|
||||||
factors: [
|
factors: [
|
||||||
`Risiko-Score: ${scores.risk}/10`,
|
`Risiko-Score: ${scores.risk_score}/10`,
|
||||||
`Komplexitäts-Score: ${scores.complexity}/10`,
|
`Komplexitäts-Score: ${scores.complexity_score}/10`,
|
||||||
`Assurance-Score: ${scores.assurance}/10`,
|
`Assurance-Score: ${scores.assurance_need}/10`,
|
||||||
`Composite Score: ${scores.composite}/10`,
|
`Composite Score: ${scores.composite_score}/10`,
|
||||||
],
|
],
|
||||||
impact: `Score-basiertes Level: ${this.getLevelFromScore(scores.composite)}`,
|
impact: `Score-basiertes Level: ${this.getLevelFromScore(scores.composite_score)}`,
|
||||||
})
|
})
|
||||||
|
|
||||||
// 2. Hard Trigger Evaluation
|
// 2. Hard Trigger Evaluation
|
||||||
@@ -1675,7 +1675,7 @@ export class ComplianceScopeEngine {
|
|||||||
step: 'level_determination',
|
step: 'level_determination',
|
||||||
description: 'Finales Compliance-Level durch Maximum aus Score und Triggers',
|
description: 'Finales Compliance-Level durch Maximum aus Score und Triggers',
|
||||||
factors: [
|
factors: [
|
||||||
`Score-Level: ${this.getLevelFromScore(scores.composite)}`,
|
`Score-Level: ${this.getLevelFromScore(scores.composite_score)}`,
|
||||||
`Trigger-Level: ${this.getMaxTriggerLevel(triggers)}`,
|
`Trigger-Level: ${this.getMaxTriggerLevel(triggers)}`,
|
||||||
],
|
],
|
||||||
impact: `Finales Level: ${level}`,
|
impact: `Finales Level: ${level}`,
|
||||||
|
|||||||
Reference in New Issue
Block a user