#!/usr/bin/env bash
# check-resident-budget.sh — resident line-count ceiling (R9 / DESIGN §7).
#
# Budgets the *container* (line count) of the framework-owned files that are
# injected into every agent's context by value — the Constitution (L0), the
# AGENTS dispatcher, and each runtime RUNTIME.md slice. Gate *wording* is never
# capped (a word cap forces paraphrasing law — the exact drift vector P3 killed);
# only the file's line count is bounded, so prose creep is caught in review.
#
# This is the CI-enforceable half of the budget. The per-harness *total* resident
# prompt (which also includes user-generated SOUL.md/USER.md and the per-tier
# slice) is summed by `mosaic doctor` as a runtime advisory — CI cannot see user
# files, so it is deliberately out of scope here (DESIGN §7).
#
# Usage:  check-resident-budget.sh [--self-test]
# Exit:   0 = all within budget · 1 = a file exceeds its ceiling · 2 = self-test failed
set -uo pipefail

FW="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)" # packages/mosaic/framework

# Per-file ceilings (lines). Headroom above current counts; tighten as files settle.
# Format: "<relative-path>:<max-lines>"
CEILINGS=(
  "defaults/CONSTITUTION.md:120"
  "defaults/AGENTS.md:120"
  "runtime/claude/RUNTIME.md:90"
  "runtime/codex/RUNTIME.md:90"
  "runtime/opencode/RUNTIME.md:90"
  "runtime/pi/RUNTIME.md:90"
)

# check_file <abs-path> <max> → echoes "<n>"; returns 0 if n<=max, 1 otherwise.
check_file() {
  local path="$1" max="$2" n
  n=$(wc -l <"$path" 2>/dev/null || echo 0)
  n=$((n + 0))
  echo "$n"
  [ "$n" -le "$max" ]
}

run_budget() {
  local fail=0 rel max abs n
  printf '%-32s %8s %8s   %s\n' "FILE" "LINES" "CEILING" "STATUS"
  for entry in "${CEILINGS[@]}"; do
    rel="${entry%%:*}"
    max="${entry##*:}"
    abs="$FW/$rel"
    if [ ! -f "$abs" ]; then
      printf '%-32s %8s %8s   %s\n' "$rel" "-" "$max" "MISSING"
      fail=1
      continue
    fi
    n=$(check_file "$abs" "$max")
    if [ "$n" -le "$max" ]; then
      printf '%-32s %8s %8s   %s\n' "$rel" "$n" "$max" "ok"
    else
      printf '%-32s %8s %8s   %s\n' "$rel" "$n" "$max" "OVER BUDGET"
      fail=1
    fi
  done
  return "$fail"
}

self_test() {
  local tmp rc
  tmp=$(mktemp)
  # 3 lines, ceiling 5 → within budget (rc 0)
  printf 'a\nb\nc\n' >"$tmp"
  check_file "$tmp" 5 >/dev/null
  rc=$?
  if [ "$rc" -ne 0 ]; then echo "self-test FAIL: under-budget file flagged"; rm -f "$tmp"; return 2; fi
  # 6 lines, ceiling 5 → over budget (rc 1)
  printf 'a\nb\nc\nd\ne\nf\n' >"$tmp"
  check_file "$tmp" 5 >/dev/null
  rc=$?
  if [ "$rc" -ne 1 ]; then echo "self-test FAIL: over-budget file not flagged"; rm -f "$tmp"; return 2; fi
  rm -f "$tmp"
  echo "self-test OK"
  return 0
}

if [ "${1:-}" = "--self-test" ]; then
  self_test
  exit $?
fi

if run_budget; then
  echo "Resident budget: all framework-owned resident files within ceiling."
  exit 0
else
  echo "Resident budget EXCEEDED — trim prose or raise the ceiling deliberately (see DESIGN §7)." >&2
  exit 1
fi
