Spaces:
Running
Running
| # STEM BIO-AI Skill Package Structure Validator | |
| # Usage: bash validate_skill_structure.sh [SKILL_ROOT] | |
| # Validates the STEM BIO-AI skill package is complete and well-formed | |
| set -euo pipefail | |
| SKILL_ROOT="${1:-.}" | |
| ERRORS=0 | |
| WARNINGS=0 | |
| print_help() { | |
| echo "STEM BIO-AI Skill Package Structure Validator" | |
| echo "" | |
| echo "Usage: bash validate_skill_structure.sh [SKILL_ROOT]" | |
| echo "" | |
| echo " SKILL_ROOT Path to stem-ai skill directory (default: current directory)" | |
| echo "" | |
| echo "Validates: directory structure, required files, frontmatter, version consistency." | |
| } | |
| if [ "${1:-}" = "--help" ] || [ "${1:-}" = "-h" ]; then | |
| print_help | |
| exit 0 | |
| fi | |
| check_file() { | |
| local path="$1" | |
| local required="$2" | |
| if [ -f "$SKILL_ROOT/$path" ]; then | |
| echo " [OK] $path" | |
| elif [ "$required" = "required" ]; then | |
| echo " [FAIL] $path -- REQUIRED but missing" | |
| ERRORS=$((ERRORS + 1)) | |
| else | |
| echo " [WARN] $path -- recommended but missing" | |
| WARNINGS=$((WARNINGS + 1)) | |
| fi | |
| } | |
| check_dir() { | |
| local path="$1" | |
| if [ -d "$SKILL_ROOT/$path" ]; then | |
| echo " [OK] $path/" | |
| else | |
| echo " [FAIL] $path/ -- REQUIRED directory missing" | |
| ERRORS=$((ERRORS + 1)) | |
| fi | |
| } | |
| check_contains() { | |
| local path="$1" | |
| local pattern="$2" | |
| local label="$3" | |
| if grep -Fq "$pattern" "$SKILL_ROOT/$path" 2>/dev/null; then | |
| echo " [OK] $label" | |
| else | |
| echo " [FAIL] $label" | |
| ERRORS=$((ERRORS + 1)) | |
| fi | |
| } | |
| echo "=== STEM BIO-AI Skill Package Validation ===" | |
| echo "Root: $SKILL_ROOT" | |
| echo "" | |
| echo "--- Root Files ---" | |
| check_file "SKILL.md" "required" | |
| check_file "README.md" "required" | |
| check_file "LICENSE" "required" | |
| check_file "CHANGELOG.md" "required" | |
| check_file "CONTRIBUTING.md" "recommended" | |
| check_file ".gitignore" "recommended" | |
| echo "" | |
| echo "--- Required Directories ---" | |
| check_dir "spec" | |
| check_dir "discrimination" | |
| check_dir "templates" | |
| check_dir "scripts" | |
| check_dir "references" | |
| echo "" | |
| echo "--- Core Spec ---" | |
| CORE=$(find "$SKILL_ROOT/spec/" -name "STEM-AI_v*_CORE.md" 2>/dev/null | sort -V | tail -1) | |
| if [ -n "$CORE" ]; then | |
| echo " [OK] Core spec: $CORE" | |
| else | |
| echo " [FAIL] No STEM-AI_v*_CORE.md found in spec/" | |
| ERRORS=$((ERRORS + 1)) | |
| fi | |
| CORE_BASENAME=$(basename "$CORE" 2>/dev/null || true) | |
| CORE_VERSION=$(echo "$CORE_BASENAME" | sed -n 's/^STEM-AI_v\([0-9.]*\)_CORE\.md$/\1/p') | |
| echo "" | |
| echo "--- Version Drift Checks ---" | |
| if [ -n "$CORE_VERSION" ]; then | |
| echo " [INFO] Active core version: $CORE_VERSION" | |
| check_contains "templates/audit_report.md" "v$CORE_VERSION" "audit report template references v$CORE_VERSION" | |
| check_contains "templates/claim_matrix.md" "v$CORE_VERSION" "claim matrix template references v$CORE_VERSION" | |
| check_contains "templates/method_appendix.md" "v$CORE_VERSION" "method appendix references v$CORE_VERSION" | |
| check_contains "templates/errata_log.md" "v$CORE_VERSION" "errata log references v$CORE_VERSION" | |
| check_contains "CONTRIBUTING.md" "spec/STEM-AI_v${CORE_VERSION}_CORE.md" "contributing guide references current core spec" | |
| else | |
| echo " [FAIL] Could not derive core version from spec filename" | |
| ERRORS=$((ERRORS + 1)) | |
| fi | |
| MICA_YAML_SPEC=$(sed -n 's/^mica_spec: "\([0-9.]*\)"$/\1/p' "$SKILL_ROOT/memory/mica.yaml" 2>/dev/null | head -1) | |
| MICA_JSON=$(find "$SKILL_ROOT/memory/" -name "stem-ai.mica.v*.json" 2>/dev/null | sort -V | tail -1) | |
| MICA_JSON_SPEC=$(sed -n 's/^ "mica_spec": "\([0-9.]*\)",$/\1/p' "$MICA_JSON" 2>/dev/null | head -1) | |
| if [ -n "$MICA_YAML_SPEC" ] && [ -n "$MICA_JSON_SPEC" ]; then | |
| if [ "$MICA_YAML_SPEC" = "$MICA_JSON_SPEC" ]; then | |
| echo " [OK] MICA spec aligned ($MICA_YAML_SPEC)" | |
| else | |
| echo " [FAIL] MICA spec mismatch: yaml=$MICA_YAML_SPEC json=$MICA_JSON_SPEC" | |
| ERRORS=$((ERRORS + 1)) | |
| fi | |
| else | |
| echo " [WARN] Could not read MICA spec version from yaml/json" | |
| WARNINGS=$((WARNINGS + 1)) | |
| fi | |
| echo "" | |
| echo "--- Discrimination Files ---" | |
| check_file "discrimination/H1-H6_examples.md" "required" | |
| check_file "discrimination/T2_examples.md" "required" | |
| check_file "discrimination/CA_severity_examples.md" "required" | |
| check_file "discrimination/B3_COI_guide.md" "required" | |
| check_file "discrimination/G1-G5_examples.md" "required" | |
| echo "" | |
| echo "--- Templates ---" | |
| check_file "templates/audit_report.md" "required" | |
| check_file "templates/claim_matrix.md" "required" | |
| check_file "templates/executive_summary.md" "required" | |
| check_file "templates/evidence_ledger.md" "recommended" | |
| check_file "templates/method_appendix.md" "recommended" | |
| check_file "templates/document_control.md" "recommended" | |
| check_file "templates/errata_log.md" "recommended" | |
| echo "" | |
| echo "--- Scripts ---" | |
| check_file "scripts/local_analysis_scan.sh" "required" | |
| check_file "scripts/ca_detection_scan.sh" "required" | |
| check_file "scripts/snapshot_provenance.sh" "required" | |
| echo "" | |
| echo "--- References ---" | |
| check_file "references/tier_decision_table.md" "recommended" | |
| check_file "references/risk_taxonomy.md" "recommended" | |
| check_file "references/clinical_adjacent_triggers.md" "recommended" | |
| echo "" | |
| echo "=== Validation Summary ===" | |
| echo "Errors: $ERRORS" | |
| echo "Warnings: $WARNINGS" | |
| if [ "$ERRORS" -gt 0 ]; then | |
| echo "RESULT: FAIL -- $ERRORS required items missing" | |
| exit 1 | |
| else | |
| echo "RESULT: PASS ($WARNINGS warnings)" | |
| exit 0 | |
| fi | |