← Files MOOS-IvP SkillsARCHIVED FILE

skills/moos-ivp-eval-mission-builder/scripts/static_check_eval_mission.sh

5.03 KB · Oct 5, 2026 · 18:35 UTC

↓ Download file

#!/usr/bin/env bash
set -u

mission_dir="${1:-.}"
fail=0

search_file() {
  local pattern="$1"
  local file="$2"
  local content_cmd="sed /^[[:space:]]*\\/\\//d"
  case "$file" in
    *.sh) content_cmd="sed s/[[:space:]]*#.*$//" ;;
  esac
  if command -v rg >/dev/null 2>&1; then
    $content_cmd "$file" | rg -q -- "$pattern"
  else
    $content_cmd "$file" | grep -Eq -- "$pattern"
  fi
}

meta_files() {
  local meta="$mission_dir/meta_shoreside.moos"
  echo "$meta"
  if [ -f "$meta" ]; then
    awk '/^[[:space:]]*#include[[:space:]]+/ {
      for (i = 2; i <= NF; i++) {
        if ($i ~ /^[^<].*\.moos$/) {
          print $i
          break
        }
      }
    }' "$meta" | while read -r rel; do
      [ -f "$mission_dir/$rel" ] && echo "$mission_dir/$rel"
    done
  fi
}

need_file() {
  local rel="$1"
  if [ ! -f "$mission_dir/$rel" ]; then
    echo "FAIL missing $rel"
    fail=1
  fi
}

need_grep() {
  local pattern="$1"
  local rel="$2"
  local label="$3"
  if [ ! -f "$mission_dir/$rel" ] || ! search_file "$pattern" "$mission_dir/$rel"; then
    echo "FAIL missing $label in $rel"
    fail=1
  fi
}

need_meta_grep() {
  local pattern="$1"
  local label="$2"
  local found=0
  for file in $(meta_files); do
    if [ -f "$file" ] && search_file "$pattern" "$file"; then
      found=1
    fi
  done
  if [ "$found" -eq 0 ]; then
    echo "FAIL missing $label in meta_shoreside.moos or local includes"
    fail=1
  fi
}

meta_has() {
  local pattern="$1"
  for file in $(meta_files); do
    if [ -f "$file" ] && search_file "$pattern" "$file"; then
      return 0
    fi
  done
  return 1
}

need_file "README.md"
need_file "launch.sh"
need_file "launch_shoreside.sh"
need_file "zlaunch.sh"
need_file "meta_shoreside.moos"

has_vehicle="no"
if [ -f "$mission_dir/launch_vehicle.sh" ] ||
   [ -f "$mission_dir/meta_vehicle.moos" ] ||
   [ -f "$mission_dir/meta_vehicle.bhv" ]; then
  has_vehicle="yes"
fi

if [ "$has_vehicle" = "yes" ]; then
  need_file "launch_vehicle.sh"
fi
if [ ! -f "$mission_dir/launch_shoreside.sh" ] ||
   { [ "$has_vehicle" = "yes" ] && [ ! -f "$mission_dir/launch_vehicle.sh" ]; }; then
  echo "HINT ordinary mission launcher structure is incomplete; use the moos-ivp-mission-builder workflow before adding eval plumbing"
fi

if ! meta_has 'ProcessConfig[[:space:]]*=[[:space:]]*pAutoPoke'; then
  if meta_has 'ProcessConfig[[:space:]]*=[[:space:]]*uTimerScript'; then
    echo "WARN no pAutoPoke config found; acceptable for unit-style evals if uTimerScript or the app under test owns initialization"
  else
    echo "FAIL missing pAutoPoke or uTimerScript initialization config in meta_shoreside.moos or local includes"
    fail=1
  fi
fi
need_meta_grep 'ProcessConfig[[:space:]]*=[[:space:]]*pMissionEval' "pMissionEval config"
need_meta_grep 'result_flag[[:space:]]*=[[:space:]]*MISSION_EVALUATED[[:space:]]*=[[:space:]]*true' "MISSION_EVALUATED result flag"
need_meta_grep 'report_file[[:space:]]*=[[:space:]]*results.txt' "results.txt report file"
need_meta_grep 'report_column[[:space:]]*=.*grade=' "grade report column"
need_meta_grep 'lead_condition[[:space:]]*=' "lead condition"
need_meta_grep 'pass_condition[[:space:]]*=' "pass condition"
if meta_has 'lead_condition[[:space:]]*=.*\|\|'; then
  echo "FAIL unsupported || in lead_condition; use textual or with parenthesized operands, such as (EVENT_A = true) or (EVENT_B = true)"
  fail=1
fi
if meta_has 'report_column[[:space:]]*=.*mhash='; then
  need_meta_grep 'pMissionHash' "pMissionHash for mhash column"
fi
if [ -f "$mission_dir/targ_shoreside.moos" ] &&
   search_file 'Run[[:space:]]*=[[:space:]]*pMissionHash' "$mission_dir/targ_shoreside.moos" &&
   search_file 'Run[[:space:]]*=[[:space:]]*pMarineViewer' "$mission_dir/targ_shoreside.moos"; then
  echo "FAIL generated targ_shoreside.moos launches both pMissionHash and pMarineViewer; keep pMissionHash headless-only unless pMarineViewer mission-hash publication is disabled"
  fail=1
fi
need_grep 'xlaunch.sh' "zlaunch.sh" "xlaunch call"
need_grep '--max_time' "zlaunch.sh" "max_time support"
need_grep 'results.txt' "zlaunch.sh" "results truncation or handling"
need_grep 'grade=' "zlaunch.sh" "missing grade detection"
need_grep 'moos_scoped_teardown|scripts/moos_scoped_teardown\.sh|TEARDOWN_HELPER' "zlaunch.sh" "scoped teardown helper"

if [ -f "$mission_dir/zlaunch.sh" ]; then
  if search_file 'grade=.*>[[:space:]]*results[.]txt|printf[[:space:]].*grade=.*results[.]txt|grade_hint' "$mission_dir/zlaunch.sh"; then
    echo "FAIL zlaunch.sh appears to synthesize grade=; pMissionEval should write results.txt"
    fail=1
  fi
  if command -v rg >/dev/null 2>&1; then
    rg -n '(^|[^[:alnum:]_])(ktm|pkill|killall)([^[:alnum:]_]|$)' "$mission_dir/zlaunch.sh" >/dev/null && bad_cleanup=yes || bad_cleanup=no
  else
    grep -En '(^|[^[:alnum:]_])(ktm|pkill|killall)([^[:alnum:]_]|$)' "$mission_dir/zlaunch.sh" >/dev/null && bad_cleanup=yes || bad_cleanup=no
  fi
  if [ "$bad_cleanup" = "yes" ]; then
    echo "FAIL zlaunch.sh uses global cleanup; prefer scoped teardown"
    fail=1
  fi
fi

if [ "$fail" -eq 0 ]; then
  echo "PASS eval mission structural checks"
fi

exit "$fail"

SHA-256: 4ad07496649675299d286ad6c525405ad6e96f86d5b31912666e030d1c3afe4d