#!/usr/bin/env bash
# H7 FAST TRAIN · bash + pure nasm · NO python hot path · NO C glue
# Smart: precompile once · parallel check · rejoin SORT by id · finite FULL
# Law: never ML · deterministic iron · C IS LIE · Always Hostess 7 · no thrash
#
#   ./Build/h7-fast-train.sh build|run|full|status|clean
#   H7_JOBS=24 ./Build/h7-fast-train.sh full
#
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
OUT="$ROOT/out"
FAST="$OUT/h7fast"
OBJD="$FAST/obj"
BIND="$FAST/bin"
RD="$FAST/results"
TSV="$FAST/curriculum.tsv"   # id\tlimb\tmode\twant\ttitle  · title never used as path
PROG="$OUT/hostess7_train_progress.json"
JOBS="${H7_JOBS:-$(nproc 2>/dev/null || echo 8)}"
SKIP_DIRS='out|Build|KateRTX|Data|json|AMOURANTHRTX|OpenPaperWork|BlueBox|RTXLayer|heuristics'
# volatile non-det · real iron, excluded only from det FULL map
VOLATILE_NONDET='epoch|clock|clock64|rdrand|rdseed|rdtscp|rdrand_clock|rng|rng_clock|rng_hw|free_rng|heat|k10temp|fan|fan_pwm|fan_set'

mkdir -p "$OBJD" "$BIND" "$RD" "$OUT"
cmd="${1:-full}"
say() { echo "$*"; }

# ── pure nasm runner for one limb symbol ──
emit_runner() {
  local path="$1" sym="$2"
  cat >"$path" <<'ASM'
bits 64
default rel
global _start
extern __SYM__
section .bss
align 16
buf:    resb 32
section .text
_start:
    mov     rax, [rsp]
    xor     edi, edi
    cmp     rax, 2
    jl      .call
    mov     rsi, [rsp+16]
    xor     eax, eax
.atoi:
    movzx   ecx, byte [rsi]
    test    cl, cl
    jz      .atoi_done
    cmp     cl, '0'
    jb      .atoi_done
    cmp     cl, '9'
    ja      .atoi_done
    imul    eax, eax, 10
    sub     cl, '0'
    add     eax, ecx
    inc     rsi
    jmp     .atoi
.atoi_done:
    mov     edi, eax
.call:
    xor     esi, esi
    xor     edx, edx
    xor     ecx, ecx
    call    __SYM__
    mov     r8d, eax
    lea     rdi, [buf+31]
    mov     byte [rdi], 10
    dec     rdi
    mov     r9d, r8d
    test    r8d, r8d
    jns     .abs_ok
    neg     r8d
.abs_ok:
    mov     eax, r8d
    mov     ebx, 10
.itoa:
    xor     edx, edx
    div     ebx
    add     dl, '0'
    mov     [rdi], dl
    dec     rdi
    test    eax, eax
    jnz     .itoa
    test    r9d, r9d
    jns     .sign_ok
    mov     byte [rdi], '-'
    dec     rdi
.sign_ok:
    inc     rdi
    lea     rdx, [buf+32]
    sub     rdx, rdi
    mov     rsi, rdi
    mov     eax, 1
    mov     edi, 1
    syscall
    mov     eax, 60
    xor     edi, edi
    syscall
ASM
  # inject symbol (safe: limb globals are [A-Za-z0-9_]+)
  sed -i "s/__SYM__/${sym}/g" "$path"
}

ensure_tsv() {
  if [[ -f "$TSV" && -s "$TSV" ]]; then
    return 0
  fi
  local cj="$OUT/hostess7_curriculum.json"
  if [[ -f "$cj" ]]; then
    python3 - "$cj" "$TSV" <<'PY'
import json,sys
c=json.load(open(sys.argv[1]))
with open(sys.argv[2],'w') as o:
  for L in c.get('lessons') or []:
    title=(L.get('title') or '').replace('\t',' ').replace('\n',' ')
    o.write(f"{L['id']}\t{L['limb']}\t{L['mode']}\t{L['want']}\t{title}\n")
print('tsv from json', sys.argv[2])
PY
    return 0
  fi
  say "no curriculum · generating deterministic TSV via limb census"
  : >"$TSV"
  cat >>"$TSV" <<'CORE'
0	hostess7	0	7	Identity
1	hostess7	1	1	GRIN speak
2	hostess7	2	1	Know BGS
3	operate_when	0	1	When allow
4	operate_when	3	0	When deny thrash
5	operate_how	0	1	How wake
6	operate_how	1	1	How READ
7	operate_how	2	1	How BGS
8	operate_how	3	1	How BGF
9	operate_how	4	1	How BGL
10	operate_how	5	1	How SDF
11	operate_how	6	1	How SPV
12	hostess7	7	7	Kit seven
13	educate	0	7	Educate
14	actual_intel	0	7	Actual intelligence
15	grin	0	1	GRIN pole
16	grin_all	0	1	GRIN ALL
17	super_intel	0	127	SI FULL
18	super_intel	1	1	SI GRIN
19	until_grin	0	1	until GRIN
20	hostess7	8	127	Hostess FULL
CORE
  local id=21 d limb
  for d in "$ROOT"/*/; do
    limb=$(basename "$d")
    [[ "$limb" =~ ^\. ]] && continue
    [[ "$limb" =~ ^($SKIP_DIRS)$ ]] && continue
    [[ "$limb" =~ ^($VOLATILE_NONDET)$ ]] && continue
    [[ -f "$d/x86_64.asm" ]] || continue
    grep -qiE '^\s*(syscall|rdrand|rdtsc|rdseed)\b' "$d/x86_64.asm" 2>/dev/null && continue
    printf '%s\t%s\t0\t?\t%s\n' "$id" "$limb" "$limb" >>"$TSV"
    id=$((id+1))
  done
}

build_bins() {
  ensure_tsv
  say "BUILD · jobs=$JOBS · precompile limbs (nasm parallel · pure asm runners)"
  local list="$FAST/limbs.txt"
  # LC_ALL=C: en_US.UTF-8 sort -u collapses biggrin≡big_grin (underscore ignored)
  cut -f2 "$TSV" | LC_ALL=C sort -u | while read -r limb; do
    [[ -f "$ROOT/$limb/x86_64.asm" ]] && printf '%s\n' "$limb"
  done >"$list"

  # 1) nasm limbs parallel
  xargs -a "$list" -P "$JOBS" -I{} bash -c '
    ROOT="'"$ROOT"'"; OBJD="'"$OBJD"'"
    limb="$1"
    src="$ROOT/$limb/x86_64.asm"
    obj="$OBJD/$limb.o"
    [[ -f "$src" ]] || exit 0
    if [[ -f "$obj" && "$obj" -nt "$src" ]]; then exit 0; fi
    nasm -f elf64 -o "$obj" "$src" 2>/dev/null || exit 0
  ' _ {}

  # 2) emit pure-asm runners (serial emit is cheap) then link parallel
  local limb sym rasm robj obj bin
  while IFS= read -r limb; do
    [[ -f "$OBJD/$limb.o" ]] || continue
    sym=$(grep -m1 -E '^\s*global\s+\w+' "$ROOT/$limb/x86_64.asm" | awk '{print $2}')
    [[ -n "$sym" ]] || continue
    # only allow safe symbol chars
    [[ "$sym" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]] || continue
    rasm="$BIND/${limb}_runner.asm"
    if [[ ! -f "$rasm" ]] || [[ "$ROOT/$limb/x86_64.asm" -nt "$rasm" ]]; then
      emit_runner "$rasm" "$sym"
    fi
  done <"$list"

  xargs -a "$list" -P "$JOBS" -I{} bash -c '
    OBJD="'"$OBJD"'"; BIND="'"$BIND"'"
    limb="$1"
    obj="$OBJD/$limb.o"
    robj="$OBJD/${limb}_runner.o"
    rasm="$BIND/${limb}_runner.asm"
    bin="$BIND/$limb"
    [[ -f "$obj" && -f "$rasm" ]] || exit 0
    if [[ -f "$bin" && "$bin" -nt "$obj" && "$bin" -nt "$rasm" ]]; then exit 0; fi
    nasm -f elf64 -o "$robj" "$rasm" 2>/dev/null || exit 0
    ld -o "$bin" -e _start "$robj" "$obj" 2>/dev/null || exit 0
    chmod +x "$bin" 2>/dev/null || true
  ' _ {}

  # 3) probe want=? · NUL-safe · per-id files · rejoin SORT
  say "BUILD · probe wants for TSV rows with ?"
  local pd="$FAST/probe"
  rm -rf "$pd"
  mkdir -p "$pd"

  awk -F'\t' '$4=="?"{print}' "$TSV" | tr '\n' '\0' | \
  xargs -0 -P "$JOBS" -n1 bash -c '
    BIND="'"$BIND"'"; pd="'"$pd"'"
    line="$1"
    IFS=$'"'"'\t'"'"' read -r id limb mode want title <<<"$line"
    id="${id//[^0-9]/}"
    [[ -n "$id" ]] || exit 0
    bin="$BIND/$limb"
    if [[ -x "$bin" ]]; then
      a=$("$bin" "$mode" 2>/dev/null | tr -d "\r" | tail -1)
      b=$("$bin" "$mode" 2>/dev/null | tr -d "\r" | tail -1)
      if [[ "$a" == "$b" && -n "$a" ]]; then
        title=${title//$'"'"'\t'"'"'/ }
        printf "%s\t%s\t%s\t%s\t%s\n" "$id" "$limb" "$mode" "$a" "$title" >"$pd/$id"
      fi
    fi
  ' _

  local fixed="$FAST/curriculum.fixed.tsv"
  awk -F'\t' '$4!="?"{print}' "$TSV" >"$fixed"
  local f
  for f in "$pd"/*; do
    [[ -f "$f" ]] && cat "$f" >>"$fixed"
  done
  LC_ALL=C sort -n -k1,1 "$fixed" | awk -F'\t' '!seen[$1]++' >"$TSV"
  local n bins
  n=$(wc -l <"$TSV" | tr -d ' ')
  bins=$(find "$BIND" -maxdepth 1 -type f -executable ! -name '*.asm' 2>/dev/null | wc -l | tr -d ' ')
  say "BUILD done · lessons_in_tsv=$n · bins=$bins · pure nasm+ld"
}

run_parallel() {
  ensure_tsv
  local n bins
  bins=$(find "$BIND" -maxdepth 1 -type f -executable ! -name '*.asm' 2>/dev/null | wc -l | tr -d ' ')
  [[ "$bins" -gt 0 ]] || build_bins
  n=$(wc -l <"$TSV" | tr -d ' ')
  say "RUN parallel · N=$n · jobs=$JOBS · rejoin SORT · bash+nasm only"
  rm -rf "$RD"
  mkdir -p "$RD"

  # NUL-delimited full lines · id digits-only path · never title-as-path
  tr '\n' '\0' <"$TSV" | xargs -0 -P "$JOBS" -n1 bash -c '
    BIND="'"$BIND"'"; RD="'"$RD"'"
    line="$1"
    IFS=$'"'"'\t'"'"' read -r id limb mode want title <<<"$line"
    id="${id//[^0-9]/}"
    [[ -n "$id" ]] || exit 0
    bin="$BIND/$limb"
    got="ERR"
    if [[ -x "$bin" ]]; then
      got=$("$bin" "$mode" 2>/dev/null | tr -d "\r" | tail -1)
    fi
    if [[ "$got" == "$want" ]]; then
      printf "PASS\n" >"$RD/$id"
    else
      printf "FAIL got=%s want=%s limb=%s mode=%s\n" "$got" "$want" "$limb" "$mode" >"$RD/$id"
    fi
  ' _

  local pass=0 fail=0 first_fail="" i line
  while IFS= read -r line; do
    IFS=$'\t' read -r i _ <<<"$line"
    i="${i//[^0-9]/}"
    if [[ -n "$i" && -f "$RD/$i" ]] && grep -q '^PASS' "$RD/$i"; then
      pass=$((pass+1))
    else
      fail=$((fail+1))
      if [[ -z "$first_fail" ]]; then
        first_fail=$(cat "$RD/$i" 2>/dev/null || echo "missing $i")
      fi
    fi
  done <"$TSV"

  say "REJOIN · pass=$pass fail=$fail N=$n"
  if [[ "$fail" -eq 0 ]]; then
    cat >"$PROG" <<EOF
{
  "ts": "$(date -Iseconds)",
  "word": "HOSTESS7_TRAIN",
  "stage": $n,
  "title": "FULL LEARNED · fast parallel rejoin · bash+pure nasm",
  "full_learned": true,
  "full_mark": 127,
  "finite": true,
  "never_ml": true,
  "self_develop": true,
  "auto_advance": true,
  "parallel": true,
  "stack": "bash+nasm",
  "jobs": $JOBS,
  "pass": $pass,
  "fail": 0,
  "N": $n,
  "next": null,
  "law": "precompile once · parallel check · rejoin SORT · pure linear until GRIN · no C hot path"
}
EOF
    say "FULL LEARNED · mark 127|1 · N=$n · parallel bash+nasm"
    return 0
  else
    local ff_json
    ff_json=$(printf '%s' "$first_fail" | python3 -c 'import json,sys;print(json.dumps(sys.stdin.read()))' 2>/dev/null \
      || printf '"%s"' "${first_fail//\"/\\\"}")
    cat >"$PROG" <<EOF
{
  "ts": "$(date -Iseconds)",
  "word": "HOSTESS7_TRAIN",
  "stage": $pass,
  "title": "partial · first_fail",
  "full_learned": false,
  "full_mark": 127,
  "finite": true,
  "stack": "bash+nasm",
  "pass": $pass,
  "fail": $fail,
  "N": $n,
  "first_fail": $ff_json,
  "law": "rejoin SORT · fix first fail · re-run"
}
EOF
    say "NOT FULL · first_fail: $first_fail"
    return 1
  fi
}

status() {
  if [[ -f "$PROG" ]]; then cat "$PROG"; else say "no progress yet"; fi
  if [[ -f "$TSV" ]]; then say "tsv_lessons=$(wc -l <"$TSV" | tr -d ' ')"; fi
  local bins
  bins=$(find "$BIND" -maxdepth 1 -type f -executable ! -name '*.asm' 2>/dev/null | wc -l | tr -d ' ')
  say "bins=$bins jobs=$JOBS stack=bash+nasm"
}

case "$cmd" in
  build) build_bins ;;
  run|check) run_parallel ;;
  full)
    t0=$(date +%s.%N)
    build_bins
    run_parallel || true
    t1=$(date +%s.%N)
    say "ELAPSED_SEC=$(awk -v a="$t0" -v b="$t1" 'BEGIN{printf "%.3f", b-a}')"
    # exit with fail if not full
    grep -q '"full_learned": true' "$PROG" 2>/dev/null
    ;;
  status) status ;;
  clean)
    rm -rf "$FAST"
    say "cleaned $FAST"
    ;;
  *)
    echo "usage: $0 build|run|full|status|clean" >&2
    echo "  H7_JOBS=16 $0 full" >&2
    echo "  stack: bash + pure nasm/ld (no C, no python hot path)" >&2
    exit 2
    ;;
esac
