Skip to content

models

models

Validation result models and data structures.

Contains the core result types used by the validation engine and consumed by the runner, prompts, and escalation layers.

Classes

ValidationResult dataclass

ValidationResult(rule, passed, actual_value=None, expected_value=None, error_message=None, checked_at=utc_now(), check_duration_ms=0.0, confidence=1.0, confidence_factors=dict(), failure_reason=None, failure_category=None, suggested_fix=None, error_type=None)

Result of a single validation check.

Attributes
confidence class-attribute instance-attribute
confidence = 1.0

Confidence in this validation result (0.0-1.0). Default 1.0 = fully confident.

confidence_factors class-attribute instance-attribute
confidence_factors = field(default_factory=dict)

Factors affecting confidence, e.g., {'file_age': 0.9, 'pattern_specificity': 0.8}.

failure_reason class-attribute instance-attribute
failure_reason = None

Semantic explanation of why validation failed.

failure_category class-attribute instance-attribute
failure_category = None

Category of failure: 'missing', 'malformed', 'incomplete', 'stale', 'error'.

suggested_fix class-attribute instance-attribute
suggested_fix = None

Hint for how to fix the issue.

error_type class-attribute instance-attribute
error_type = None

Distinguishes validation failures from validation crashes. None or 'validation_failure' = output didn't meet the rule. 'internal_error' = the validation check itself crashed.

Functions
to_dict
to_dict()

Convert to serializable dictionary.

Source code in src/marianne/execution/validation/models.py
def to_dict(self) -> ValidationDetailDict:
    """Convert to serializable dictionary."""
    return {
        "rule_type": self.rule.type,
        "description": self.rule.description,
        "path": self.rule.path,
        "pattern": self.rule.pattern,
        "passed": self.passed,
        "actual_value": self.actual_value,
        "expected_value": self.expected_value,
        "error_message": self.error_message,
        "checked_at": self.checked_at.isoformat(),
        "check_duration_ms": self.check_duration_ms,
        "confidence": self.confidence,
        "confidence_factors": self.confidence_factors,
        "failure_reason": self.failure_reason,
        "failure_category": self.failure_category,
        "suggested_fix": self.suggested_fix,
        "error_type": self.error_type,
    }
format_failure_summary
format_failure_summary()

Format failure information for prompt injection.

Source code in src/marianne/execution/validation/models.py
def format_failure_summary(self) -> str:
    """Format failure information for prompt injection."""
    if self.passed:
        return ""

    parts: list[str] = []
    if self.failure_category:
        parts.append(f"[{self.failure_category.upper()}]")
    if self.failure_reason:
        parts.append(self.failure_reason)
    if self.suggested_fix:
        parts.append(f"Fix: {self.suggested_fix}")

    return " ".join(parts)

SheetValidationResult dataclass

SheetValidationResult(sheet_num, results, rules_checked=0)

Aggregate result of all validations for a sheet.

Attributes
all_passed property
all_passed

Check if all validations passed.

passed_count property
passed_count

Count of passed validations.

failed_count property
failed_count

Count of failed validations (excluding skipped).

skipped_count property
skipped_count

Count of skipped validations (due to staged fail-fast).

executed_count property
executed_count

Count of validations that actually executed (not skipped).

pass_percentage property
pass_percentage

Percentage of validations that passed.

executed_pass_percentage property
executed_pass_percentage

Percentage of EXECUTED validations that passed.

majority_passed property
majority_passed

Returns True if >50% of validations passed.

aggregate_confidence property
aggregate_confidence

Calculate weighted aggregate confidence across all validation results.

Functions
get_passed_rules
get_passed_rules()

Get rules that passed.

Source code in src/marianne/execution/validation/models.py
def get_passed_rules(self) -> list[ValidationRule]:
    """Get rules that passed."""
    return [result.rule for result in self.results if result.passed]
get_failed_rules
get_failed_rules()

Get rules that failed.

Source code in src/marianne/execution/validation/models.py
def get_failed_rules(self) -> list[ValidationRule]:
    """Get rules that failed."""
    return [result.rule for result in self.results if not result.passed]
get_passed_results
get_passed_results()

Get results that passed.

Source code in src/marianne/execution/validation/models.py
def get_passed_results(self) -> list[ValidationResult]:
    """Get results that passed."""
    return [result for result in self.results if result.passed]
get_failed_results
get_failed_results()

Get results that failed.

Source code in src/marianne/execution/validation/models.py
def get_failed_results(self) -> list[ValidationResult]:
    """Get results that failed."""
    return [result for result in self.results if not result.passed]
to_dict_list
to_dict_list()

Convert all results to serializable list.

Source code in src/marianne/execution/validation/models.py
def to_dict_list(self) -> list[ValidationDetailDict]:
    """Convert all results to serializable list."""
    return [result.to_dict() for result in self.results]
get_semantic_summary
get_semantic_summary()

Aggregate semantic information from failed validations.

Source code in src/marianne/execution/validation/models.py
def get_semantic_summary(self) -> dict[str, Any]:
    """Aggregate semantic information from failed validations."""
    category_counts: dict[str, int] = {}
    has_semantic_info = False

    for result in self.results:
        if not result.passed and result.failure_category:
            has_semantic_info = True
            category = result.failure_category
            category_counts[category] = category_counts.get(category, 0) + 1

    dominant_category: str | None = None
    if category_counts:
        dominant_category = max(category_counts, key=lambda k: category_counts[k])

    return {
        "category_counts": category_counts,
        "dominant_category": dominant_category,
        "has_semantic_info": has_semantic_info,
        "total_failures": self.failed_count,
    }
get_actionable_hints
get_actionable_hints(limit=3)

Extract actionable hints from failed validations.

Source code in src/marianne/execution/validation/models.py
def get_actionable_hints(self, limit: int = 3) -> list[str]:
    """Extract actionable hints from failed validations."""
    hints: list[str] = []
    seen: set[str] = set()

    for result in self.results:
        if not result.passed and result.suggested_fix:
            hint = result.suggested_fix
            if len(hint) > 100:
                hint = hint[:97] + "..."

            if hint not in seen:
                seen.add(hint)
                hints.append(hint)

            if len(hints) >= limit:
                break

    return hints

FileModificationTracker

FileModificationTracker()

Tracks file mtimes before sheet execution for file_modified checks.

Source code in src/marianne/execution/validation/models.py
def __init__(self) -> None:
    self._mtimes: dict[str, float] = {}
Functions
snapshot
snapshot(paths)

Capture mtimes of files before sheet execution.

Source code in src/marianne/execution/validation/models.py
def snapshot(self, paths: list[Path]) -> None:
    """Capture mtimes of files before sheet execution."""
    for path in paths:
        path_str = str(path.resolve())
        if path.exists():
            self._mtimes[path_str] = path.stat().st_mtime
        else:
            self._mtimes[path_str] = 0.0
was_modified
was_modified(path)

Check if file was modified (or created) after snapshot.

Source code in src/marianne/execution/validation/models.py
def was_modified(self, path: Path) -> bool:
    """Check if file was modified (or created) after snapshot."""
    resolved = path.resolve()
    try:
        current_mtime = resolved.stat().st_mtime
    except (OSError, ValueError):
        return False
    original_mtime = self._mtimes.get(str(resolved), 0.0)
    return current_mtime > original_mtime
get_original_mtime
get_original_mtime(path)

Get the original mtime from snapshot.

Source code in src/marianne/execution/validation/models.py
def get_original_mtime(self, path: Path) -> float | None:
    """Get the original mtime from snapshot."""
    path_str = str(path.resolve())
    return self._mtimes.get(path_str)
clear
clear()

Clear all tracked mtimes.

Source code in src/marianne/execution/validation/models.py
def clear(self) -> None:
    """Clear all tracked mtimes."""
    self._mtimes.clear()

Functions