← Files SavvyARCHIVED FILE

skills/savvy/scripts/validators/skill_readiness.py

1.83 KB · Oct 2, 2026 · 00:28 UTC

↓ Download file

#!/usr/bin/env python3
"""Validate generic Savant skill readiness checkpoint evidence."""

from __future__ import annotations

import sys
from pathlib import Path
from typing import Any

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from checkpoints.lifecycle import validate_checkpoint_lifecycle  # noqa: E402


CHECKPOINTS = {
    "editor_readiness_checkpoint": {
        "stages": {"questions_needed", "ready"},
        "unresolved": "Required editor readiness field `{field}` is unresolved; editor cannot proceed.",
    },
    "q_and_a_intake_checkpoint": {
        "stages": {"questions_needed", "ready"},
        "unresolved": "Required Q&A context field `{field}` is unresolved; answer cannot proceed.",
    },
}


def _require_non_empty_string(errors: list[str], value: Any, field_path: str) -> None:
    if not isinstance(value, str) or not value.strip():
        errors.append(f"`{field_path}` must be a non-empty string.")


def validate_skill_readiness(evidence: dict[str, Any]) -> tuple[list[str], list[str]]:
    errors: list[str] = []
    warnings: list[str] = []

    task_type = evidence.get("task_type")
    config = CHECKPOINTS.get(task_type)
    if config is None:
        errors.append(
            "`task_type` must be `editor_readiness_checkpoint` or `q_and_a_intake_checkpoint`."
        )
        return errors, warnings

    stage = evidence.get("stage")
    if stage not in config["stages"]:
        allowed = " or ".join(f"`{value}`" for value in sorted(config["stages"]))
        errors.append(f"`stage` must be {allowed}.")
        stage = "questions_needed"

    _require_non_empty_string(errors, evidence.get("request_summary"), "request_summary")

    validate_checkpoint_lifecycle(
        errors,
        evidence,
        stage=stage,
        unresolved_error_template=config["unresolved"],
    )

    return errors, warnings

SHA-256: 9b8df624a0f500b1ce0294436fb2c754858b4d05db5e0c0031844960f00a33ea