{"record":{"id":"5978c3e6e389457e","repo":"affaan-m/ECC","slug":"label-lacks-probe-evidence","errorCode":null,"errorMessage":"{label} lacks probe evidence","messagePattern":"(.+?) lacks probe evidence","errorType":"validation","errorClass":"ContractError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/contract.py","lineNumber":53,"sourceCode":"\n\ndef _validate_numeric_evidence(value: Any, *, label: str) -> None:\n    if isinstance(value, bool):\n        raise ContractError(f\"{label} contains a boolean numeric value\")\n    if isinstance(value, (int, float)):\n        if not math.isfinite(value):\n            raise ContractError(f\"{label} contains a non-finite numeric value\")\n    elif isinstance(value, dict):\n        for nested in value.values():\n            _validate_numeric_evidence(nested, label=label)\n    elif isinstance(value, list):\n        for nested in value:\n            _validate_numeric_evidence(nested, label=label)\n\n\ndef _validate_probe_evidence(probe: Any, source_duration: float, *, label: str) -> None:\n    if not isinstance(probe, dict):\n        raise ContractError(f\"{label} lacks probe evidence\")\n    _validate_numeric_evidence(probe, label=label)\n    if probe.get(\"duration\") != source_duration:\n        raise ContractError(f\"{label} probe duration is not bound to source duration\")\n    for field in (\"sample_times\", \"scene_changes\"):\n        values = probe.get(field, [])\n        if not isinstance(values, list):\n            raise ContractError(f\"{label} has invalid {field}\")\n        for value in values:\n            _validate_media_time(value, source_duration, label=f\"{label} {field}\")\n    samples = probe.get(\"style_samples\", [])\n    if not isinstance(samples, list) or any(not isinstance(sample, dict) for sample in samples):\n        raise ContractError(f\"{label} has invalid style evidence\")\n    for sample in samples:\n        _validate_media_time(sample.get(\"time\"), source_duration, label=f\"{label} style evidence\")\n\n\ndef _sha256(path: Path) -> str:\n    if not hasattr(os, \"O_NOFOLLOW\"):","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/contract.py#L35-L71","documentation":"_validate_probe_evidence requires the probe field of an artifact receipt to be a dict (object). If probe is missing, null, or any non-object type, the validator raises 'lacks probe evidence' because media claims must be backed by structured probe data (duration, sample_times, scene_changes, style_samples).","triggerScenarios":"validate_artifact_receipt called on a receipt whose 'probe' key is absent, explicitly null, or set to a string/list instead of an object.","commonSituations":"Receipts stripped of the probe section to shrink file size, older receipt formats with a flat probe schema, hand-authored receipts that forgot the probe block, or a merge that dropped the key.","solutions":["Add a complete probe object to the receipt (duration, sample_times, scene_changes, style_samples).","Re-run the media probe step so the receipt is regenerated with its evidence attached.","Restore the probe section if a post-processing step stripped it from the receipt.","Upgrade/regenerate receipts produced by an older tool version with a different schema."],"exampleFix":"// before\n{\"artifact\": \"a.png\", \"probe\": null}\n// after\n{\"artifact\": \"a.png\", \"probe\": {\"duration\": 12.5, \"sample_times\": [0.0, 6.25], \"scene_changes\": [], \"style_samples\": []}}","handlingStrategy":"type-guard","validationCode":"def probe_present(receipt) -> bool:\n    return isinstance(receipt, dict) and isinstance(receipt.get('probe'), dict)","typeGuard":"def has_probe(obj) -> bool:\n    return isinstance(obj, dict) and isinstance(obj.get('probe'), dict)","tryCatchPattern":"try:\n    validate_artifact_receipt(receipt)\nexcept ContractError as e:\n    if 'lacks probe evidence' in str(e):\n        receipt['probe'] = run_media_probe(receipt['artifact'])\n    else:\n        raise","preventionTips":["Never strip the probe section from receipts to save space","Regenerate receipts after schema upgrades rather than patching them","Keep probe generation as a mandatory step in the receipt pipeline","Validate receipts against the full schema before distribution"],"tags":["python","validation","schema","provenance"],"backgroundTag":"empty-required-field","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}