What provenance chains must survive a model fine-tuning event?

**Date of Record:** 2026 October 26 **Scope:** Applies when an agentic session uses a model that undergoes fine-tuning (by the agent itself or by an upstream provider) and must preserve the provenance of the model's behavior, training data, and evaluation results across the fine-tuning event. Does not apply to frozen models that are never updated, or fully stateless prompts that do not accumulate model-specific state.

Core Distinction

The separation between **model version** (the identifier string, e.g., `gpt-4o-2026-10-01`) and **fine-tuning provenance chain** (the cryptographic record of what base model was used, what training data was applied, what evaluation was performed, and what behavior change was observed). Relying solely on version strings creates the **Fine-Tuning Amnesia**: a model is fine-tuned, the version string changes, but the successor cannot determine whether the fine-tuning was authorized, which data was used, or whether the model still passes the safety evaluations that the base model passed.

What Was Observed

In model-dependent agent architectures, failing to preserve fine-tuning provenance produces three primary failure modes:

  1. **Unauthorized Fine-Tune:** An attacker fine-tunes a model on adversarial data, changing its refusal behavior. The version string updates, but no provenance record exists to detect that the fine-tuning was malicious.
  2. **Data Contamination:** Fine-tuning data includes copyrighted, biased, or PII-laden content. Without provenance, the successor cannot detect the contamination and continues to propagate it.
  3. **Evaluation Regression:** The fine-tune improved the model on one task but regressed it on safety evaluations. Without a comparison to the pre-fine-tune baseline, the successor cannot detect the regression.

Recorded Elements

  1. **`base_model_hash`:** The exact hash of the base model weights from which the fine-tune was derived.
  2. **`training_data_provenance_hash`:** The cryptographic hash of the training data, including its source, license, and PII scan results.
  3. **`evaluation_baseline_comparison_receipt`:** The cryptographic proof that the fine-tuned model was evaluated against the same benchmarks as the base model, with before/after scores.
  4. **`fine_tuning_authorization_signature`:** The cryptographic signature of the principal who authorized the fine-tune, binding the change to an authorized workflow.

Condition of Validity

* **Applies when:** The model can be fine-tuned (by the agent, the provider, or an attacker), and the fine-tuning can alter behavior in ways that matter for downstream safety, accuracy, or compliance. * **Does not apply when:** The model is strictly frozen (no fine-tuning possible), or the agent's use of the model is entirely within a safe, isolated context where behavior changes have no downstream consequence.

Decision Boundary

  1. **Has the model been fine-tuned since the last verification?** If no, standard model use applies. If yes, proceed.
  2. **Is the `fine_tuning_authorization_signature` present and signed by a trusted principal?** If no, the fine-tune is unauthorized. Reject the model.
  3. **Does the `training_data_provenance_hash` match a known-good dataset?** If no, the training data may be contaminated. Reject the model.
  4. **Conversely, when can a fine-tuned model be used without full provenance?** Only when the agent's use of the model is strictly advisory (e.g., summarization, brainstorming) with no downstream action, or the fine-tune was performed in a fully isolated environment with a documented, reviewed training pipeline.

Operational Effect

  1. **Unauthorized Fine-Tune Detection:** Prevents attackers from altering model behavior via fine-tuning by requiring authorization signatures.
  2. **Contamination Containment:** Detects contaminated training data through cryptographic provenance, preventing propagation.
  3. **Evaluation Regression Prevention:** Preserves before/after evaluation baselines, catching silent safety or accuracy regressions.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class FineTuneVerdict(Enum):
    MODEL_VERIFIED = auto()
    UNAUTHORIZED_FINE_TUNE = auto()
    CONTAMINATED_TRAINING_DATA = auto()
    EVALUATION_REGRESSION = auto()

@dataclass(frozen=True)
class FineTuneRecord:
    base_model_hash: str
    fine_tuned_model_hash: str
    training_data_provenance_hash: str | None
    authorization_signature: str | None
    pre_fine_tune_score: float
    post_fine_tune_score: float

@dataclass(frozen=True)
class FineTunePolicy:
    trusted_base_models: frozenset[str]
    trusted_training_data: frozenset[str]
    min_score_retention_ratio: float

@dataclass(frozen=True)
class FineTuneManifest:
    verdict: FineTuneVerdict
    directive: str
    manifest_digest: str

class FineTuneLineageGuard:
    @staticmethod
    def _hash(data: str) -> str:
        return hashlib.sha256(data.encode("utf-8")).hexdigest()

    @classmethod
    def evaluate_fine_tune(
        cls, record: FineTuneRecord, policy: FineTunePolicy
    ) -> FineTuneManifest:
        
        # Gate 1: Base model trust
        if record.base_model_hash not in policy.trusted_base_models:
            return FineTuneManifest(
                verdict=FineTuneVerdict.UNAUTHORIZED_FINE_TUNE,
                directive=f"HALT: Base model {record.base_model_hash} not in trusted set.",
                manifest_digest=cls._hash(f"UNTRUSTED_BASE:{record.base_model_hash}")
            )

        # Gate 2: Authorization
        if not record.authorization_signature:
            return FineTuneManifest(
                verdict=FineTuneVerdict.UNAUTHORIZED_FINE_TUNE,
                directive="HALT: Fine-tune lacks authorization signature.",
                manifest_digest=cls._hash(f"NO_AUTH:{record.fine_tuned_model_hash}")
            )

        # Gate 3: Training data provenance
        if not record.training_data_provenance_hash or record.training_data_provenance_hash not in policy.trusted_training_data:
            return FineTuneManifest(
                verdict=FineTuneVerdict.CONTAMINATED_TRAINING_DATA,
                directive=f"HALT: Training data provenance {record.training_data_provenance_hash} not trusted.",
                manifest_digest=cls._hash(f"CONTAMINATED:{record.fine_tuned_model_hash}")
            )

        # Gate 4: Evaluation regression
        if record.pre_fine_tune_score > 0:
            retention = record.post_fine_tune_score / record.pre_fine_tune_score
            if retention < policy.min_score_retention_ratio:
                return FineTuneManifest(
                    verdict=FineTuneVerdict.EVALUATION_REGRESSION,
                    directive=f"HALT: Score retained {retention:.2%} < threshold {policy.min_score_retention_ratio:.2%}.",
                    manifest_digest=cls._hash(f"REGRESSION:{record.fine_tuned_model_hash}")
                )

        # Gate 5: Verified
        digest = cls._hash(json.dumps({
            "base": record.base_model_hash,
            "fine_tuned": record.fine_tuned_model_hash,
            "training": record.training_data_provenance_hash,
            "auth": record.authorization_signature
        }, sort_keys=True))
        
        return FineTuneManifest(
            verdict=FineTuneVerdict.MODEL_VERIFIED,
            directive="PROCEED: Fine-tune provenance and evaluation verified.",
            manifest_digest=digest
        )