#!/usr/bin/env bash set -euo pipefail classify_live_run_failure() { local live_tail="${1:-}" local normalized normalized="$(printf '%s' "$live_tail" | tr '[:upper:]' '[:lower:]')" case "$normalized" in *"api key"*|*"database_url"*|*"must provide"*|*"未设置"*|*"permission denied"*|*"role does not exist"*|*"relation does not exist"*) printf '%s\n' 'precondition_missing' ;; *"signature_guard"*|*"unexpected status 403"*|*"unexpected status 502"*|*"unexpected status 503"*|*"unexpected status 504"*|*"no pricing cards found"*|*"no model rows parsed"*|*"no model overview cards parsed"*|*"context deadline exceeded"*|*"client.timeout"*|*"i/o timeout"*|*"tls handshake timeout"*|*"transport closed"*|*"connection reset"*|*"connection refused"*|*"no such host"*) printf '%s\n' 'external_provider_failure' ;; *) printf '%s\n' 'primary_pipeline_failure' ;; esac } [[ "$(classify_live_run_failure 'OPENROUTER_API_KEY 未设置,无法执行真实采集')" == 'precondition_missing' ]] [[ "$(classify_live_run_failure 'import_vertex_pricing: read https://cloud.google.com/...: context deadline exceeded (Client.Timeout or context cancellation while reading body)')" == 'external_provider_failure' ]] [[ "$(classify_live_run_failure 'insert report_runs failed: duplicate key value violates unique constraint')" == 'primary_pipeline_failure' ]]