abhigyanpatwari/GitNexus · error · SandboxError

transcript artifact source is not the parent event stream

Error message

transcript artifact source is not the parent event stream

What it means

Within the validated metadata dict, the 'source' field must equal runner_sessions.PARENT_EVENT_STREAM_SOURCE ('parent-captured-stream-json'). Only transcripts the harness itself captured from the parent event stream are admissible as evidence; an agent-exported or third-party stream could have been tampered with.

Source

Thrown at eval/workflow_bench/evolve.py:334

        except OSError as exc:
            raise SandboxError(f"results artifact parent is unavailable: {current}: {exc}") from exc
        if stat.S_ISLNK(metadata.st_mode) or not stat.S_ISDIR(metadata.st_mode):
            raise SandboxError(f"results artifact parent must be a real directory: {current}")
        if transcript and stat.S_IMODE(metadata.st_mode) & 0o077:
            raise SandboxError(f"transcript artifact parent must be owner-only: {current}")
    return root / Path(*relative.parts)


def _transcript_artifact_metadata(metadata: Any) -> tuple[str, str, int]:
    """Validate transcript metadata without touching any host path."""

    if not isinstance(metadata, dict) or set(metadata) != {"path", "sha256", "bytes", "source"}:
        raise SandboxError("transcript artifact metadata must contain only path, sha256, bytes, and source")
    relative = metadata["path"]
    expected_digest = metadata["sha256"]
    expected_size = metadata["bytes"]
    if metadata["source"] != runner_sessions.PARENT_EVENT_STREAM_SOURCE:
        raise SandboxError("transcript artifact source is not the parent event stream")
    if not isinstance(relative, str) or not re.fullmatch(r"[0-9a-f]{64}", str(expected_digest)):
        raise SandboxError("transcript artifact metadata is malformed")
    if not isinstance(expected_size, int) or isinstance(expected_size, bool):
        raise SandboxError("transcript artifact byte count must be an integer")
    if expected_size < 0 or expected_size > runner.MAX_TRANSCRIPT_BYTES:
        raise SandboxError("transcript artifact exceeds the bounded run-output limit")
    return relative, expected_digest, expected_size


def _normalized_transcript_artifact_path(relative_value: str) -> str:
    """Apply the transcript path contract without touching the filesystem."""

    relative = PurePosixPath(relative_value)
    if (
        relative.is_absolute()
        or len(relative.parts) != 2
        or relative.parts[0] != "transcripts"
        or any(part in {"", ".", ".."} for part in relative.parts)

View on GitHub (pinned to d540b00184)

Solutions

  1. Set source to the exact constant value 'parent-captured-stream-json'.
  2. Import the constant rather than hard-coding: `from eval.workflow_bench.runner_sessions import PARENT_EVENT_STREAM_SOURCE`.
  3. If you genuinely have a new provenance, add and validate it as a first-class source in runner_sessions before using it.

Example fix

# before
{"path": "transcripts/r.json", "sha256": "<64hex>", "bytes": 12, "source": "agent-exported-json"}

# after
from eval.workflow_bench.runner_sessions import PARENT_EVENT_STREAM_SOURCE
row = {"path": "transcripts/r.json", "sha256": "<64hex>", "bytes": 12, "source": PARENT_EVENT_STREAM_SOURCE}
Defensive patterns

Strategy: validation

Validate before calling

from eval.workflow_bench.runner_sessions import PARENT_EVENT_STREAM_SOURCE

def source_is_parent_stream(metadata: dict) -> bool:
    return metadata.get("source") == PARENT_EVENT_STREAM_SOURCE

Type guard

from eval.workflow_bench.runner_sessions import PARENT_EVENT_STREAM_SOURCE

def has_parent_stream_source(metadata: dict) -> bool:
    return isinstance(metadata, dict) and metadata.get("source") == PARENT_EVENT_STREAM_SOURCE

Prevention

When it happens

Trigger: source = 'agent-exported-json', 'cli-transcript', an empty string, or any value other than the exact constant; a forked runner wrote transcripts with a different provenance tag.

Common situations: Mixing transcript sources; a runner fork that changed the tag; copy-paste producing a typo in the constant.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/48449cc4c9420002. Report an issue: GitHub.