{"record":{"id":"529adb60b5f20c2a","repo":"abhigyanpatwari/GitNexus","slug":"transcript-artifact-metadata-must-contain-only-pat","errorCode":null,"errorMessage":"transcript artifact metadata must contain only path, sha256, bytes, and source","messagePattern":"transcript artifact metadata must contain only path, sha256, bytes, and source","errorType":"exception","errorClass":"SandboxError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/evolve.py","lineNumber":329,"sourceCode":"    current = root\n    for part in relative.parts[:-1]:\n        current /= part\n        try:\n            metadata = current.lstat()\n        except OSError as exc:\n            raise SandboxError(f\"results artifact parent is unavailable: {current}: {exc}\") from exc\n        if stat.S_ISLNK(metadata.st_mode) or not stat.S_ISDIR(metadata.st_mode):\n            raise SandboxError(f\"results artifact parent must be a real directory: {current}\")\n        if transcript and stat.S_IMODE(metadata.st_mode) & 0o077:\n            raise SandboxError(f\"transcript artifact parent must be owner-only: {current}\")\n    return root / Path(*relative.parts)\n\n\ndef _transcript_artifact_metadata(metadata: Any) -> tuple[str, str, int]:\n    \"\"\"Validate transcript metadata without touching any host path.\"\"\"\n\n    if not isinstance(metadata, dict) or set(metadata) != {\"path\", \"sha256\", \"bytes\", \"source\"}:\n        raise SandboxError(\"transcript artifact metadata must contain only path, sha256, bytes, and source\")\n    relative = metadata[\"path\"]\n    expected_digest = metadata[\"sha256\"]\n    expected_size = metadata[\"bytes\"]\n    if metadata[\"source\"] != runner_sessions.PARENT_EVENT_STREAM_SOURCE:\n        raise SandboxError(\"transcript artifact source is not the parent event stream\")\n    if not isinstance(relative, str) or not re.fullmatch(r\"[0-9a-f]{64}\", str(expected_digest)):\n        raise SandboxError(\"transcript artifact metadata is malformed\")\n    if not isinstance(expected_size, int) or isinstance(expected_size, bool):\n        raise SandboxError(\"transcript artifact byte count must be an integer\")\n    if expected_size < 0 or expected_size > runner.MAX_TRANSCRIPT_BYTES:\n        raise SandboxError(\"transcript artifact exceeds the bounded run-output limit\")\n    return relative, expected_digest, expected_size\n\n\ndef _normalized_transcript_artifact_path(relative_value: str) -> str:\n    \"\"\"Apply the transcript path contract without touching the filesystem.\"\"\"\n\n    relative = PurePosixPath(relative_value)","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/evolve.py#L311-L347","documentation":"_transcript_artifact_metadata pins the admissible schema to exactly four keys: {path, sha256, bytes, source}. Extra keys (e.g. 'mtime', 'mtime_ns') or missing ones mean the row was not produced by the trusted runner, so the harness rejects it rather than guess which fields to trust.","triggerScenarios":"A results.jsonl transcript_artifacts row carries an extra field, omits one of the four, or uses a renamed key (e.g. 'size' instead of 'bytes'); a hand-edited or third-party runner wrote the row.","commonSituations":"Runner version skew after a schema change; manual edits to results.jsonl; a forked runner that adds metadata.","solutions":["Diff the row against the trusted runner's writer (runner_sessions) and align key names exactly.","Regenerate the results row with the current runner so the schema matches.","If adding a field is intended, extend the allowed set in _transcript_artifact_metadata deliberately, with review."],"exampleFix":"# before\n{\"path\": \"transcripts/r.json\", \"sha256\": \"<64hex>\", \"bytes\": 12, \"source\": \"parent-captured-stream-json\", \"mtime\": 123}\n\n# after (drop the extra key)\n{\"path\": \"transcripts/r.json\", \"sha256\": \"<64hex>\", \"bytes\": 12, \"source\": \"parent-captured-stream-json\"}","handlingStrategy":"type-guard","validationCode":"from eval.workflow_bench.evolve import _transcript_artifact_metadata  # reuse the exact check\n\nTRANSCRIPT_KEYS = {\"path\", \"sha256\", \"bytes\", \"source\"}\n\ndef transcript_metadata_shape_ok(metadata: dict) -> bool:\n    return isinstance(metadata, dict) and set(metadata) == TRANSCRIPT_KEYS","typeGuard":"TRANSCRIPT_KEYS = {\"path\", \"sha256\", \"bytes\", \"source\"}\n\ndef is_transcript_metadata(value: object) -> TypeGuard[dict]:\n    return isinstance(value, dict) and set(value) == TRANSCRIPT_KEYS","tryCatchPattern":null,"preventionTips":["Write transcript rows only via runner_sessions so the schema cannot drift.","Pin the schema in a shared constant both writer and validator import.","Reject hand-edited results.jsonl in CI."],"tags":["workflow-bench","sandbox","schema","validation","transcript","evidence"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}