Source code for ralph.policy.models._artifact_contract
"""ArtifactContract Pydantic model."""
from __future__ import annotations
from typing import cast
from pydantic import Field, model_validator
from ralph.policy.models._frozen_policy_model import _FrozenPolicyModel
[docs]
class ArtifactContract(_FrozenPolicyModel):
"""Contract for an artifact type submitted by an agent at a given drain."""
drain: str = Field(..., description="Drain this artifact is submitted at")
artifact_type: str = Field(
...,
description="Artifact type identifier submitted via MCP",
)
decision_vocabulary: list[str] = Field(
default_factory=list,
description="Valid decision values for analysis artifacts",
)
prompt_template: str | None = Field(
default=None,
description="Optional custom prompt template path",
)
artifact_json_path: str | None = Field(
default=None,
description=(
"Override path for the artifact JSON file. "
"When None, falls back to '.agent/artifacts/<artifact_type>.json'."
),
)
markdown_summary_path: str | None = Field(
default=None,
description=(
"Path to the human-readable markdown summary for this artifact. "
"When set, the runner writes a markdown handoff at this path."
),
)
@model_validator(mode="before")
@classmethod
def _reject_phase_owned_fields(cls, data: object) -> object:
if not isinstance(data, dict):
return data
raw = cast("dict[str, object]", dict(data))
if "artifact_required" in raw:
raise ValueError(
"ArtifactContract.artifact_required has moved to pipeline.toml. "
"Set phases.<phase>.artifact_required instead."
)
return raw