# c14 — adapter: import-graph rendering. Walks ALL_FILES, # resolves their import edges via collect_imports, emits a graphviz # .dot file, and (if `dot` is on PATH) renders a PNG. The boundary # call to `dot` happens here, so this file is correctly Layer 2 — # its prefix declares it as such, and the §4.4 Modeled (boundary) # rule permits filesystem + tool boundaries in Layer 2. # sama-import: a31_constants.sh # sama-import: b32_utils.sh # Emit a .dot graph of the import topology to stdout. # # Node attributes are layer-coloured so the rendered PNG makes the # layer stratification visible. Edges flow from importer → imported # (matching the natural reading direction); the .dot `rankdir=LR` # puts Layer 0 on the left and Layer 3 on the right. emit_dot() { local repo_root="$1" local src_dir="$2" echo "digraph sama {" echo " rankdir = LR;" echo " node [shape=box, style=\"rounded,filled\", fontname=\"Helvetica\"];" echo " graph [splines=ortho, nodesep=0.4];" local color_l0="#cfe8d4" local color_l1="#cfd8e8" local color_l2="#e8e0c4" local color_l3="#e8c4c4" # Nodes local f for f in "${ALL_FILES[@]}"; do if is_sama_file "$f" || is_test_file "$f"; then : else continue fi local label="${f##*/}" local info local layer="?" local color="#dddddd" if info="$(declared_layer "$f")"; then layer="$(echo "$info" | awk '{print $1}')" case "$layer" in 0) color="$color_l0" ;; 1) color="$color_l1" ;; 2) color="$color_l2" ;; 3) color="$color_l3" ;; esac fi echo " \"$f\" [label=\"$label\\nL$layer\", fillcolor=\"$color\"];" done # Edges for f in "${ALL_FILES[@]}"; do if is_sama_file "$f" || is_test_file "$f"; then : else continue fi local imp while IFS= read -r imp; do [ -z "$imp" ] && continue # Only emit edges into files we actually loaded. local found=0 local x for x in "${ALL_FILES[@]}"; do if [ "$x" = "$imp" ]; then found=1; break; fi done [ "$found" = "1" ] || continue echo " \"$f\" -> \"$imp\";" done < <(collect_imports "$f" "$repo_root") done echo "}" } # Wrapper: write .dot to a path; render PNG if dot is available. render_graph() { local repo_root="$1" local src_dir="$2" local out_dot="${3:-/tmp/sama-graph.dot}" local out_png="${4:-/tmp/sama-graph.png}" emit_dot "$repo_root" "$src_dir" > "$out_dot" echo "Wrote: $out_dot" if command -v dot > /dev/null 2>&1; then if dot -Tpng "$out_dot" -o "$out_png" 2>/dev/null; then echo "Wrote: $out_png" return 0 fi echo "warning: \`dot\` failed to render — keeping .dot only" >&2 return 0 fi echo "info: \`dot\` (graphviz) not installed — wrote .dot only" >&2 return 0 }