#!/usr/bin/env bash # Shared presentation and run-directory helpers for run-raw-task.sh. now_ms() { node -p 'Date.now()'; } progress() { local run_label=$1 message=$2 printf '[%s] [%s] %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$run_label" "$message" } progress_bar() { local label=$1 completed=$2 total=$3 width=24 filled empty percent bar [ "$total" -gt 0 ] || return filled=$((completed * width / total)) empty=$((width - filled)) percent=$((completed * 100 / total)) printf -v bar '%*s' "$filled" '' bar=${bar// /#} printf -v empty '%*s' "$empty" '' empty=${empty// /-} printf '[%s] [%s%s] %d/%d (%d%%)\n' "$label" "$bar" "$empty" "$completed" "$total" "$percent" } normalize_run_component() { printf '%s' "$1" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9' '-' | sed -E 's/^-+//; s/-+$//' } run_task_label() { case "$TASK_SLUG" in 111-offer-letter-generator) printf '%s' 'task-1' ;; 222-software-dependency-audit) printf '%s' 'task-2' ;; 333-fix-build-google-auto) printf '%s' 'task-3' ;; *) printf 'task-%s' "$(normalize_run_component "$TASK_SLUG")" ;; esac } run_condition_label() { case "$SOURCE_SKILL" in */results/model-compiled-skills/*|*/dist/*|*/conditions/*|/tmp/*) printf '%s' '编译后skill' ;; *) printf '%s' '原始skill' ;; esac } reserve_run_root() { # Allocation and mkdir share one lock: concurrent attempts must never claim # the same trace/workspace directory. local prefix=$1 run_root suffix=1 lock_fd local lock_path="/tmp/skill-agent-raw-name-index.lock" mkdir -p "$PROJECT_ROOT/runs/$MODE" exec {lock_fd}>"$lock_path" flock "$lock_fd" # Do the check and the mkdir while holding the same lock. Starting at 1 # also tolerates old, interrupted runs and avoids parsing a path whose # prefix itself contains hyphens. while :; do run_root="$PROJECT_ROOT/runs/$MODE/$prefix-$suffix" if mkdir "$run_root" 2>/dev/null; then break fi suffix=$((suffix + 1)) done flock -u "$lock_fd" exec {lock_fd}>&- printf '%s' "$run_root" }