#!/usr/bin/env bash # check-runtime-growth.sh — GROWTH guard for lang/runtime/el_runtime.c. # # Sibling to scripts/check-single-runtime.sh. That one guards against the file # being COPIED (a lagging fork shipped to prod and dropped learned hebb edges). # Nothing guarded against it GROWING — so it grew from 10,607 to 20,527 lines in # 3.5 months, while under an explicit commit-message promise that it was a # temporary shim about to be deleted. # # This enforces the RATCHET in lang/runtime/BUDGET: the numbers may only go down. # # It also checks two invariants that keep the multi-file runtime honest: # * every .c in lang/runtime/ is either in SOURCES or explicitly optional # * lang/install.sh's hardcoded download list matches SOURCES # # Exits non-zero on any violation. Run from anywhere; resolves the repo root. set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$ROOT" RUNTIME_DIR="lang/runtime" TARGET="$RUNTIME_DIR/el_runtime.c" BUDGET_FILE="$RUNTIME_DIR/BUDGET" SOURCES_FILE="$RUNTIME_DIR/SOURCES" FAIL=0 for f in "$TARGET" "$BUDGET_FILE" "$SOURCES_FILE"; do if [ ! -f "$f" ]; then echo "FATAL: required file missing: $f" >&2 exit 1 fi done budget() { local key="$1" sed -e 's/#.*//' "$BUDGET_FILE" | awk -v k="$key" '$1==k {print $2; found=1} END{if(!found) exit 1}' } MAX_LINES="$(budget max_lines)" || { echo "FATAL: no 'max_lines' in $BUDGET_FILE" >&2; exit 1; } MAX_ENGRAM="$(budget max_engram_fns)" || { echo "FATAL: no 'max_engram_fns' in $BUDGET_FILE" >&2; exit 1; } # --------------------------------------------------------------------------- # The message every failure prints. The guard that existed before this one told # you what was wrong but not where the code should go — so it was easy to # "fix" by arguing with the guard. This one names the destination. # --------------------------------------------------------------------------- where_it_goes() { cat >&2 <<'MSG' WHERE THE CODE ACTUALLY GOES ---------------------------- Placement is a LINK-TIME concern. The compiler cannot tell which .c a symbol came from: `builtin_arity` in el-compiler/src/codegen.el maps NAME -> ARITY INT only, the El name is emitted as the exact C symbol, and `ld` resolves it. The SHIPPED compiler already links from ten translation units — check it: nm lang/dist/platform/elc | grep -E 'T _(engram_think|vindex_insert)' So a builtin defined in a sibling .c is EXACTLY as linkable as one defined in el_runtime.c. Pick the file that owns the concern: engram store ops ......... lang/runtime/engram_store.c ANN / vector index ....... lang/runtime/engram_vindex.c geometry, priming ........ lang/runtime/engram_geometry.c reasoning operators ...... lang/runtime/engram_reason.c grounding, consistency ... lang/runtime/engram_verify.c think, stance ............ lang/runtime/engram_cognition.c No existing file owns it? Create one, add ONE line to lang/runtime/SOURCES, and every build path picks it up. Every runtime file EXCEPT el_runtime.c is deliberately uncapped. Belongs to a downstream program, not the runtime? Declare `c_source "path/to/file.c"` in that program's manifest.el — elb already links it (parse_manifest_c_sources, lang/elb.el:82). See lang/AGENTS.md "Where a new C builtin goes". MSG } # --- 1. Line-count ratchet --------------------------------------------------- LINES="$(wc -l < "$TARGET" | tr -d ' ')" if [ "$LINES" -gt "$MAX_LINES" ]; then echo "FAIL: $TARGET grew past its budget." >&2 echo " now: $LINES lines" >&2 echo " budget: $MAX_LINES lines (lang/runtime/BUDGET: max_lines)" >&2 echo " over by: $((LINES - MAX_LINES))" >&2 echo "" >&2 echo "This file is a 2026-05-03 build shim that was scheduled for deletion and" >&2 echo "never retired. It does not get to grow. Do NOT raise the budget." >&2 where_it_goes FAIL=1 fi # --- 2. Engram-concern ratchet ---------------------------------------------- # ~47.5% of el_runtime.c is engram code, and engram already owns six sibling # files. This count is the Stage 3 scoreboard: it may only go down. ENGRAM_FNS="$(grep -cE '^(static +)?[A-Za-z_][A-Za-z0-9_ *]*\b(engram|eg|cog)_[a-z0-9_]+\(' "$TARGET" || true)" if [ "$ENGRAM_FNS" -gt "$MAX_ENGRAM" ]; then echo "FAIL: new engram/eg_/cog_ function(s) added to $TARGET." >&2 echo " now: $ENGRAM_FNS definitions" >&2 echo " budget: $MAX_ENGRAM (lang/runtime/BUDGET: max_engram_fns)" >&2 echo "" >&2 echo "Engram code belongs in the six engram_*.c files that already exist." >&2 where_it_goes FAIL=1 fi # --- 3. Ratchet-down nudge (advisory, never fails) --------------------------- if [ "$LINES" -lt "$MAX_LINES" ]; then echo "NOTE: $TARGET is $((MAX_LINES - LINES)) lines under budget — lower" >&2 echo " 'max_lines' to $LINES in $BUDGET_FILE in this same commit, so the" >&2 echo " ground you gained cannot be quietly given back." >&2 fi if [ "$ENGRAM_FNS" -lt "$MAX_ENGRAM" ]; then echo "NOTE: $((MAX_ENGRAM - ENGRAM_FNS)) engram fn(s) moved out — lower" >&2 echo " 'max_engram_fns' to $ENGRAM_FNS in $BUDGET_FILE in this same commit." >&2 fi # --- 4. Every runtime .c is accounted for ------------------------------------ # A new .c that is in neither SOURCES nor the optional list will not be # compiled by any build path — it would be silently dead. Catch that here. OPTIONAL_RE='^(el_android|el_gtk4|el_lvgl|el_sdl2|el_win32|el_runtime_win32|eg_cosine_batch_strategy_ggml|vindex_bench)\.c$' mapfile -t IN_SOURCES < <(scripts/el-runtime-sources.sh) for path in "$RUNTIME_DIR"/*.c; do base="$(basename "$path")" if printf '%s\n' "${IN_SOURCES[@]}" | grep -qxF "$base"; then continue; fi if [[ "$base" =~ $OPTIONAL_RE ]]; then continue; fi echo "FAIL: $path is in neither lang/runtime/SOURCES nor the platform-optional" >&2 echo " list in this guard. It will not be compiled by any build path." >&2 echo " Add it to SOURCES (one line), or add it to OPTIONAL_RE here if it" >&2 echo " is a platform/strategy variant that is linked in deliberately." >&2 FAIL=1 done # --- 5. install.sh must not drift from SOURCES ------------------------------- # install.sh runs on machines with no repo checkout, so it cannot call # el-runtime-sources.sh and has to hardcode the list. That copy is exactly the # kind of duplicate that silently drifted before — so it is checked, not trusted. INSTALL_SH="lang/install.sh" if [ -f "$INSTALL_SH" ]; then EXPECTED="$(scripts/el-runtime-sources.sh | sort)" ACTUAL="$(sed -n '/^RUNTIME_SOURCES=(/,/^)/p' "$INSTALL_SH" \ | grep -oE '[a-z_0-9]+\.c' | sort)" if [ "$EXPECTED" != "$ACTUAL" ]; then echo "FAIL: $INSTALL_SH RUNTIME_SOURCES has drifted from $SOURCES_FILE." >&2 echo " Only in SOURCES: $(comm -23 <(echo "$EXPECTED") <(echo "$ACTUAL") | tr '\n' ' ')" >&2 echo " Only in install.sh: $(comm -13 <(echo "$EXPECTED") <(echo "$ACTUAL") | tr '\n' ' ')" >&2 echo " An SDK that ships the wrong set produces a lib/ that cannot link." >&2 FAIL=1 fi fi if [ "$FAIL" -ne 0 ]; then exit 1 fi echo "OK: el_runtime.c within budget ($LINES/$MAX_LINES lines, $ENGRAM_FNS/$MAX_ENGRAM engram fns);" echo " runtime sources accounted for; install.sh in step with SOURCES."