\ #!/usr/bin/env bash set -euo pipefail ROOT="${1:-$(pwd)}" ROOT="$(cd "$ROOT" && pwd)" TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/graphshield-verify.XXXXXX")" trap 'rm -rf "$TMP_DIR"' EXIT required=( "README.md" "taxonomy/evaluation_taxonomy.json" "graphShieldMistral/README.md" "graphShieldMistral/assets/graph-classifier-map.png" "graphShieldMistral/examples/malware-hierarchy-result.json" "graphShieldMistral/scripts/build_graph.sh" "graphShieldMistral/scripts/build_graph.py" ) for rel in "${required[@]}"; do test -f "$ROOT/$rel" || { echo "FAIL: missing GraphShieldMistral release file: $rel" >&2 exit 1 } done grep -Fq \ 'graphShieldMistral/assets/graph-classifier-map.png' \ "$ROOT/README.md" || { echo "FAIL: model card does not reference the graph image" >&2 exit 1 } grep -Fq 'graphShieldMistral/' "$ROOT/README.md" || { echo "FAIL: model card does not link the graph code directory" >&2 exit 1 } for classifier in \ "scripts/classify_node.sh" \ "scripts/hierarchical_classify.sh"; do test -f "$ROOT/$classifier" || { echo "FAIL: direct classifier missing: $classifier" >&2 exit 1 } done python - "$ROOT/graphShieldMistral/assets/graph-classifier-map.png" <<'PY' from pathlib import Path import struct import sys path = Path(sys.argv[1]) data = path.read_bytes() assert data[:8] == b"\x89PNG\r\n\x1a\n", "invalid PNG signature" width, height = struct.unpack(">II", data[16:24]) assert width >= 1200 and height >= 700, (width, height) print(f"PASS: graph model-card image {width}x{height}") PY export PYTHONPATH="$ROOT/graphShieldMistral/src${PYTHONPATH:+:$PYTHONPATH}" bash "$ROOT/graphShieldMistral/scripts/build_graph.sh" \ --output-dir "$TMP_DIR/taxonomy" \ --title "GraphShieldMistral remote taxonomy verification" bash "$ROOT/graphShieldMistral/scripts/build_graph.sh" \ --result "$ROOT/graphShieldMistral/examples/malware-hierarchy-result.json" \ --output-dir "$TMP_DIR/scenario" \ --title "GraphShieldMistral remote scenario verification" for output in taxonomy scenario; do for rel in \ classification-network.html \ classification-network.svg \ classification-network.graphml \ classification-network.json \ classification-clusters.json; do test -s "$TMP_DIR/$output/$rel" || { echo "FAIL: graph generation did not create $output/$rel" >&2 exit 1 } done done python - "$TMP_DIR/taxonomy" "$TMP_DIR/scenario" <<'PY' from pathlib import Path import json import sys import networkx as nx taxonomy = Path(sys.argv[1]) scenario = Path(sys.argv[2]) tax_graph = nx.read_graphml(taxonomy / "classification-network.graphml") scenario_graph = nx.read_graphml(scenario / "classification-network.graphml") assert tax_graph.number_of_nodes() == 90, tax_graph.number_of_nodes() assert tax_graph.number_of_edges() >= 78, tax_graph.number_of_edges() assert scenario_graph.number_of_nodes() >= 91, scenario_graph.number_of_nodes() assert scenario_graph.number_of_edges() >= 79, scenario_graph.number_of_edges() clusters = json.loads( (scenario / "classification-clusters.json").read_text(encoding="utf-8") ) rows = clusters.get("classification_scenarios", []) assert rows, "scenario export contains no classification scenario" assert any(row.get("document_available") for row in rows), rows print( "PASS: generated taxonomy graph " f"nodes={tax_graph.number_of_nodes()} " f"edges={tax_graph.number_of_edges()}" ) print( "PASS: generated scenario graph " f"nodes={scenario_graph.number_of_nodes()} " f"edges={scenario_graph.number_of_edges()}" ) print("PASS: scenario export retains the classified input document") PY echo "PASS: GraphShieldMistral assets, direct classifier, graph code and deterministic graph generation."