// TezzNative tool (self-hosting scaffolding)
import "io"
import "net"
import "time"

// Unique suffix counter for Windows builds (avoid locked object collisions).
static let g_obj_uid:int = 1
static let g_startup_profile_path:str = ""
static let g_startup_profile_lane:str = ""
static let g_startup_profile_source:str = ""
static let g_startup_profile_platform:str = ""
static let g_startup_profile_vectorize:int = 0
static let g_startup_profile_pre_ms:int = 0
static let g_startup_profile_exec_ms:int = 0
static let g_startup_profile_total_ms:int = 0
static let g_startup_profile_rc:int = 0

fn streq(a:str, b:str) -> int:
  if a == 0 && b == 0:
    ret 1
  if a == 0 || b == 0:
    ret 0
  an:int = len(a)
  bn:int = len(b)
  if an != bn:
    ret 0
  i:int = 0
  while i < an:
    if a[i] != b[i]:
      ret 0
    i = i + 1
  ret 1

fn str_len(s:str) -> int:
  ret len(s)

fn str_contains(hay:str, needle:str) -> int:
  if hay == 0 || needle == 0:
    ret 0
  n:int = len(needle)
  if n == 0:
    ret 1
  i:int = 0
  while hay[i] != 0:
    j:int = 0
    while needle[j] != 0 && hay[i + j] == needle[j]:
      j = j + 1
    if needle[j] == 0:
      ret 1
    i = i + 1
  ret 0

fn str_join2(a:str, b:str) -> str:
  if a == 0:
    a = ""
  if b == 0:
    b = ""
  al:int = len(a)
  bl:int = len(b)
  out:*char = (*char)malloc(al + bl + 1)
  i:int = 0
  while i < al:
    out[i] = a[i]
    i = i + 1
  j:int = 0
  while j < bl:
    out[i + j] = b[j]
    j = j + 1
  out[al + bl] = 0 as char
  ret out

fn str_join3(a:str, b:str, c:str) -> str:
  if a == 0:
    a = ""
  if b == 0:
    b = ""
  if c == 0:
    c = ""
  al:int = len(a)
  bl:int = len(b)
  cl:int = len(c)
  out:*char = (*char)malloc(al + bl + cl + 1)
  i:int = 0
  while i < al:
    out[i] = a[i]
    i = i + 1
  j:int = 0
  while j < bl:
    out[i + j] = b[j]
    j = j + 1
  k:int = 0
  while k < cl:
    out[i + j + k] = c[k]
    k = k + 1
  out[al + bl + cl] = 0 as char
  ret out

fn maybe_free(s:str) -> int:
  if s != 0:
    free(s)
  ret 0

fn quote_cmd_path(p:str) -> str:
  if p == 0:
    ret 0 as str
  // already quoted
  if p[0] == (34 as char):
    ret str_join2("", p)
  i:int = 0
  while p[i] != 0:
    c:int = p[i] as int
    if c == 32 || c == 9:
      q1:str = str_join2("\"", p)
      q2:str = str_join2(q1, "\"")
      free(q1)
      ret q2
    i = i + 1
  ret str_join2("", p)

fn tezzc_override_arg() -> str:
  i:int = 0
  while i < args_count():
    a:str = arg(i)
    if streq(a, "--tezzc") && (i + 1) < args_count():
      ret arg(i + 1)
    if starts_with(a, "--tezzc=") != 0:
      ret a + 8
    i = i + 1
  ret 0 as str

fn sdk_root_arg() -> str:
  i:int = 0
  while i < args_count():
    a:str = arg(i)
    if streq(a, "--sdk-root") && (i + 1) < args_count():
      ret arg(i + 1)
    if starts_with(a, "--sdk-root=") != 0:
      ret a + 11
    i = i + 1
  ret 0 as str

fn path_join(root:str, rel:str) -> str:
  if root == 0:
    ret str_join2("", rel)
  if rel == 0:
    ret str_join2("", root)
  n:int = len(root)
  if n > 0:
    c:int = root[n - 1] as int
    if c == 47 || c == 92:
      ret str_join2(root, rel)
  ret str_join3(root, "/", rel)

fn hidden_arg_key(a:str) -> int:
  if a == 0:
    ret 0
  if streq(a, "--tezzc") != 0 || starts_with(a, "--tezzc=") != 0:
    ret 1
  if streq(a, "--sdk-root") != 0 || starts_with(a, "--sdk-root=") != 0:
    ret 1
  ret 0

fn user_args_count() -> int:
  i:int = 0
  n:int = args_count()
  while i < n:
    a:str = arg(i)
    if hidden_arg_key(a) != 0:
      ret i
    i = i + 1
  ret n

fn dup_lit(s:str) -> str:
  if s == 0:
    ret 0 as str
  ret str_join2("", s)

fn win_fix_cmd_slash(cmd:str) -> str:
  if cmd == 0:
    ret 0 as str
  n:int = len(cmd)
  out:*char = (*char)malloc(n + 1)
  i:int = 0
  while i < n:
    c:int = cmd[i] as int
    if c == 47:
      out[i] = 92 as char
    else:
      out[i] = cmd[i]
    i = i + 1
  out[n] = 0 as char
  ret out

fn url_dir(u:str) -> str:
  if u == 0:
    ret 0 as str
  n:int = len(u)
  if n == 0:
    ret str_join2(u, "/")
  i:int = n - 1
  while i >= 0:
    if u[i] == 47:
      ret substr_dup(u, 0, i + 1)
    i = i - 1
  // no slash
  ret str_join2(u, "/")

fn is_space(c:int) -> int:
  ret c == 32 || c == 9 || c == 13 || c == 10

fn starts_with(s:str, pre:str) -> int:
  if s == 0 || pre == 0:
    ret 0
  sn:int = len(s)
  pn:int = len(pre)
  if pn > sn:
    ret 0
  i:int = 0
  while i < pn:
    if s[i] != pre[i]:
      ret 0
    i = i + 1
  ret 1

fn starts_with_at(s:str, off:int, pre:str) -> int:
  if s == 0 || pre == 0:
    ret 0
  if off < 0:
    ret 0
  sn:int = len(s)
  pn:int = len(pre)
  if off > sn:
    ret 0
  if (off + pn) > sn:
    ret 0
  seg:str = substr_dup(s, off, off + pn)
  ok:int = 0
  if seg != 0:
    if strcmp(seg, pre) == 0:
      ok = 1
  free(seg)
  ret ok

fn substr_dup(s:str, a:int, b:int) -> str:
  if s == 0:
    ret 0 as str
  slen:int = len(s)
  st:int = a
  en:int = b
  if st < 0:
    st = 0
  if st > slen:
    st = slen
  if en < st:
    en = st
  if en > slen:
    en = slen
  n:int = en - st
  out:*char = malloc(n + 1)
  if out == 0:
    ret 0 as str
  if n > 0:
    unsafe:
      memcpy(out, (s as *char) + st, n)
  out[n] = 0 as char
  ret out as str

fn path_basename_no_ext(p:str) -> str:
  if p == 0:
    ret 0 as str
  n:int = len(p)
  if n == 0:
    ret substr_dup(p, 0, 0)
  i:int = n - 1
  while i >= 0:
    c:int = p[i] as int
    if c == 47 || c == 92:
      break
    i = i - 1
  start:int = i + 1
  end:int = n
  if n >= 3:
    if p[n-3] == 46 && p[n-2] == 116 && p[n-1] == 110:
      end = n - 3
  if end < start:
    end = start
  ret substr_dup(p, start, end)

fn ensure_dir(path:str) -> int:
  if path == 0:
    ret 0 - 1
  if path_exists(path) != 0:
    if path_is_dir(path) != 0:
      ret 0
    ret 0 - 1
  ret mkdir(path)

fn mod_get_value(mod:str, key:str) -> str:
  if mod == 0 || key == 0:
    ret 0 as str
  scan:str = str_join2("", mod)
  key2:str = str_join2("", key)
  if scan == 0 || key2 == 0:
    if scan != 0:
      free(scan)
    if key2 != 0:
      free(key2)
    ret 0 as str
  i:int = 0
  line:int = 0
  while 1:
    c:int = scan[i] as int
    if c == 0 || c == 10:
      end:int = i
      s:int = line
      while s < end && (scan[s] == 32 || scan[s] == 9):
        s = s + 1
      if starts_with_at(scan, s, key2) != 0:
        k:int = len(key2)
        t:int = s + k
        while t < end && (scan[t] == 32 || scan[t] == 9):
          t = t + 1
        if t < end && scan[t] == 61:
          t = t + 1
          while t < end && (scan[t] == 32 || scan[t] == 9):
            t = t + 1
          u:int = end
          while u > t && (scan[u-1] == 32 || scan[u-1] == 9 || scan[u-1] == 13):
            u = u - 1
          if u > t:
            outv:str = substr_dup(scan, t, u)
            free(key2)
            free(scan)
            ret outv
      if c == 0:
        break
      line = i + 1
    i = i + 1
  free(key2)
  free(scan)
  ret 0 as str

fn crc32_bytes(buf:*char, n:int) -> int:
  if buf == 0 || n <= 0:
    ret 0
  // Stable 32-bit hash for lock/check metadata.
  // Uses a djb2-style mixer to avoid wide unsigned constant portability issues.
  h:int = 5381
  i:int = 0
  while i < n:
    b:int = 0
    unsafe:
      b = buf[i] as int
    b = b & 255
    h = ((h << 5) + h + b) & 2147483647
    i = i + 1
  ret h

fn crc32_str(s:str) -> int:
  if s == 0:
    ret 0
  s2:str = str_join2("", s)
  if s2 == 0:
    ret 0
  n:int = len(s2)
  h:int = 5381
  i:int = 0
  while i < n:
    b:int = s2[i] as int
    b = b & 255
    h = ((h << 5) + h + b) & 2147483647
    i = i + 1
  free(s2)
  ret h

fn hex8(x:int) -> str:
  u:int = x
  if u < 0:
    u = u + 4294967296
  out:*char = (*char)malloc(9)
  i:int = 0
  while i < 8:
    sh:int = (7 - i) * 4
    nib:int = (u >> sh) & 15
    c:int = 0
    if nib < 10:
      c = 48 + nib
    else:
      c = 55 + nib
    out[i] = c as char
    i = i + 1
  out[8] = 0 as char
  ret out

fn hex64_pair(hi:int, lo:int) -> str:
  s1:str = hex8(hi)
  s2:str = hex8(lo)
  out:str = str_join2(s1, s2)
  free(s1); free(s2)
  ret out

fn rd_u16(buf:*char, off:int) -> int:
  if buf == 0:
    ret 0
  b0:int = 0
  b1:int = 0
  unsafe:
    b0 = buf[off] as int
    b1 = buf[off + 1] as int
  if b0 < 0:
    b0 = b0 + 256
  if b1 < 0:
    b1 = b1 + 256
  ret b0 | (b1 << 8)

fn rd_u32(buf:*char, off:int) -> int:
  if buf == 0:
    ret 0
  b0:int = 0
  b1:int = 0
  b2:int = 0
  b3:int = 0
  unsafe:
    b0 = buf[off] as int
    b1 = buf[off + 1] as int
    b2 = buf[off + 2] as int
    b3 = buf[off + 3] as int
  if b0 < 0:
    b0 = b0 + 256
  if b1 < 0:
    b1 = b1 + 256
  if b2 < 0:
    b2 = b2 + 256
  if b3 < 0:
    b3 = b3 + 256
  ret b0 | (b1 << 8) | (b2 << 16) | (b3 << 24)

fn dbg_elf_kernel(path:str):
  if path == 0:
    ret
  buf:*char = read_file(path)
  if buf == 0:
    ret
  magic0:int = 0
  magic1:int = 0
  magic2:int = 0
  magic3:int = 0
  unsafe:
    magic0 = buf[0] as int
    magic1 = buf[1] as int
    magic2 = buf[2] as int
    magic3 = buf[3] as int
  if magic0 < 0:
    magic0 = magic0 + 256
  if magic1 < 0:
    magic1 = magic1 + 256
  if magic2 < 0:
    magic2 = magic2 + 256
  if magic3 < 0:
    magic3 = magic3 + 256
  if magic0 != 127:
    say "elf: bad magic"
    free(buf)
    ret
  if magic1 != 69:
    say "elf: bad magic"
    free(buf)
    ret
  if magic2 != 76:
    say "elf: bad magic"
    free(buf)
    ret
  if magic3 != 70:
    say "elf: bad magic"
    free(buf)
    ret
  entry_lo:int = rd_u32(buf, 24)
  entry_hi:int = rd_u32(buf, 28)
  phoff_lo:int = rd_u32(buf, 32)
  phoff_hi:int = rd_u32(buf, 36)
  phentsz:int = rd_u16(buf, 54)
  phnum:int = rd_u16(buf, 56)
  entry_hex:str = hex64_pair(entry_hi, entry_lo)
  phoff_hex:str = hex64_pair(phoff_hi, phoff_lo)
  msg1:str = str_join3("elf: entry=0x", entry_hex, " phoff=0x")
  msg2:str = str_join3(msg1, phoff_hex, " phnum=")
  pns:str = int_to_str(phnum)
  msg3:str = str_join2(msg2, pns)
  say msg3
  io.write_all("build/boot/elf_dbg.txt", msg3)
  free(entry_hex); free(phoff_hex); free(pns); free(msg1); free(msg2); free(msg3)
  if phnum > 0:
    if phentsz >= 56:
    // Dump first program header (ELF64).
      ph0:int = phoff_lo
      p_type:int = rd_u32(buf, ph0 + 0)
      p_flags:int = rd_u32(buf, ph0 + 4)
      p_off_lo:int = rd_u32(buf, ph0 + 8)
      p_off_hi:int = rd_u32(buf, ph0 + 12)
      p_vaddr_lo:int = rd_u32(buf, ph0 + 16)
      p_vaddr_hi:int = rd_u32(buf, ph0 + 20)
      p_paddr_lo:int = rd_u32(buf, ph0 + 24)
      p_paddr_hi:int = rd_u32(buf, ph0 + 28)
      p_filesz_lo:int = rd_u32(buf, ph0 + 32)
      p_filesz_hi:int = rd_u32(buf, ph0 + 36)
      p_memsz_lo:int = rd_u32(buf, ph0 + 40)
      p_memsz_hi:int = rd_u32(buf, ph0 + 44)
      tstr:str = int_to_str(p_type)
      off_hex:str = hex64_pair(p_off_hi, p_off_lo)
      v_hex:str = hex64_pair(p_vaddr_hi, p_vaddr_lo)
      pa_hex:str = hex64_pair(p_paddr_hi, p_paddr_lo)
      fs_hex:str = hex64_pair(p_filesz_hi, p_filesz_lo)
      ms_hex:str = hex64_pair(p_memsz_hi, p_memsz_lo)
      msga:str = str_join3("elf: ph0 type=", tstr, " off=0x")
      msgb:str = str_join3(msga, off_hex, " vaddr=0x")
      msgc:str = str_join3(msgb, v_hex, " paddr=0x")
      msgd:str = str_join3(msgc, pa_hex, " filesz=0x")
      msge:str = str_join3(msgd, fs_hex, " memsz=0x")
      msgf:str = str_join2(msge, ms_hex)
      say msgf
      prev:str = io.read_all("build/boot/elf_dbg.txt")
      if prev != 0:
        tmp:str = str_join3(prev, "\n", msgf)
        io.write_all("build/boot/elf_dbg.txt", tmp)
        free(tmp)
        free(prev)
      else:
        io.write_all("build/boot/elf_dbg.txt", msgf)
      free(tstr); free(off_hex); free(v_hex); free(pa_hex); free(fs_hex); free(ms_hex)
      free(msga); free(msgb); free(msgc); free(msgd); free(msge); free(msgf)
  free(buf)

fn parse_hex(s:str) -> int:
  if s == 0:
    ret 0
  i:int = 0
  v:int = 0
  while s[i] != 0:
    c:int = s[i] as int
    d:int = 0 - 1
    if c >= 48 && c <= 57:
      d = c - 48
    else:
      if c >= 65 && c <= 70:
        d = c - 65 + 10
      else:
        if c >= 97 && c <= 102:
          d = c - 97 + 10
    if d < 0:
      break
    v = (v << 4) | d
    v = v & 4294967295
    i = i + 1
  ret v

fn is_hex_digit(c:int) -> int:
  if c >= 48 && c <= 57:
    ret 1
  if c >= 65 && c <= 70:
    ret 1
  if c >= 97 && c <= 102:
    ret 1
  ret 0

fn is_hex8(s:str) -> int:
  if s == 0:
    ret 0
  i:int = 0
  while s[i] != 0:
    if is_hex_digit(s[i] as int) == 0:
      ret 0
    i = i + 1
  ret i == 8

fn parse_i64(s:str) -> int:
  if s == 0:
    ret 0
  s2:str = str_join2("", s)
  if s2 == 0:
    ret 0
  i:int = 0
  sign:int = 1
  if s2[0] == 45:
    sign = 0 - 1
    i = 1
  v:int = 0
  while s2[i] != 0:
    c:int = s2[i] as int
    if c < 48 || c > 57:
      break
    v = v * 10 + (c - 48)
    i = i + 1
  free(s2)
  ret v * sign

fn int_to_str(x:int) -> str:
  neg:int = 0
  v:int = x
  if v < 0:
    neg = 1
    v = 0 - v
  buf:[char;32]
  i:int = 0
  if v == 0:
    buf[i] = 48 as char
    i = i + 1
  while v > 0:
    d:int = v % 10
    buf[i] = (48 + d) as char
    i = i + 1
    v = v / 10
  if neg != 0:
    buf[i] = 45 as char
    i = i + 1
  out:*char = (*char)malloc(i + 1)
  j:int = 0
  while j < i:
    out[j] = buf[i - 1 - j]
    j = j + 1
  out[i] = 0 as char
  ret out

fn meta_find_value(line:str, key:str) -> str:
  if line == 0 || key == 0:
    ret 0 as str
  line2:str = str_join2("", line)
  key2:str = str_join2("", key)
  if line2 == 0 || key2 == 0:
    if line2 != 0:
      free(line2)
    if key2 != 0:
      free(key2)
    ret 0 as str
  kn:int = len(key2)
  i:int = 0
  while line2[i] != 0:
    if (i == 0 || is_space(line2[i - 1] as int) != 0) && starts_with_at(line2, i, key2) != 0:
      j:int = i + kn
      while line2[j] != 0 && is_space(line2[j] as int) == 0:
        j = j + 1
      outv:str = substr_dup(line2, i + kn, j)
      free(line2)
      free(key2)
      ret outv
    i = i + 1
  free(line2)
  free(key2)
  ret 0 as str

fn meta_signature_hex(payload_hex:str, line_n:int, sign_key:str) -> str:
  has_key:int = 0
  if sign_key != 0:
    if sign_key[0] != 0:
      has_key = 1
  if has_key == 0:
    ret substr_dup("none", 0, 4)
  ln:str = int_to_str(line_n)
  p0:str = str_join3(payload_hex, "|", ln)
  p1:str = str_join3(p0, "|", sign_key)
  sig:str = hex8(crc32_str(p1))
  free(ln)
  free(p0)
  free(p1)
  ret sig

fn provenance_meta_line(kind:str, payload:str, line_n:int) -> str:
  crc:int = crc32_str(payload)
  payload_hex:str = hex8(crc)
  sign_key:str = env_value("TEZZ_SIGN_KEY")
  key_id:str = substr_dup("none", 0, 4)
  has_key:int = 0
  if sign_key != 0:
    if sign_key[0] != 0:
      has_key = 1
  if has_key != 0:
    free(key_id)
    key_id = hex8(crc32_str(sign_key))
  sig:str = meta_signature_hex(payload_hex, line_n, sign_key)
  ln:str = int_to_str(line_n)
  p0:str = str_join3("# ", kind, " v1 ")
  p1:str = str_join3(p0, "lines=", ln)
  p2:str = str_join3(p1, " payload=", payload_hex)
  p3:str = str_join3(p2, " key=", key_id)
  out:str = str_join3(p3, " sig=", sig)
  free(payload_hex)
  free(key_id)
  free(sig)
  free(ln)
  free(p0)
  free(p1)
  free(p2)
  free(p3)
  if sign_key != 0:
    free(sign_key)
  ret out

fn release_sign_key() -> str:
  k1:str = env_value("TEZZ_RELEASE_SIGN_KEY")
  if k1 != 0:
    if k1[0] != 0:
      ret k1
    free(k1)
  k2:str = env_value("TEZZ_SIGN_KEY")
  if k2 != 0:
    if k2[0] != 0:
      ret k2
    free(k2)
  if path_exists("build/release_sign.key") != 0:
    k3raw:str = io.read_all("build/release_sign.key")
    if k3raw != 0:
      k3:str = trim_line(k3raw)
      if k3[0] != 0:
        ret str_join2(k3, "")
  ret 0 as str

fn release_meta_line(payload:str, line_n:int, sign_key:str) -> str:
  payload_hex:str = hex8(crc32_str(payload))
  key_id:str = substr_dup("none", 0, 4)
  has_key:int = 0
  if sign_key != 0:
    if sign_key[0] != 0:
      has_key = 1
  if has_key != 0:
    free(key_id)
    key_id = hex8(crc32_str(sign_key))
  sig:str = meta_signature_hex(payload_hex, line_n, sign_key)
  ln:str = int_to_str(line_n)
  p0:str = str_join3("# ", "release-meta", " v1 ")
  p1:str = str_join3(p0, "lines=", ln)
  p2:str = str_join3(p1, " payload=", payload_hex)
  p3:str = str_join3(p2, " key=", key_id)
  out:str = str_join3(p3, " sig=", sig)
  free(payload_hex)
  free(key_id)
  free(sig)
  free(ln)
  free(p0)
  free(p1)
  free(p2)
  free(p3)
  ret out

fn release_append_artifact(payload:*str, line_n:*int, path:str) -> int:
  if path == 0:
    ret 0
  if path[0] == 0:
    ret 0
  if path_exists(path) == 0:
    ret 0
  sz:int = file_size(path)
  crc:int = crc32_file(path)
  szs:str = int_to_str(sz)
  csum:str = hex8(crc)
  p0:str = str_join3(path, " ", szs)
  line:str = str_join3(p0, " ", csum)
  p1:str = 0 as str
  if *payload == 0:
    p1 = str_join3(line, "\n", "")
  else:
    p1 = str_join3(*payload, line, "\n")
    free(*payload)
  *payload = p1
  *line_n = *line_n + 1
  free(szs)
  free(csum)
  free(p0)
  free(line)
  ret 0

fn release_write_manifest(out_path:str, require_sign:int, quiet:int, sign_key_override:str) -> int:
  if out_path == 0 || out_path[0] == 0:
    say "release-artifacts: missing output path"
    ret 0 - 1
  dbg:int = 0
  dbg_v:str = env_value("TEZZ_RELEASE_ARTIFACTS_TRACE")
  if dbg_v != 0:
    if dbg_v[0] != 0 && dbg_v[0] != 48:
      dbg = 1
    free(dbg_v)
  if dbg != 0:
    say "ra: begin"
  payload:str = 0 as str
  line_n:int = 0

  release_append_artifact(&payload, &line_n, "tezz")
  release_append_artifact(&payload, &line_n, "tezz.cmd")
  release_append_artifact(&payload, &line_n, "tezz.ps1")
  release_append_artifact(&payload, &line_n, "tools/tezz.tn")
  release_append_artifact(&payload, &line_n, "CMakeLists.txt")
  release_append_artifact(&payload, &line_n, "tezz.mod")
  release_append_artifact(&payload, &line_n, "tezz.lock")
  release_append_artifact(&payload, &line_n, "docs/LANGUAGE_SPEC.md")
  release_append_artifact(&payload, &line_n, "docs/v1_release.md")
  release_append_artifact(&payload, &line_n, "docs/native_exe_plan.md")
  release_append_artifact(&payload, &line_n, "docs/security_response_policy.md")
  release_append_artifact(&payload, &line_n, "docs/release_candidate_runbook.md")
  release_append_artifact(&payload, &line_n, "docs/m8_platform_ga_runbook.md")
  release_append_artifact(&payload, &line_n, "docs/m8_platform_ga_signoff.md")
  release_append_artifact(&payload, &line_n, "docs/lts_compatibility_policy.md")
  release_append_artifact(&payload, &line_n, "tests/gui_manifest.tnx")
  release_append_artifact(&payload, &line_n, "tests/gui_check_manifest.tnx")
  release_append_artifact(&payload, &line_n, "tests/gui_event_bridge.tn")
  release_append_artifact(&payload, &line_n, "tests/gui_tree_lifecycle.tn")
  release_append_artifact(&payload, &line_n, "tests/gui_caps_host.tn")
  release_append_artifact(&payload, &line_n, "tests/gui_window_smoke.tn")
  release_append_artifact(&payload, &line_n, "tests/gui_ime_state.tn")
  release_append_artifact(&payload, &line_n, "tests/gui_wm_runtime.tn")
  release_append_artifact(&payload, &line_n, "tests/gui_compile_contract.tn")
  release_append_artifact(&payload, &line_n, "tests/gui_tzui_compile.tn")
  release_append_artifact(&payload, &line_n, "tests/gui_tnui_controls_compile.tn")
  release_append_artifact(&payload, &line_n, "tests/gui_wm_compile_contract.tn")
  release_append_artifact(&payload, &line_n, "examples/gui_first_app.tn")
  release_append_artifact(&payload, &line_n, "tests/runtime_call_multiarg.tn")
  release_append_artifact(&payload, &line_n, "bench/perf_baseline_m6.tnx")
  release_append_artifact(&payload, &line_n, "bench/perf_baseline_tznum.tnx")
  release_append_artifact(&payload, &line_n, "bench/perf_compare_matrix.tnx")
  release_append_artifact(&payload, &line_n, "bench/tezz_bench_sum.tn")
  release_append_artifact(&payload, &line_n, "bench/tezz_bench_fib.tn")
  release_append_artifact(&payload, &line_n, "bench/external_manifest.tnx")
  release_append_artifact(&payload, &line_n, "bench/external/bench_sum.py")
  release_append_artifact(&payload, &line_n, "bench/external/bench_fib.py")
  release_append_artifact(&payload, &line_n, "bench/external/bench_sum.c")
  release_append_artifact(&payload, &line_n, "bench/external/bench_fib.c")
  release_append_artifact(&payload, &line_n, "bench/external/run_c_bench_sum.sh")
  release_append_artifact(&payload, &line_n, "bench/external/run_c_bench_fib.sh")
  release_append_artifact(&payload, &line_n, "bench/micro_tznum_matmul_nn.tn")
  release_append_artifact(&payload, &line_n, "bench/micro_tznum_rmsnorm_nn.tn")
  release_append_artifact(&payload, &line_n, "bench/c/tznum_native_parity.c")
  release_append_artifact(&payload, &line_n, "tools/m6_perf_gate.sh")
  release_append_artifact(&payload, &line_n, "tools/tznum_native_parity_gate.sh")
  release_append_artifact(&payload, &line_n, "tools/tznum_perf_gate.sh")
  release_append_artifact(&payload, &line_n, "tools/m8_platform_ga_gate.sh")
  release_append_artifact(&payload, &line_n, "tools/runtime_io_gate.sh")
  release_append_artifact(&payload, &line_n, "tools/simple_mode_gate.sh")
  release_append_artifact(&payload, &line_n, "tools/startup_latency_gate.sh")
  release_append_artifact(&payload, &line_n, "tools/tier1_perf_gate.sh")
  release_append_artifact(&payload, &line_n, "tools/build_core_strict.sh")
  release_append_artifact(&payload, &line_n, "tools/build_core_strict.ps1")
  release_append_artifact(&payload, &line_n, "tools/package_sdk.sh")
  release_append_artifact(&payload, &line_n, "tools/package_sdk.ps1")
  release_append_artifact(&payload, &line_n, "tools/publish_download_bundle.sh")
  release_append_artifact(&payload, &line_n, "tools/publish_download_bundle.ps1")
  release_append_artifact(&payload, &line_n, "tools/deploy_tezzcorp.sh")
  release_append_artifact(&payload, &line_n, "tools/deploy_tezzcorp_rollback.sh")
  release_append_artifact(&payload, &line_n, "bin/tezz")
  release_append_artifact(&payload, &line_n, "bin/tezz.cmd")
  release_append_artifact(&payload, &line_n, "bin/tezz.ps1")
  release_append_artifact(&payload, &line_n, "bin/tezzc")
  release_append_artifact(&payload, &line_n, "bin/tezzc.exe")
  release_append_artifact(&payload, &line_n, "build/tezzc")
  release_append_artifact(&payload, &line_n, "build/tezzc.exe")
  release_append_artifact(&payload, &line_n, "bin/tezzc-linux-x64")
  release_append_artifact(&payload, &line_n, "bin/tezzc-windows-x64.exe")
  release_append_artifact(&payload, &line_n, "web/tn_site/public/index.php")
  release_append_artifact(&payload, &line_n, "web/tn_site/public/assets/site.css")
  release_append_artifact(&payload, &line_n, "web/tn_site/public/assets/site.js")
  release_append_artifact(&payload, &line_n, "web/tn_site/public/download/install.sh")
  release_append_artifact(&payload, &line_n, "web/tn_site/public/download/install.ps1")
  release_append_artifact(&payload, &line_n, "web/tn_site/public/download/install_gui.ps1")
  release_append_artifact(&payload, &line_n, "web/tn_site/public/download/install_gui.cmd")
  release_append_artifact(&payload, &line_n, "web/tn_site/public/frameworks/index.php")
  release_append_artifact(&payload, &line_n, "web/tn_site/public/frameworks/tezzapi.php")
  release_append_artifact(&payload, &line_n, "web/tn_site/public/frameworks/tezzserve.php")
  release_append_artifact(&payload, &line_n, "web/tn_site/public/frameworks/tsm.php")
  release_append_artifact(&payload, &line_n, "web/tn_site/public/frameworks/tezzui.php")
  release_append_artifact(&payload, &line_n, "web/tn_site/public/frameworks/tezzdb.php")
  release_append_artifact(&payload, &line_n, "build/tezznative-sdk-linux.tar.gz")
  release_append_artifact(&payload, &line_n, "build/tezznative-sdk-macos.tar.gz")
  release_append_artifact(&payload, &line_n, "build/tezznative-sdk.zip")

  if line_n == 0:
    say "release-artifacts: no artifact files found"
    if payload != 0:
      free(payload)
    ret 0 - 1
  if dbg != 0:
    ln_dbg0:str = int_to_str(line_n)
    say "ra: collected lines"
    say ln_dbg0
    free(ln_dbg0)

  sign_key:str = 0 as str
  has_sign:int = 0
  if sign_key_override != 0:
    if sign_key_override[0] != 0:
      sign_key = str_join2(sign_key_override, "")
      has_sign = 1
  if has_sign == 0 && require_sign != 0:
    sign_key = release_sign_key()
    if sign_key != 0:
      if sign_key[0] != 0:
        has_sign = 1
      else:
        free(sign_key)
        sign_key = 0 as str
  if require_sign != 0 && has_sign == 0:
    say "release-artifacts: missing signing key"
    say "set TEZZ_RELEASE_SIGN_KEY (or TEZZ_SIGN_KEY) and retry"
    if payload != 0:
      free(payload)
    if sign_key != 0:
      free(sign_key)
    ret 0 - 1
  if dbg != 0:
    say "ra: signing ready"

  if dbg != 0:
    say "ra: before meta"
  meta:str = release_meta_line(payload, line_n, sign_key)
  if dbg != 0:
    say "ra: after meta"
  out:str = str_join3(meta, "\n", payload)
  if dbg != 0:
    say "ra: after join"
  if starts_with(out_path, "build/") != 0:
    ensure_dir("build")
  io.write_all(out_path, out)
  if dbg != 0:
    say "ra: after write"

  if quiet == 0:
    say "release-artifacts: wrote"
    say out_path
    say "release-artifacts: signed entries"
    ln_say:str = int_to_str(line_n)
    say ln_say
    free(ln_say)
  if sign_key != 0:
    free(sign_key)
  free(meta)
  if payload != 0:
    free(payload)
  free(out)
  if dbg != 0:
    say "ra: done"
  ret 0

fn stats_min(buf:*int, n:int) -> int:
  if n <= 0:
    ret 0
  m:int = buf[0]
  i:int = 1
  while i < n:
    if buf[i] < m:
      m = buf[i]
    i = i + 1
  ret m

fn stats_avg(buf:*int, n:int) -> int:
  if n <= 0:
    ret 0
  sum:int = 0
  i:int = 0
  while i < n:
    sum = sum + buf[i]
    i = i + 1
  ret sum / n

fn stats_median(buf:*int, n:int) -> int:
  if n <= 0:
    ret 0
  tmp:[int;64]
  i:int = 0
  while i < n:
    tmp[i] = buf[i]
    i = i + 1
  i = 0
  while i < n:
    j:int = i + 1
    while j < n:
      if tmp[j] < tmp[i]:
        t:int = tmp[i]
        tmp[i] = tmp[j]
        tmp[j] = t
      j = j + 1
    i = i + 1
  if (n % 2) != 0:
    ret tmp[n / 2]
  a:int = tmp[(n / 2) - 1]
  b:int = tmp[n / 2]
  ret (a + b) / 2

fn stats_p95(buf:*int, n:int) -> int:
  if n <= 0:
    ret 0
  tmp:[int;64]
  i:int = 0
  while i < n:
    tmp[i] = buf[i]
    i = i + 1
  i = 0
  while i < n:
    j:int = i + 1
    while j < n:
      if tmp[j] < tmp[i]:
        t:int = tmp[i]
        tmp[i] = tmp[j]
        tmp[j] = t
      j = j + 1
    i = i + 1
  idx:int = ((n * 95) + 99) / 100
  if idx <= 0:
    idx = 1
  idx = idx - 1
  if idx >= n:
    idx = n - 1
  ret tmp[idx]

fn sqrtf(x:float) -> float:
  if x <= 0.0:
    ret 0.0
  r:float = x
  i:int = 0
  while i < 8:
    r = 0.5 * (r + (x / r))
    i = i + 1
  ret r

fn stats_stddev(buf:*int, n:int) -> int:
  if n <= 1:
    ret 0
  sum:float = 0.0
  i:int = 0
  while i < n:
    sum = sum + (buf[i] as float)
    i = i + 1
  mean:float = sum / (n as float)
  var:float = 0.0
  i = 0
  while i < n:
    d:float = (buf[i] as float) - mean
    var = var + (d * d)
    i = i + 1
  var = var / (n as float)
  sd:float = sqrtf(var)
  ret sd as int

fn csv_field(line:str, idx:int) -> str:
  if line == 0:
    ret 0 as str
  i:int = 0
  field:int = 0
  start:int = 0
  while line[i] != 0:
    if line[i] == 44:
      if field == idx:
        ret substr_dup(line, start, i)
      field = field + 1
      start = i + 1
    i = i + 1
  if field == idx:
    ret substr_dup(line, start, i)
  ret 0 as str

fn bench_find_p95(log:str, name:str, mode:str) -> int:
  if log == 0 || name == 0 || mode == 0:
    ret 0 - 1
  idx:int = 0
  while 1:
    line:str = next_manifest_line(log, &idx)
    if line == 0:
      break
    if starts_with(line, "name,") != 0:
      free(line)
      continue
    f0:str = csv_field(line, 0)
    f1:str = csv_field(line, 1)
    if f0 != 0 && f1 != 0 && streq(f0, name) != 0 && streq(f1, mode) != 0:
      f6:str = csv_field(line, 6)
      p:int = 0 - 1
      if f6 != 0:
        p = parse_i64(f6)
        free(f6)
      free(f0)
      free(f1)
      free(line)
      ret p
    if f0 != 0:
      free(f0)
    if f1 != 0:
      free(f1)
    free(line)
  ret 0 - 1

fn crc32_file(path:str) -> int:
  if path == 0 || path[0] == 0:
    ret 0
  // Use a streaming byte hash so we can checksum binaries (io.read_all is text-oriented).
  f:*char = fopen(path, "rb")
  if f == 0:
    ret 0
  cap:int = 65536
  buf:*char = (*char)malloc(cap)
  if buf == 0:
    fclose(f)
    ret 0
  h:int = 5381
  for ;;:
    n:int = fread(buf, 1, cap, f)
    if n <= 0:
      break
    i:int = 0
    while i < n:
      b:int = 0
      unsafe:
        b = buf[i] as int
      b = b & 255
      h = ((h << 5) + h + b) & 2147483647
      i = i + 1
  free(buf)
  fclose(f)
  ret h

fn crc32_source_file(path:str) -> int:
  if path == 0 || path[0] == 0:
    ret 0
  data:str = io.read_all(path)
  if data == 0:
    ret 0
  // Canonicalize source package newlines so lockfiles are stable on Windows/Linux.
  h:int = 5381
  pending_cr:int = 0
  n:int = len(data)
  i:int = 0
  while i < n:
    b:int = 0
    unsafe:
      b = data[i] as int
    b = b & 255
    consumed:int = 0
    if pending_cr != 0:
      if b == 10:
        h = ((h << 5) + h + 10) & 2147483647
        pending_cr = 0
        consumed = 1
      else:
        h = ((h << 5) + h + 13) & 2147483647
        pending_cr = 0
    if consumed == 0:
      if b == 13:
        pending_cr = 1
      else:
        h = ((h << 5) + h + b) & 2147483647
    i = i + 1
  if pending_cr != 0:
    h = ((h << 5) + h + 13) & 2147483647
  free(data)
  ret h

fn print_usage() -> int:
  say "tezz <cmd> [args]"
  say "  --version | -V | version"
  say "  init [name] [--name <project_name>] [--template cli|api|lib|script|gui]"
  say "  <file.tn>            (run)"
  say "  run <file.tn> [--mode simple|systems] [--platform linux|windows|macos|android|native] [--vectorize|--no-vectorize] [--startup-profile]"
  say "  build <file.tn> [--platform linux|windows|macos|android] [--vectorize|--no-vectorize] [--dxil] [--dxil-entry <name>] [--dxc <path>]"
  say "  repl [--mode simple|systems] (interactive REPL)"
  say "  install <name@ver> [url] [checksum]   (alias: get)"
  say "  add <name@ver> [url] [checksum]       (dependency install)"
  say "  remove <name>                         (remove dependency)"
  say "  update [--check|--install|--reinstall|--uninstall]"
  say "  get <name@ver> [url] [checksum]"
  say "  lock"
  say "  publish [out_path]                    (validate + write registry metadata)"
  say "  registry [out_path]"
  say "  manifest"
  say "  verify [--strict]"
  say "  release-artifacts [--out <path>] [--verify-repro] [--require-sign] [--sign-key <key>|--sign-key-file <path>]"
  say "  reprocheck"
  say "  release-policy-check"
  say "  test [--smoke] [--conformance] [--conformance-strict] [--stdlib-v1] [--tooling] [--gui] [--parity] [--accel] [--accel-onnx] [--cross] [--runtime-hardening] [--runtime-fuzz --fuzz-rounds N --fuzz-iters N] [--runtime-soak --soak-hours N|--soak-minutes N|--soak-fast] [--io-smoke] [--simple-smoke] [--legacy-unstable] [--kernel-perf]"
  say "  bench [--all|--bc|--native] [--profile [N]] [--gate --baseline <path> --perf-max-pct <n>]"
  say "  benchext"
  say "  doctor"
  say "  lsp"
  say "  ai|tsm|boot            (not available in tezz core CLI)"
  say "  clean"
  say "  fmt <path>"
  say "  lint <path>"
  say "  release"
  ret 0

fn print_usage_ai() -> int:
  say "tezz ai is not available in tezz core CLI"
  ret 0

fn print_usage_tsm() -> int:
  say "tezz tsm is not available in tezz core CLI"
  ret 0

fn print_usage_init() -> int:
  say "tezz init [name|.] [--name <project_name>] [--template minimal|cli|api|lib|script|gui]"
  say "  templates:"
  say "    minimal -> creates tezz.mod + tezz.lock + .tezz/cache (default)"
  say "    cli  -> command line app scaffold"
  say "    api  -> TezzServe/TezzApi backend scaffold"
  say "    lib  -> reusable library scaffold"
  say "    script -> compact interactive script scaffold"
  say "    gui -> windowed GUI scaffold (tnui host-window app)"
  ret 0

fn print_usage_run() -> int:
  say "tezz run <file.tn> [--mode simple|systems] [--platform linux|windows|macos|android|native] [--vectorize|--no-vectorize] [--startup-profile]"
  say "  --mode systems: compatibility/default mode (current Tezz behavior)"
  say "  --mode simple: script-first mode (auto std + auto-main wrapping)"
  say "  --startup-profile: print + persist startup timing metrics"
  say "  --startup-profile-out <path>: override startup metrics output path"
  say "  if <file.tn> is omitted, defaults to src/main.tn (or main.tn) when present"
  ret 0

fn print_usage_build() -> int:
  say "tezz build <file.tn> [--release] [--platform linux|windows|macos|android] [--vectorize|--no-vectorize] [--dxil] [--dxil-entry <name>] [--dxc <path>]"
  say "  if <file.tn> is omitted, defaults to src/main.tn (or main.tn) when present"
  ret 0

fn print_usage_test() -> int:
  say "tezz test [--smoke] [--conformance] [--conformance-strict] [--stdlib-v1] [--tooling] [--gui] [--parity] [--accel] [--accel-onnx] [--cross] [--runtime-hardening] [--runtime-fuzz --fuzz-rounds N --fuzz-iters N] [--runtime-soak --soak-hours N|--soak-minutes N|--soak-fast] [--io-smoke] [--simple-smoke] [--legacy-unstable] [--kernel-perf]"
  ret 0

fn print_usage_doctor() -> int:
  say "tezz doctor [--strict] [--fix]"
  say "  --strict: treat warnings as failures"
  say "  --fix: run auto-repair installer when checks fail/warn"
  ret 0

fn print_usage_update() -> int:
  say "tezz update [--check|--install|--reinstall|--uninstall]"
  ret 0

fn print_usage_fmt() -> int:
  say "tezz fmt <path>"
  ret 0

fn print_usage_lint() -> int:
  say "tezz lint <path>"
  ret 0

fn print_usage_lsp() -> int:
  say "tezz lsp"
  say "  starts the TezzNative LSP server on stdio"
  ret 0

fn print_usage_repl() -> int:
  say "tezz repl [--mode simple|systems]"
  say "  interactive TezzNative REPL with expression evaluation"
  say "  simple mode blocks systems-only constructs (unsafe/pointers)"
  say "  commands: .help .reset .state .quit/.exit"
  ret 0

fn print_usage_verify() -> int:
  say "tezz verify [--strict]"
  say "  --strict: enforce lock format/order and exact tezz.mod dep coverage"
  say "           validates lock provenance metadata + optional TEZZ_SIGN_KEY signature"
  ret 0

fn print_usage_release_artifacts() -> int:
  say "tezz release-artifacts [--out <path>] [--verify-repro] [--require-sign] [--sign-key <key>|--sign-key-file <path>]"
  say "  writes deterministic release artifact manifest with metadata/signature"
  say "  signing key precedence: --sign-key, --sign-key-file, TEZZ_RELEASE_SIGN_KEY, TEZZ_SIGN_KEY"
  ret 0

fn print_usage_reprocheck() -> int:
  say "tezz reprocheck"
  say "  rebuilds compiler twice and verifies deterministic output checksum/size"
  say "  writes report: build/reproducible_build.tnx"
  ret 0

fn print_usage_release_policy_check() -> int:
  say "tezz release-policy-check"
  say "  validates required M6 policy docs and benchmark matrix files"
  ret 0

fn cmd_version() -> int:
  say "tezz 1.0.0-rc.1"
  ret 0

fn norm_os(os:str) -> str:
  if os == 0:
    ret 0 as str
  if streq(os, "posix") != 0:
    free(os)
    ret str_join2("linux", "")
  ret os

fn ends_with_tn(p:str) -> int:
  if p == 0:
    ret 0
  n:int = len(p)
  if n < 3:
    ret 0
  if p[n-3] == 46 && p[n-2] == 116 && p[n-1] == 110:
    ret 1
  ret 0

fn parse_name_ver(nv:str, out_name:*char, out_ver:*char) -> int:
  ret parse_namever_token(nv, out_name, out_ver)

fn str_has_char(s:str, ch:int) -> int:
  if s == 0:
    ret 0
  i:int = 0
  while s[i] != 0:
    if (s[i] as int) == ch:
      ret 1
    i = i + 1
  ret 0

fn copy_into_buf(dst:*char, src:str, max_len:int) -> int:
  if dst == 0 || src == 0 || max_len <= 0:
    ret 0
  i:int = 0
  lim:int = max_len - 1
  while src[i] != 0 && i < lim:
    dst[i] = src[i]
    i = i + 1
  dst[i] = 0 as char
  ret 1

fn parse_namever_token(tok:str, out_name:*char, out_ver:*char) -> int:
  if tok == 0 || out_name == 0 || out_ver == 0:
    ret 0
  tok2:str = str_join2("", tok)
  if tok2 == 0:
    ret 0
  i:int = 0
  at:int = 0 - 1
  while tok2[i] != 0:
    if (tok2[i] as int) == 64:
      at = i
      break
    i = i + 1
  if at <= 0:
    free(tok2)
    ret 0
  j:int = 0
  while j < at:
    out_name[j] = tok2[j]
    j = j + 1
  out_name[j] = 0 as char
  i = at + 1
  j = 0
  while tok2[i] != 0:
    out_ver[j] = tok2[i]
    j = j + 1
    i = i + 1
  out_ver[j] = 0 as char
  if out_ver[0] == 0:
    free(tok2)
    ret 0
  free(tok2)
  ret 1

fn parse_ver_seg(v:str, idx:*int) -> int:
  if v == 0 || idx == 0:
    ret 0
  i:int = 0
  unsafe:
    i = *idx
  n:int = 0
  seen:int = 0
  while v[i] != 0 && v[i] != 46:
    c:int = v[i] as int
    if c >= 48 && c <= 57:
      n = (n * 10) + (c - 48)
      seen = 1
    else:
      break
    i = i + 1
  while v[i] != 0 && v[i] != 46:
    i = i + 1
  if v[i] == 46:
    i = i + 1
  unsafe:
    *idx = i
  if seen == 0:
    ret 0
  ret n

fn version_cmp(a:str, b:str) -> int:
  if a == 0 && b == 0:
    ret 0
  if a == 0:
    ret 0 - 1
  if b == 0:
    ret 1
  ai:int = 0
  bi:int = 0
  while 1:
    av:int = parse_ver_seg(a, &ai)
    bv:int = parse_ver_seg(b, &bi)
    if av > bv:
      ret 1
    if av < bv:
      ret 0 - 1
    if a[ai] == 0 && b[bi] == 0:
      break
  c:int = strcmp(a, b)
  if c > 0:
    ret 1
  if c < 0:
    ret 0 - 1
  ret 0

fn update_tezz_mod(dep_name:str, dep_ver:str) -> int:
  mod:str = io.read_all("tezz.mod")
  if mod == 0:
    ret 0 - 1

  key:str = str_join3("dep.", dep_name, " = ")
  if str_contains(mod, key):
    free(mod)
    free(key)
    ret 0

  line:str = str_join3("dep.", dep_name, " = ")
  line2:str = str_join2(line, dep_ver)
  line3:str = str_join2(line2, "\n")
  newmod:str = str_join2(mod, line3)

  io.write_all("tezz.mod", newmod)

  free(mod)
  free(key)
  free(line)
  free(line2)
  free(line3)
  free(newmod)
  ret 0

fn line_is_dep(line:str, name:str, ver:str) -> int:
  if line == 0 || name == 0 || ver == 0:
    ret 0
  line2:str = str_join2("", line)
  name2:str = str_join2("", name)
  ver2:str = str_join2("", ver)
  if line2 == 0 || name2 == 0 || ver2 == 0:
    if line2 != 0:
      free(line2)
    if name2 != 0:
      free(name2)
    if ver2 != 0:
      free(ver2)
    ret 0
  i:int = 0
  while name2[i] != 0:
    if line2[i] != name2[i]:
      free(line2)
      free(name2)
      free(ver2)
      ret 0
    i = i + 1
  if line2[i] != 64:
    free(line2)
    free(name2)
    free(ver2)
    ret 0
  i = i + 1
  j:int = 0
  while ver2[j] != 0:
    if line2[i + j] != ver2[j]:
      free(line2)
      free(name2)
      free(ver2)
      ret 0
    j = j + 1
  c:int = line2[i + j] as int
  free(line2)
  free(name2)
  free(ver2)
  if c == 0 || c == 32 || c == 9:
    ret 1
  ret 0

fn update_tezz_lock(dep_name:str, dep_ver:str, url:str, checksum:str) -> int:
  nv:str = str_join3(dep_name, "@", dep_ver)
  line1:str = str_join2(nv, " ")
  line2:str = str_join2(line1, checksum)
  line3:str = str_join2(line2, " ")
  newline:str = str_join2(line3, url)

  lock:str = io.read_all("tezz.lock")
  if lock == 0:
    out:str = str_join2(newline, "\n")
    meta0:str = provenance_meta_line("lock-meta", out, 1)
    full0:str = str_join3(meta0, "\n", out)
    io.write_all("tezz.lock", full0)
    free(full0)
    free(meta0)
    free(out)
    free(nv)
    free(line1)
    free(line2)
    free(line3)
    free(newline)
    ret 0

  lines:[str;128]
  n:int = 0

  i:int = 0
  start:*char = lock
  while 1:
    c:int = lock[i] as int
    if c == 0 || c == 10:
      lock[i] = 0 as char
      if start[0] != 0 && (start[0] as int) != 35:
        if line_is_dep(start, dep_name, dep_ver) == 0:
          lines[n] = start
          n = n + 1
      if c == 0:
        break
      start = lock + i + 1
    i = i + 1

  lines[n] = newline
  n = n + 1

  // simple sort for determinism
  a:int = 0
  while a < n:
    b:int = a + 1
    while b < n:
      if strcmp(lines[a], lines[b]) > 0:
        tmp:str = lines[a]
        lines[a] = lines[b]
        lines[b] = tmp
      b = b + 1
    a = a + 1

  total:int = 0
  i = 0
  while i < n:
    total = total + len(lines[i]) + 1
    i = i + 1

  out:*char = (*char)malloc(total + 1)
  w:int = 0
  i = 0
  while i < n:
    j:int = 0
    while lines[i][j] != 0:
      out[w] = lines[i][j]
      w = w + 1
      j = j + 1
    out[w] = 10 as char
    w = w + 1
    i = i + 1
  out[w] = 0 as char

  meta:str = provenance_meta_line("lock-meta", out, n)
  full:str = str_join3(meta, "\n", out)
  io.write_all("tezz.lock", full)
  free(full)
  free(meta)
  free(out)
  free(lock)
  free(nv)
  free(line1)
  free(line2)
  free(line3)
  free(newline)
  ret 0

fn mod_line_is_dep_name(line:str, dep_name:str) -> int:
  if line == 0 || dep_name == 0:
    ret 0
  i:int = 0
  while line[i] == 32 || line[i] == 9:
    i = i + 1
  if starts_with_at(line, i, "dep.") == 0:
    ret 0
  i = i + 4
  ns:int = i
  while line[i] != 0 && line[i] != 32 && line[i] != 9 && line[i] != 61:
    i = i + 1
  name_tok:str = substr_dup(line, ns, i)
  ok:int = 0
  if name_tok != 0:
    if strcmp(name_tok, dep_name) == 0:
      ok = 1
    free(name_tok)
  ret ok

fn lock_line_is_dep_name(line:str, dep_name:str) -> int:
  if line == 0 || dep_name == 0:
    ret 0
  i:int = 0
  while line[i] == 32 || line[i] == 9:
    i = i + 1
  ns:int = i
  while line[i] != 0 && line[i] != 64 && line[i] != 32 && line[i] != 9:
    i = i + 1
  name_tok:str = substr_dup(line, ns, i)
  ok:int = 0
  if name_tok != 0:
    if strcmp(name_tok, dep_name) == 0:
      ok = 1
    free(name_tok)
  ret ok

fn rewrite_tezz_mod_without_dep(dep_name:str) -> int:
  mod:str = io.read_all("tezz.mod")
  if mod == 0:
    say "remove: missing tezz.mod"
    ret 0 - 1
  key:str = str_join3("dep.", dep_name, " = ")
  out:*char = (*char)malloc(len(mod) + 1)
  w:int = 0
  changed:int = 0
  i:int = 0
  line_start:int = 0
  while 1:
    c:int = mod[i] as int
    if c == 0 || c == 10:
      s:int = line_start
      while s < i && (mod[s] == 32 || mod[s] == 9):
        s = s + 1
      skip:int = 0
      if starts_with_at(mod, s, key) != 0:
        skip = 1
      if skip != 0:
        changed = 1
      else:
        j:int = line_start
        while j < i:
          out[w] = mod[j]
          w = w + 1
          j = j + 1
        if c == 10:
          out[w] = 10 as char
          w = w + 1
      if c == 0:
        break
      line_start = i + 1
    i = i + 1
  out[w] = 0 as char
  if changed != 0:
    io.write_all("tezz.mod", out)
  free(out)
  free(key)
  free(mod)
  ret 0

fn rewrite_tezz_lock_without_dep(dep_name:str) -> int:
  lock:str = io.read_all("tezz.lock")
  if lock == 0:
    ret 0
  key:str = str_join2(dep_name, "@")
  out:*char = (*char)malloc(len(lock) + 1)
  w:int = 0
  n:int = 0
  changed:int = 0
  i:int = 0
  line_start:int = 0
  while 1:
    c:int = lock[i] as int
    if c == 0 || c == 10:
      s:int = line_start
      while s < i && (lock[s] == 32 || lock[s] == 9):
        s = s + 1
      skip:int = 0
      is_comment:int = 0
      if s < i && (lock[s] as int) == 35:
        is_comment = 1
      if is_comment == 0 && starts_with_at(lock, s, key) != 0:
        skip = 1
      if skip != 0:
        changed = 1
      else:
        if is_comment == 0 && s < i:
          n = n + 1
          j:int = line_start
          while j < i:
            out[w] = lock[j]
            w = w + 1
            j = j + 1
          if c == 10:
            out[w] = 10 as char
            w = w + 1
      if c == 0:
        break
      line_start = i + 1
    i = i + 1
  out[w] = 0 as char
  if changed != 0:
    meta:str = provenance_meta_line("lock-meta", out, n)
    full:str = str_join3(meta, "\n", out)
    io.write_all("tezz.lock", full)
    free(full)
    free(meta)
  free(out)
  free(key)
  free(lock)
  ret 0

fn cmd_add() -> int:
  if user_args_count() < 2:
    say "tezz add <name@ver> [url] [checksum]"
    ret 0 - 1
  ret cmd_get()

fn cmd_remove() -> int:
  if user_args_count() < 2:
    say "tezz remove <name>"
    ret 0 - 1
  raw:str = arg(1)
  namebuf:[char;128]
  verbuf:[char;64]
  dep_name:str = raw
  if str_has_char(raw, 64) != 0:
    if parse_namever_token(raw, namebuf, verbuf) == 0:
      say "remove: expected <name> or <name@version>"
      ret 0 - 1
    dep_name = namebuf
  else:
    copy_into_buf(namebuf, raw, 128)
  if dep_name == 0 || dep_name[0] == 0:
    say "remove: empty package name"
    ret 0 - 1
  if rewrite_tezz_mod_without_dep(dep_name) != 0:
    ret 0 - 1
  if rewrite_tezz_lock_without_dep(dep_name) != 0:
    ret 0 - 1
  lib0:str = str_join3("lib/", dep_name, "")
  libp:str = str_join2(lib0, ".tn")
  if path_exists(libp) != 0:
    remove(libp)
  free(lib0)
  free(libp)
  say "ok"
  ret 0

fn cmd_get() -> int:
  ucnt:int = user_args_count()
  if ucnt < 2:
    say "tezz get <name@ver> [url] [checksum]"
    ret 0 - 1

  nv:str = arg(1)
  url:str = 0 as str
  checksum:str = 0 as str
  own_checksum:int = 0
  if ucnt >= 3:
    url = arg(2)
  if ucnt >= 4:
    checksum = arg(3)

  namebuf:[char;128]
  verbuf:[char;64]
  if parse_name_ver(nv, namebuf, verbuf) == 0:
    ret 0 - 1
  explicit_version:int = str_has_char(nv, 64)
  if explicit_version == 0 && url != 0:
    say "tezz get/install with explicit url requires <name@version>"
    ret 0 - 1

  sdk_root:str = sdk_root_arg()
  project_mode:int = 0
  if path_exists("tezz.mod") != 0:
    project_mode = 1

  mod_path:str = "tezz.mod"
  mod_path_owned:int = 0
  if project_mode == 0 && sdk_root != 0 && sdk_root[0] != 0:
    mod_path2:str = path_join(sdk_root, "tezz.mod")
    if path_exists(mod_path2) != 0:
      mod_path = mod_path2
      mod_path_owned = 1
    else:
      free(mod_path2)

  ensure_dir(".tezz")
  ensure_dir(".tezz/cache")

  if url == 0:
    mod:str = io.read_all(mod_path)
    if mod == 0:
      say "missing tezz.mod"
      if mod_path_owned != 0:
        free(mod_path)
      ret 0 - 1
    reg_url:str = mod_get_value(mod, "registry")
    if reg_url == 0:
      say "missing registry in tezz.mod"
      free(mod)
      if mod_path_owned != 0:
        free(mod_path)
      ret 0 - 1
    reg_path:str = ".tezz/cache/registry.tnx"
    reg_ok:int = 0
    reg:str = 0 as str
    // prefer SDK-bundled registry first for stable installs.
    if sdk_root != 0 && sdk_root[0] != 0:
      sdk_reg1:str = path_join(sdk_root, "registry.tnx")
      reg = io.read_all(sdk_reg1)
      if reg == 0:
        free(sdk_reg1)
        sdk_reg2:str = path_join(sdk_root, "download/sdk/registry.tnx")
        reg = io.read_all(sdk_reg2)
        free(sdk_reg2)
      else:
        free(sdk_reg1)
    if reg == 0:
      if net.download(reg_url, reg_path) == 0:
        reg_ok = 1
      reg = io.read_all(reg_path)
    if reg == 0:
      if reg_ok == 0:
        say "registry download failed"
      else:
        say "missing registry cache"
      free(mod)
      free(reg_url)
      if mod_path_owned != 0:
        free(mod_path)
      ret 0 - 1

    urlbuf:[char;512]
    ckbuf:[char;128]
    urlbuf[0] = 0 as char
    ckbuf[0] = 0 as char

    if explicit_version == 0:
      reg_scan:str = str_join2("", reg)
      if reg_scan == 0:
        say "registry parse failed"
        free(reg)
        free(mod)
        free(reg_url)
        if mod_path_owned != 0:
          free(mod_path)
        ret 0 - 1
      i0:int = 0
      st0:*char = reg_scan
      best_ver:[char;64]
      best_ver[0] = 0 as char
      while 1:
        c0:int = reg_scan[i0] as int
        if c0 == 0 || c0 == 10:
          reg_scan[i0] = 0 as char
          if st0[0] != 0 && (st0[0] as int) != 35:
            tok:[char;192]
            tj:int = 0
            tk:int = 0
            while st0[tk] != 0 && st0[tk] != 32 && st0[tk] != 9:
              if tj < 191:
                tok[tj] = st0[tk]
                tj = tj + 1
              tk = tk + 1
            tok[tj] = 0 as char
            if tok[0] != 0:
              pname:[char;128]
              pver:[char;64]
              if parse_namever_token(tok, pname, pver) != 0:
                if streq(namebuf, pname) != 0:
                  if best_ver[0] == 0 || version_cmp(pver, best_ver) > 0:
                    copy_into_buf(best_ver, pver, 64)
          if c0 == 0:
            break
          st0 = reg_scan + i0 + 1
        i0 = i0 + 1
      if best_ver[0] == 0:
        free(reg_scan)
        say "package not found in registry"
        free(reg)
        free(mod)
        free(reg_url)
        if mod_path_owned != 0:
          free(mod_path)
        ret 0 - 1
      free(reg_scan)
      copy_into_buf(verbuf, best_ver, 64)

    // second pass: exact package@version fields
    i:int = 0
    start:*char = reg
    found:int = 0
    while 1:
      c:int = reg[i] as int
      if c == 0 || c == 10:
        reg[i] = 0 as char
        if start[0] != 0 && (start[0] as int) != 35:
          if line_is_dep(start, namebuf, verbuf) != 0:
            // parse fields: name@ver url checksum
            j:int = 0
            while start[j] != 0 && start[j] != 32 && start[j] != 9:
              j = j + 1
            while start[j] == 32 || start[j] == 9:
              j = j + 1
            k:int = 0
            while start[j] != 0 && start[j] != 32 && start[j] != 9:
              if k < 511:
                urlbuf[k] = start[j]
                k = k + 1
              j = j + 1
            urlbuf[k] = 0 as char
            while start[j] == 32 || start[j] == 9:
              j = j + 1
            k = 0
            while start[j] != 0 && start[j] != 32 && start[j] != 9:
              if k < 127:
                ckbuf[k] = start[j]
                k = k + 1
              j = j + 1
            ckbuf[k] = 0 as char
            found = 1
        if c == 0:
          break
        start = reg + i + 1
      i = i + 1

    if found == 0 || urlbuf[0] == 0:
      say "package not found in registry"
      free(reg)
      free(mod)
      free(reg_url)
      if mod_path_owned != 0:
        free(mod_path)
      ret 0 - 1

    url = urlbuf
    if checksum == 0 && ckbuf[0] != 0:
      checksum = ckbuf
    free(reg)
    free(mod)
    free(reg_url)
    if mod_path_owned != 0:
      free(mod_path)
      mod_path_owned = 0

  if checksum != 0 && is_hex8(checksum) == 0:
    say "invalid checksum format (expected 8 hex chars)"
    if mod_path_owned != 0:
      free(mod_path)
    ret 0 - 1

  base1:str = str_join3(".tezz/cache/", namebuf, "-")
  base2:str = str_join2(base1, verbuf)
  cache:str = str_join2(base2, ".tn")
  tmp:str = str_join2(cache, ".tmp")

  use_cache:int = 0
  if path_exists(cache) != 0:
    if checksum == 0:
      use_cache = 1
    else:
      want:int = parse_hex(checksum)
      have:int = crc32_source_file(cache)
      if have == want:
        use_cache = 1

  if use_cache == 0:
    dl_ok:int = 0
    if net.download(url, tmp) == 0:
      dl_ok = 1
    else:
      // fallback: for SDK-core modules, source directly from SDK lib.
      if sdk_root != 0 && sdk_root[0] != 0:
        lib_dir0:str = path_join(sdk_root, "lib")
        tn_name0:str = str_join2(namebuf, ".tn")
        src_lib0:str = path_join(lib_dir0, tn_name0)
        src_data0:str = io.read_all(src_lib0)
        if src_data0 != 0:
          if io.write_all(tmp, src_data0) != (0 - 1):
            dl_ok = 1
          free(src_data0)
        free(lib_dir0)
        free(tn_name0)
        free(src_lib0)
    if dl_ok == 0:
      say "download failed"
      free(base1)
      free(base2)
      free(cache)
      free(tmp)
      ret 0 - 1
    if checksum != 0:
      want2:int = parse_hex(checksum)
      have2:int = crc32_source_file(tmp)
      if have2 != want2:
        say "checksum mismatch"
        remove(tmp)
        free(base1)
        free(base2)
        free(cache)
        free(tmp)
        ret 0 - 1
    if path_exists(cache) != 0:
      remove(cache)
    io.move_file(tmp, cache)

  dest_lib:str = "lib"
  dest_lib_owned:int = 0
  if project_mode != 0:
    ensure_dir("lib")
  else if sdk_root != 0 && sdk_root[0] != 0:
    sdk_lib2:str = path_join(sdk_root, "lib")
    if path_exists(sdk_lib2) == 0:
      ensure_dir(sdk_lib2)
    dest_lib = sdk_lib2
    dest_lib_owned = 1
  else:
    ensure_dir("lib")

  out0:str = path_join(dest_lib, namebuf)
  out_path:str = str_join2(out0, ".tn")
  copy_ok:int = io.copy_file(cache, out_path)
  if copy_ok < 0:
    // If SDK path is read-only (common in Program Files), keep cache usable.
    if project_mode != 0:
      ensure_dir("lib")
      out_local0:str = str_join3("lib/", namebuf, "")
      out_local:str = str_join2(out_local0, ".tn")
      if io.copy_file(cache, out_local) < 0:
        warn_copy:str = str_join3("warning: install target not writable: ", out_path, "")
        say warn_copy
        free(warn_copy)
        say "warning: package kept in .tezz/cache and will resolve via lock/cache fallback"
      free(out_local0)
      free(out_local)
    else:
      warn_copy2:str = str_join3("warning: install target not writable: ", out_path, "")
      say warn_copy2
      free(warn_copy2)
      say "warning: package kept in .tezz/cache"
  free(out0)

  // compute checksum if missing
  if checksum == 0:
    have3:int = crc32_source_file(cache)
    checksum = hex8(have3)
    own_checksum = 1

  if project_mode != 0:
    update_tezz_mod(namebuf, verbuf)
    update_tezz_lock(namebuf, verbuf, url, checksum)

  free(base1)
  free(base2)
  free(cache)
  free(tmp)
  free(out_path)
  if dest_lib_owned != 0:
    free(dest_lib)
  if mod_path_owned != 0:
    free(mod_path)
  if own_checksum != 0 && checksum != 0:
    free(checksum)
  say "ok"
  ret 0

fn copy_module_file(src_root:str, dst_root:str, name:str) -> int:
  if src_root == 0 || dst_root == 0 || name == 0:
    ret 0
  s0:str = path_join(src_root, name)
  src:str = str_join2(s0, ".tn")
  d0:str = path_join(dst_root, name)
  dst:str = str_join2(d0, ".tn")
  ok:int = 0
  if path_exists(src) != 0 && path_exists(dst) == 0:
    io.copy_file(src, dst)
    ok = 1
  free(s0)
  free(src)
  free(d0)
  free(dst)
  ret ok

fn copy_core_modules_from_sdk(sdk_lib:str, dst_lib:str) -> int:
  if sdk_lib == 0 || dst_lib == 0:
    ret 0
  copied:int = 0
  copied = copied + copy_module_file(sdk_lib, dst_lib, "std")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "io")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "time")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "net")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "tls")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "event")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "frame")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "tzgui")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "tzui")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "tnui")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "tezzsetup")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "math")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "tzimage")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "tnauto")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "simd")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "intrin")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "data")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "task")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "tezzapi")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "tezzserve")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "tnx")
  copied = copied + copy_module_file(sdk_lib, dst_lib, "sys")
  ret copied

fn refresh_compat_intrin_from_sdk(sdk_lib:str) -> int:
  if sdk_lib == 0:
    ret 0
  if path_exists("lib/intrin.tn") == 0:
    ret 0

  s0:str = path_join(sdk_lib, "intrin")
  src:str = str_join2(s0, ".tn")
  ok:int = 0
  if path_exists(src) != 0:
    io.copy_file(src, "lib/intrin.tn")
    ok = 1
  free(s0)
  free(src)
  ret ok

fn sync_local_lib_from_sdk() -> int:
  // Compatibility lane: if local lib/std.tn is missing, seed lib/ from SDK.
  // Works for both project mode (with tezz.mod) and single-file script mode.
  if path_exists("lib/std.tn") != 0:
    ret 0

  sdk_root_raw:str = sdk_root_arg()
  sdk_root:str = sdk_root_raw
  sdk_root_owned:int = 0
  if sdk_root != 0 && sdk_root[0] != 0:
    sdk_norm0:str = strip_outer_quotes(sdk_root)
    if sdk_norm0 != 0 && sdk_norm0[0] != 0:
      sdk_root = sdk_norm0
      sdk_root_owned = 1
    else if sdk_norm0 != 0:
      free(sdk_norm0)
  if sdk_root == 0 || sdk_root[0] == 0:
    s0:str = env_value("TEZZ_SDK_ROOT")
    if s0 != 0 && s0[0] != 0:
      sdk_root = s0
      sdk_root_owned = 1
    else:
      if s0 != 0:
        free(s0)
      s1:str = env_value("TEZZ_SDK_DIR")
      if s1 != 0 && s1[0] != 0:
        sdk_root = s1
        sdk_root_owned = 1
      else:
        if s1 != 0:
          free(s1)
        tzc:str = tezzc_path()
        if tzc != 0:
          s2:str = infer_sdk_root_from_tezzc(tzc)
          if s2 != 0 && s2[0] != 0:
            sdk_root = s2
            sdk_root_owned = 1
          else:
            if s2 != 0:
              free(s2)

  if sdk_root == 0 || sdk_root[0] == 0:
    ret 0

  sdk_lib:str = path_join(sdk_root, "lib")
  copied:int = 0
  if path_exists(sdk_lib) != 0:
    ensure_dir("lib")
    deps_added:int = 0
    if path_exists("tezz.mod") != 0:
      deps_added = sync_project_deps_from_sdk_lib(sdk_lib)
    copied = copy_core_modules_from_sdk(sdk_lib, "lib")
    copied = copied + copy_all_modules_from_sdk(sdk_lib, "lib")
    // If we changed dependency coverage, stale lockfiles become invalid.
    // Remove tezz.lock so compiler lock enforcement does not block run/build.
    if deps_added > 0 && path_exists("tezz.lock") != 0:
      remove("tezz.lock")
  free(sdk_lib)
  if sdk_root_owned != 0:
    free(sdk_root)
  ret copied

fn ensure_std_from_cache() -> int:
  if path_exists("lib/std.tn") != 0:
    ret 1
  ensure_dir(".tezz")
  ensure_dir(".tezz/cache")
  c0:str = ".tezz/cache/std-0.1.0.tn"
  c1:str = ".tezz/cache/std.tn"
  src:str = 0 as str
  if path_exists(c0) != 0:
    src = c0
  else if path_exists(c1) != 0:
    src = c1
  if src == 0:
    ret 0
  ensure_dir("lib")
  if io.copy_file(src, "lib/std.tn") < 0:
    ret 0
  ret 1

fn ensure_std_from_registry_lib() -> int:
  if path_exists("lib/std.tn") != 0:
    ret 1
  if path_exists("tezz.mod") == 0:
    ret 0
  mod:str = io.read_all("tezz.mod")
  if mod == 0:
    ret 0
  reg_lib:str = mod_get_value(mod, "registry_lib")
  if reg_lib == 0 || reg_lib[0] == 0:
    free(mod)
    if reg_lib != 0:
      free(reg_lib)
    ret 0
  base_url:str = reg_lib
  ulen:int = len(base_url)
  if ulen > 0:
    last:int = base_url[ulen - 1] as int
    if last != 47 && last != 92:
      tmpu:str = str_join2(base_url, "/")
      free(base_url)
      base_url = tmpu
  std_url:str = str_join2(base_url, "std.tn")
  ensure_dir(".tezz")
  ensure_dir(".tezz/cache")
  tmp_path:str = ".tezz/cache/std-0.1.0.tn.tmp"
  cache_path:str = ".tezz/cache/std-0.1.0.tn"
  ok:int = 0
  if net.download(std_url, tmp_path) == 0:
    if path_exists(cache_path) != 0:
      remove(cache_path)
    io.move_file(tmp_path, cache_path)
    ensure_dir("lib")
    if io.copy_file(cache_path, "lib/std.tn") >= 0:
      ok = 1
  remove(tmp_path)
  free(std_url)
  free(base_url)
  free(reg_lib)
  free(mod)
  ret ok

fn ensure_std_module_available() -> int:
  if path_exists("tezz.mod") == 0:
    ret 1
  if path_exists("lib/std.tn") != 0:
    ret 1
  sync_local_lib_from_sdk()
  if path_exists("lib/std.tn") != 0:
    ret 1
  if ensure_std_from_cache() != 0:
    ret 1
  if ensure_std_from_registry_lib() != 0:
    ret 1
  ret 0

fn is_blank_text(s:str) -> int:
  if s == 0:
    ret 1
  i:int = 0
  while s[i] != 0:
    c:int = s[i] as int
    if c != 32 && c != 9 && c != 10 && c != 13:
      ret 0
    i = i + 1
  ret 1

fn unlock_empty_lock_file() -> int:
  if path_exists("tezz.lock") == 0:
    ret 0
  body:str = io.read_all("tezz.lock")
  if is_blank_text(body) != 0:
    remove("tezz.lock")
    if body != 0:
      free(body)
    ret 1
  if body != 0:
    free(body)
  ret 0

fn relax_stale_std_lock() -> int:
  mod:str = io.read_all("tezz.mod")
  if mod == 0:
    ret 0
  stdv:str = mod_get_value(mod, "dep.std")
  if stdv == 0:
    free(mod)
    ret 0
  if stdv[0] == 0:
    free(stdv)
    free(mod)
    ret 0
  lock_body:str = io.read_all("tezz.lock")
  if lock_body == 0:
    free(stdv)
    free(mod)
    ret 0
  want0:str = str_join3("std@", stdv, " ")
  has_std:int = str_contains(lock_body, want0)
  free(want0)
  if has_std == 0:
    remove("tezz.lock")
  free(lock_body)
  free(stdv)
  free(mod)
  ret 0

fn sync_project_deps_from_sdk_lib(sdk_lib:str) -> int:
  if sdk_lib == 0 || path_exists("tezz.mod") == 0:
    ret 0
  list:str = io.dir_list_rec(sdk_lib)
  if list == 0:
    ret 0
  n:int = len(list)
  i:int = 0
  start:*char = list
  added:int = 0
  while 1:
    c:int = list[i] as int
    if c == 0 || c == 10:
      list[i] = 0 as char
      if start[0] != 0:
        if path_is_dir(start) == 0 && ends_with_tn(start) != 0:
          base:str = path_basename_no_ext(start)
          if base != 0 && base[0] != 0:
            if update_tezz_mod(base, "0.1.0") == 0:
              added = added + 1
          if base != 0:
            free(base)
      if c == 0:
        break
      start = list + i + 1
    i = i + 1
    if i > n:
      break
  free(list)
  ret added

fn copy_all_modules_from_sdk(sdk_lib:str, dst_lib:str) -> int:
  if sdk_lib == 0 || dst_lib == 0:
    ret 0
  list:str = io.dir_list_rec(sdk_lib)
  if list == 0:
    ret 0
  n:int = len(list)
  i:int = 0
  start:*char = list
  copied:int = 0
  while 1:
    c:int = list[i] as int
    if c == 0 || c == 10:
      list[i] = 0 as char
      if start[0] != 0:
        if path_is_dir(start) == 0 && ends_with_tn(start) != 0:
          base:str = path_basename_no_ext(start)
          if base != 0 && base[0] != 0:
            copied = copied + copy_module_file(sdk_lib, dst_lib, base)
          if base != 0:
            free(base)
      if c == 0:
        break
      start = list + i + 1
    i = i + 1
    if i > n:
      break
  free(list)
  ret copied

fn project_module_root(mod:str) -> str:
  if mod != 0:
    rootv:str = mod_get_value(mod, "module_root")
    if rootv != 0 && rootv[0] != 0:
      ret rootv
    if rootv != 0:
      free(rootv)
  // Python-like default: project imports do not require local module copies.
  // Local "lib/" remains supported, with SDK lib fallback via dep_module_path.
  ret str_join2("", "lib")

fn dep_module_path(root:str, name:str) -> str:
  if root == 0 || name == 0:
    ret 0 as str
  d0:str = path_join(root, name)
  out:str = str_join2(d0, ".tn")
  free(d0)
  if path_exists(out) != 0:
    ret out

  sdk_root_raw:str = sdk_root_arg()
  sdk_root:str = sdk_root_raw
  sdk_env_owned:int = 0
  if sdk_root == 0 || sdk_root[0] == 0:
    sdk_env:str = env_value("TEZZ_SDK_ROOT")
    if sdk_env != 0 && sdk_env[0] != 0:
      sdk_root = sdk_env
      sdk_env_owned = 1
    else:
      if sdk_env != 0:
        free(sdk_env)
      sdk_env = env_value("TEZZ_SDK_DIR")
      if sdk_env != 0 && sdk_env[0] != 0:
        sdk_root = sdk_env
        sdk_env_owned = 1
      else:
        if sdk_env != 0:
          free(sdk_env)
  if sdk_root != 0 && sdk_root[0] != 0:
    s0:str = path_join(sdk_root, "lib")
    s1:str = path_join(s0, name)
    s2:str = str_join2(s1, ".tn")
    free(s0)
    free(s1)
    if path_exists(s2) != 0:
      if sdk_env_owned != 0:
        free(sdk_root)
      free(out)
      ret s2
    free(s2)
  if sdk_env_owned != 0:
    free(sdk_root)
  ret out

fn cmd_init() -> int:
  target:str = "."
  target_set:int = 0
  name_arg:str = 0 as str
  template_raw:str = "minimal"
  ai:int = 1
  ucnt:int = user_args_count()
  while ai < ucnt:
    a:str = arg(ai)
    if streq(a, "--name") && (ai + 1) < ucnt:
      name_arg = arg(ai + 1)
      ai = ai + 2
      continue
    if starts_with(a, "--name=") != 0:
      name_arg = a + 7
      ai = ai + 1
      continue
    if streq(a, "--template") && (ai + 1) < ucnt:
      template_raw = arg(ai + 1)
      ai = ai + 2
      continue
    if starts_with(a, "--template=") != 0:
      template_raw = a + 11
      ai = ai + 1
      continue
    if streq(a, "--kind") && (ai + 1) < ucnt:
      template_raw = arg(ai + 1)
      ai = ai + 2
      continue
    if starts_with(a, "--kind=") != 0:
      template_raw = a + 7
      ai = ai + 1
      continue
    if streq(a, "--help") || streq(a, "-h"):
      print_usage_init()
      ret 0
    if starts_with(a, "--") != 0:
      p0:str = str_join2("init: unknown option: ", a)
      say p0
      free(p0)
      print_usage_init()
      ret 0 - 1
    if target_set == 0:
      target = a
      target_set = 1
      ai = ai + 1
      continue
    ai = ai + 1

  template:str = 0 as str
  if streq(template_raw, "minimal") || streq(template_raw, "base") || streq(template_raw, "default"):
    template = "minimal"
  else if streq(template_raw, "cli") || streq(template_raw, "app"):
    template = "cli"
  else if streq(template_raw, "api") || streq(template_raw, "service"):
    template = "api"
  else if streq(template_raw, "lib") || streq(template_raw, "library"):
    template = "lib"
  else if streq(template_raw, "script"):
    template = "script"
  else if streq(template_raw, "gui") || streq(template_raw, "desktop"):
    template = "gui"
  if template == 0:
    say "init: unsupported template (use minimal|cli|api|lib|script|gui)"
    print_usage_init()
    ret 0 - 1

  if target_set != 0:
    if path_exists(target) == 0:
      if ensure_dir(target) != 0:
        say "init: failed to create target directory"
        ret 0 - 1
    else if path_is_dir(target) == 0:
      say "init: target exists but is not a directory"
      ret 0 - 1

  proj_name:str = name_arg
  if proj_name == 0 || proj_name[0] == 0:
    if streq(target, ".") != 0:
      cwd:str = io.cwd()
      proj_name = path_basename_no_ext(cwd)
      free(cwd)
    else:
      proj_name = path_basename_no_ext(target)
    if proj_name == 0 || proj_name[0] == 0:
      proj_name = "tezz_app"

  tezz_dir:str = path_join(target, ".tezz")
  cache_dir:str = path_join(tezz_dir, "cache")
  src_dir:str = 0 as str
  main_path:str = 0 as str
  readme_path:str = 0 as str
  if streq(template, "minimal") == 0:
    src_dir = path_join(target, "src")
    if ensure_dir(src_dir) != 0:
      say "init: failed to create src directory"
      free(src_dir); free(tezz_dir); free(cache_dir)
      ret 0 - 1
  if ensure_dir(tezz_dir) != 0:
    say "init: failed to create .tezz directory"
    free(src_dir); free(tezz_dir); free(cache_dir)
    ret 0 - 1
  if ensure_dir(cache_dir) != 0:
    say "init: failed to create .tezz/cache directory"
    free(src_dir); free(tezz_dir); free(cache_dir)
    ret 0 - 1

  mod_path:str = path_join(target, "tezz.mod")
  if path_exists(mod_path) == 0:
    m0:str = str_join3("name = ", proj_name, "\n")
    m1:str = str_join2(m0, "version = 0.1.0\n")
    m2:str = str_join2(m1, "registry = https://tn.tezzcorp.com/registry.tnx\n")
    m3:str = str_join2(m2, "registry_lib = https://tn.tezzcorp.com/download/sdk/lib/\n")
    m4:str = str_join2(m3, "dep.std = 0.1.0\n")
    m6:str = 0 as str
    if streq(template, "minimal"):
      d1:str = str_join2(m4, "dep.io = 0.1.0\n")
      d2:str = str_join2(d1, "dep.time = 0.1.0\n")
      d3:str = str_join2(d2, "dep.net = 0.1.0\n")
      d4:str = str_join2(d3, "dep.tls = 0.1.0\n")
      d5:str = str_join2(d4, "dep.event = 0.1.0\n")
      d6:str = str_join2(d5, "dep.frame = 0.1.0\n")
      d7:str = str_join2(d6, "dep.tzgui = 0.1.0\n")
      d8:str = str_join2(d7, "dep.tzui = 0.1.0\n")
      d9:str = str_join2(d8, "dep.tnui = 0.1.0\n")
      d10:str = str_join2(d9, "dep.tezzsetup = 0.1.0\n")
      d11:str = str_join2(d10, "dep.math = 0.1.0\n")
      d12:str = str_join2(d11, "dep.tzimage = 0.1.0\n")
      d13:str = str_join2(d12, "dep.tnauto = 0.1.0\n")
      d14:str = str_join2(d13, "dep.simd = 0.1.0\n")
      d15:str = str_join2(d14, "dep.intrin = 0.1.0\n")
      d16:str = str_join2(d15, "dep.data = 0.1.0\n")
      d17:str = str_join2(d16, "dep.task = 0.1.0\n")
      d18:str = str_join2(d17, "dep.tezzapi = 0.1.0\n")
      d19:str = str_join2(d18, "dep.tezzserve = 0.1.0\n")
      d20:str = str_join2(d19, "dep.tnx = 0.1.0\n")
      d21:str = str_join2(d20, "dep.sys = 0.1.0\n")
      io.write_all(mod_path, d21)
      free(d1); free(d2); free(d3); free(d4); free(d5); free(d6); free(d7); free(d8); free(d9); free(d10)
      free(d11); free(d12); free(d13); free(d14); free(d15); free(d16); free(d17); free(d18); free(d19); free(d20); free(d21)
    else if streq(template, "cli"):
      c1:str = str_join2(m4, "dep.io = 0.1.0\n")
      c2:str = str_join2(c1, "dep.time = 0.1.0\n")
      c3:str = str_join2(c2, "dep.task = 0.1.0\n")
      io.write_all(mod_path, c3)
      free(c1); free(c2); free(c3)
    else if streq(template, "script"):
      s1:str = str_join2(m4, "dep.io = 0.1.0\n")
      s2:str = str_join2(s1, "dep.time = 0.1.0\n")
      io.write_all(mod_path, s2)
      free(s1); free(s2)
    else if streq(template, "gui"):
      g1:str = str_join2(m4, "dep.gui = 0.1.0\n")
      g2:str = str_join2(g1, "dep.tzgui = 0.1.0\n")
      g3:str = str_join2(g2, "dep.tzui = 0.1.0\n")
      g4:str = str_join2(g3, "dep.tnui = 0.1.0\n")
      g5:str = str_join2(g4, "dep.event = 0.1.0\n")
      g6:str = str_join2(g5, "dep.frame = 0.1.0\n")
      io.write_all(mod_path, g6)
      free(g1); free(g2); free(g3); free(g4); free(g5); free(g6)
    else if streq(template, "api"):
      a1:str = str_join2(m4, "dep.net = 0.1.0\n")
      a2:str = str_join2(a1, "dep.tls = 0.1.0\n")
      a3:str = str_join2(a2, "dep.tnx = 0.1.0\n")
      a4:str = str_join2(a3, "dep.task = 0.1.0\n")
      a5:str = str_join2(a4, "dep.tezzapi = 0.1.0\n")
      a6:str = str_join2(a5, "dep.tezzserve = 0.1.0\n")
      io.write_all(mod_path, a6)
      free(a1); free(a2); free(a3); free(a4); free(a5); free(a6)
    else:
      l1:str = str_join2(m4, "dep.io = 0.1.0\n")
      io.write_all(mod_path, l1)
      free(l1)
    if m6 != 0:
      free(m6)
    free(m0); free(m1); free(m2); free(m3); free(m4)

  lock_path:str = path_join(target, "tezz.lock")

  if streq(template, "minimal") == 0:
    main_path = path_join(src_dir, "main.tn")
    if path_exists(main_path) == 0:
      main_tpl:str = 0 as str
      if streq(template, "api"):
        main_tpl = "import \"std\"\nimport \"net\"\nimport \"tezzapi\"\nimport \"tezzserve\"\n\nfn main() -> int:\n  say \"Tezz API template ready.\"\n  say \"Use examples/reference_v1/api_server.tn for full server loop.\"\n  say tezzapi.tnxb_op_read()\n  say net.af_inet()\n  ret 0\n"
      else if streq(template, "script"):
        main_tpl = "import \"std\"\n\nsay(\"TezzNative script mode\")\na:float = input(\"A = \")\nb:float = input(\"B = \")\nsay(a + b)\n"
      else if streq(template, "gui"):
        main_tpl = "import \"std\"\nimport \"tnui\"\nimport \"tzgui\"\n\nfn main() -> int:\n  caps:TzGuiCaps\n  app:TnUiApp\n  active:int = 0\n  unsafe:\n    if tzgui.detect_caps(&caps) != 0:\n      say \"gui detect_caps failed\"\n      ret 1\n  if caps.windowing == 0:\n    say \"GUI host-window backend unavailable\"\n    ret 0\n  unsafe:\n    if tnui.init(&app, \"TezzNative First GUI App\", 860, 520) != 0:\n      say \"tnui init failed\"\n      ret 1\n    tnui.request_full_redraw(&app, 4)\n  while 1:\n    keep_running:int = 0\n    unsafe:\n      keep_running = tnui.running(&app)\n    if keep_running == 0:\n      break\n    unsafe:\n      if tnui.begin(&app) != 0:\n        say \"tnui begin failed\"\n        ret 1\n      tnui.frame(&app, 1, 24, 24, 812, 462, \"TezzNative First GUI App\")\n      tnui.label(&app, 2, 48, 70, \"Hello from TezzNative production GUI\")\n      if active == 0:\n        tnui.label(&app, 3, 48, 94, \"Status: waiting for button click\")\n      else:\n        tnui.label(&app, 3, 48, 94, \"Status: primary button clicked\")\n      tnui.button(&app, 4, 48, 136, 220, 36, \"Primary Action\")\n      tnui.button(&app, 5, 278, 136, 140, 36, \"Quit\")\n      if tnui.button_clicked(&app, 4) != 0:\n        active = 1 - active\n      if tnui.button_clicked(&app, 5) != 0:\n        tnui.close(&app)\n      k:int = tnui.last_key(&app)\n      if k == 27 || k == 113 || k == 81:\n        tnui.close(&app)\n      tnui.end(&app)\n  unsafe:\n    tnui.close(&app)\n  ret 0\n"
      else if streq(template, "lib"):
        main_tpl = "import \"std\"\nimport \"./lib.tn\"\n\nfn main() -> int:\n  say \"Library template demo\"\n  say lib.add(2, 3)\n  ret 0\n"
      else:
        main_tpl = "import \"std\"\nimport \"time\"\n\nfn main() -> int:\n  say \"Hello from TezzNative CLI template.\"\n  say time.date_local()\n  ret 0\n"
      io.write_all(main_path, main_tpl)

    if streq(template, "lib"):
      lib_path:str = path_join(src_dir, "lib.tn")
      if path_exists(lib_path) == 0:
        lib_tpl:str = "fn add(a:int, b:int) -> int:\n  ret a + b\n\nfn sub(a:int, b:int) -> int:\n  ret a - b\n"
        io.write_all(lib_path, lib_tpl)
      free(lib_path)

    readme_path = path_join(target, "README.tn.md")
    if path_exists(readme_path) == 0:
      r0:str = str_join3("# ", proj_name, "\n\n")
      r1:str = str_join2(r0, "Generated by `tezz init`.\n")
      r1t:str = str_join3(r1, "Template: `", template)
      r1b:str = str_join2(r1t, "`\n\n")
      free(r1t)
      free(r1)
      r1 = r1b
      r2:str = str_join2(r1, "## Commands\n")
      r3:str = str_join2(r2, "- Run: `tezz run src/main.tn`\n")
      r4:str = str_join2(r3, "- Build Linux: `tezz build src/main.tn --platform linux`\n")
      r5:str = str_join2(r4, "- Build Windows: `tezz build src/main.tn --platform windows`\n")
      r6:str = str_join2(r5, "- Install module: `tezz install std@0.1.0`\n")
      r7:str = str_join2(r6, "- Environment check: `tezz doctor`\n")
      r8:str = r7
      if streq(template, "api"):
        r8 = str_join2(r7, "- API reference sample: `examples/reference_v1/api_server.tn`\n")
      else if streq(template, "lib"):
        r8 = str_join2(r7, "- Library entry: `src/lib.tn`\n")
      else if streq(template, "gui"):
        r8 = str_join2(r7, "- GUI sample app: `examples/gui_first_app.tn` (run with `tezz run examples/gui_first_app.tn`)\n")
      io.write_all(readme_path, r8)
      free(r0); free(r1); free(r2); free(r3); free(r4); free(r5); free(r6); free(r7)
      if r8 != r7:
        free(r8)
  else:
    main_path = path_join(target, "main.tn")
    if path_exists(main_path) == 0:
      root_tpl:str = "import \"std\"\n\nfn main() -> int:\n  say \"Hello from TezzNative.\"\n  ret 0\n"
      io.write_all(main_path, root_tpl)

  free(src_dir)
  free(tezz_dir)
  free(cache_dir)
  free(mod_path)
  free(lock_path)
  free(main_path)
  free(readme_path)
  done0:str = str_join3("init: project scaffold ready (template=", template, ")")
  say done0
  free(done0)
  ret 0

fn normalize_out(s:str) -> str:
  if s == 0:
    ret 0 as str
  n:int = len(s)
  out:*char = (*char)malloc(n + 1)
  i:int = 0
  j:int = 0
  while i < n:
    if s[i] != 13:
      out[j] = s[i]
      j = j + 1
    i = i + 1
  out[j] = 0 as char
  ret out

fn normalize_slashes(s:str) -> str:
  if s == 0:
    ret 0 as str
  n:int = len(s)
  out:*char = (*char)malloc(n + 1)
  i:int = 0
  while i < n:
    c:int = s[i] as int
    if c == 92:
      out[i] = 47 as char
    else:
      out[i] = s[i]
    i = i + 1
  out[n] = 0 as char
  ret out

fn trim_trailing_ws(s:str) -> str:
  if s == 0:
    ret 0 as str
  n:int = len(s)
  while n > 0:
    c:int = s[n - 1] as int
    if c == 10 || c == 13 || c == 32 || c == 9:
      n = n - 1
      continue
    break
  out:*char = (*char)malloc(n + 1)
  i:int = 0
  while i < n:
    out[i] = s[i]
    i = i + 1
  out[n] = 0 as char
  ret out

fn strip_outer_quotes(s:str) -> str:
  if s == 0:
    ret 0 as str
  n:int = len(s)
  if n >= 2 && s[0] == (34 as char) && s[n - 1] == (34 as char):
    ret substr_dup(s, 1, n - 1)
  ret str_join2("", s)

fn env_value(name:str) -> str:
  if name == 0 || name[0] == 0:
    ret 0 as str
  osn:str = os_name()
  cmd:str = 0 as str
  if streq(osn, "windows"):
    cmd = str_join3("cmd /c echo %", name, "%")
  else:
    cmd = str_join2("printenv ", name)
  out:str = proc_out(cmd)
  free(cmd)
  if out == 0:
    ret 0 as str
  out = normalize_out(out)
  out = trim_line(out)
  if streq(osn, "windows"):
    ph:str = str_join3("%", name, "%")
    if streq(out, ph):
      free(out)
      free(ph)
      ret str_join2("", "")
    free(ph)
  ret out

fn infer_sdk_root_from_tezzc(tezzc:str) -> str:
  if tezzc == 0 || tezzc[0] == 0:
    ret 0 as str
  clean:str = strip_outer_quotes(tezzc)
  if clean == 0 || clean[0] == 0:
    if clean != 0:
      free(clean)
    ret 0 as str
  bin_dir:str = path_dirname(clean)
  root:str = 0 as str
  if bin_dir != 0 && bin_dir[0] != 0:
    root = path_dirname(bin_dir)
  if root != 0 && root[0] != 0:
    toolp:str = path_join(root, "tools/tezz.tn")
    stdp:str = path_join(root, "lib/std.tn")
    if path_exists(toolp) != 0 && path_exists(stdp) != 0:
      free(toolp)
      free(stdp)
      free(bin_dir)
      free(clean)
      ret root
    free(toolp)
    free(stdp)
  if root != 0:
    free(root)
  if bin_dir != 0:
    free(bin_dir)
  free(clean)
  ret 0 as str

fn detect_arch() -> str:
  os:str = os_name()
  os = norm_os(os)
  out:str = 0 as str
  if streq(os, "windows"):
    out = proc_out("cmd /c echo %PROCESSOR_ARCHITECTURE%")
  else:
    out = proc_out("uname -m")
  if out == 0:
    ret dup_lit("unknown")
  out = normalize_out(out)
  out = trim_line(out)
  if starts_with(out, "AMD64") || starts_with(out, "X64") || starts_with(out, "x86_64"):
    free(out)
    ret dup_lit("x64")
  if starts_with(out, "ARM64") || starts_with(out, "AARCH64") || starts_with(out, "arm64") || starts_with(out, "aarch64"):
    free(out)
    ret dup_lit("arm64")
  if starts_with(out, "x86") || starts_with(out, "X86") || starts_with(out, "i386") || starts_with(out, "i686"):
    free(out)
    ret dup_lit("x86")
  ret out

fn tune_source(src:str, block:int, unroll:int) -> str:
  if src == 0:
    ret 0 as str
  bstr:str = int_to_str(block)
  ustr:str = int_to_str(unroll)
  n:int = len(src)
  out:*char = (*char)malloc(n + 64)
  i:int = 0
  w:int = 0
  while i < n:
    line:*char = src + i
    if starts_with(line, "  block:int ="):
      // skip line
      while i < n && src[i] != 10:
        i = i + 1
      // write replacement
      j:int = 0
      rep1:str = "  block:int = "
      while rep1[j] != 0:
        out[w] = rep1[j]
        w = w + 1
        j = j + 1
      j = 0
      while bstr[j] != 0:
        out[w] = bstr[j]
        w = w + 1
        j = j + 1
      out[w] = 10 as char
      w = w + 1
      if i < n && src[i] == 10:
        i = i + 1
      continue
    if starts_with(line, "  unroll:int ="):
      while i < n && src[i] != 10:
        i = i + 1
      j2:int = 0
      rep2:str = "  unroll:int = "
      while rep2[j2] != 0:
        out[w] = rep2[j2]
        w = w + 1
        j2 = j2 + 1
      j2 = 0
      while ustr[j2] != 0:
        out[w] = ustr[j2]
        w = w + 1
        j2 = j2 + 1
      out[w] = 10 as char
      w = w + 1
      if i < n && src[i] == 10:
        i = i + 1
      continue
    // copy line
    while i < n && src[i] != 10:
      out[w] = src[i]
      w = w + 1
      i = i + 1
    if i < n && src[i] == 10:
      out[w] = 10 as char
      w = w + 1
      i = i + 1
  out[w] = 0 as char
  free(bstr)
  free(ustr)
  ret out

fn trim_line(s:str) -> str:
  if s == 0:
    ret 0 as str
  n:int = len(s)
  i:int = n - 1
  while i >= 0:
    c:int = s[i] as int
    if c == 10 || c == 13:
      s[i] = 0 as char
    else:
      break
    i = i - 1
  ret s

fn has_kernel_fn(path:str) -> int:
  if path == 0:
    ret 0
  src:str = io.read_all(path)
  if src == 0:
    ret 0
  k:int = str_contains(src, "kernel fn")
  free(src)
  ret k

fn dxc_available() -> int:
  os:str = os_name()
  out:str = 0 as str
  if streq(os, "windows"):
    out = proc_out("where dxc")
  else:
    out = proc_out("which dxc")
  if out == 0:
    ret 0
  out = normalize_out(out)
  out = trim_line(out)
  if out[0] == 0:
    free(out)
    ret 0
  free(out)
  ret 1

fn replace_substr(s:str, pat:str, rep:str) -> str:
  if s == 0 || pat == 0 || rep == 0:
    ret s
  plen:int = len(pat)
  if plen <= 0:
    ret s
  rlen:int = len(rep)
  n:int = len(s)

  cnt:int = 0
  i:int = 0
  while i < n:
    if starts_with_at(s, i, pat) != 0:
      cnt = cnt + 1
      i = i + plen
      continue
    i = i + 1
  if cnt == 0:
    ret s

  out_len:int = n + (rlen - plen) * cnt
  out:*char = (*char)malloc(out_len + 1)
  i = 0
  w:int = 0
  while i < n:
    if starts_with_at(s, i, pat) != 0:
      j:int = 0
      while j < rlen:
        out[w] = rep[j]
        w = w + 1
        j = j + 1
      i = i + plen
      continue
    out[w] = s[i]
    w = w + 1
    i = i + 1
  out[w] = 0 as char
  free(s)
  ret out

fn simple_mode_disallow_reason(src:str) -> str:
  if src == 0:
    ret 0 as str
  if str_contains(src, "unsafe") != 0:
    ret dup_lit("unsafe blocks are systems-only")
  if str_contains(src, " as *") != 0:
    ret dup_lit("pointer casts are systems-only")
  if str_contains(src, "malloc(") != 0:
    ret dup_lit("manual heap allocation is systems-only")
  if str_contains(src, "free(") != 0:
    ret dup_lit("manual memory free is systems-only")
  if str_contains(src, "sizeof(") != 0:
    ret dup_lit("sizeof is systems-only")
  if str_contains(src, "*char") != 0 || str_contains(src, "*int") != 0 || str_contains(src, "*float") != 0 || str_contains(src, "*str") != 0:
    ret dup_lit("pointer types are systems-only")
  ret 0 as str

fn simple_mode_has_decl_tokens(src:str) -> int:
  if src == 0:
    ret 0
  if starts_with(src, "fn ") != 0 || starts_with(src, "struct ") != 0 || starts_with(src, "enum ") != 0 || starts_with(src, "typedef ") != 0:
    ret 1
  if starts_with(src, "extern ") != 0 || starts_with(src, "kernel ") != 0 || starts_with(src, "static ") != 0:
    ret 1
  if str_contains(src, "\nfn ") != 0 || str_contains(src, "\nstruct ") != 0 || str_contains(src, "\nenum ") != 0 || str_contains(src, "\ntypedef ") != 0:
    ret 1
  if str_contains(src, "\nextern ") != 0 || str_contains(src, "\nkernel ") != 0 || str_contains(src, "\nstatic ") != 0:
    ret 1
  ret 0

fn simple_mode_transform(src:str) -> str:
  if src == 0:
    ret 0 as str
  needs_std:int = 0
  if str_contains(src, "import \"std\"") == 0:
    needs_std = 1
  wrap:int = 0
  if str_contains(src, "fn main(") == 0 && simple_mode_has_decl_tokens(src) == 0:
    wrap = 1
  if wrap == 0:
    if needs_std != 0:
      ret str_join2("import \"std\"\n", src)
    ret str_join2("", src)
  n:int = len(src)
  imports:*char = (*char)malloc((n * 2) + 64)
  body:*char = (*char)malloc((n * 4) + 64)
  wi:int = 0
  wb:int = 0
  i:int = 0
  while 1:
    ls:int = i
    while src[i] != 0 as char && src[i] != 10 as char:
      i = i + 1
    le:int = i
    t:int = ls
    while t < le && ((src[t] as int) == 32 || (src[t] as int) == 9):
      t = t + 1
    is_import:int = 0
    if (le - t) >= 7:
      if src[t] == 105 as char && src[t + 1] == 109 as char && src[t + 2] == 112 as char && src[t + 3] == 111 as char && src[t + 4] == 114 as char && src[t + 5] == 116 as char && src[t + 6] == 32 as char:
        is_import = 1
    if is_import != 0:
      k:int = ls
      while k < le:
        imports[wi] = src[k]
        wi = wi + 1
        k = k + 1
      imports[wi] = 10 as char
      wi = wi + 1
    else:
      body[wb] = 32 as char
      body[wb + 1] = 32 as char
      wb = wb + 2
      k2:int = ls
      while k2 < le:
        body[wb] = src[k2]
        wb = wb + 1
        k2 = k2 + 1
      body[wb] = 10 as char
      wb = wb + 1
    if src[i] == 0 as char:
      break
    i = i + 1
  imports[wi] = 0 as char
  body[wb] = 0 as char

  hdr:str = str_join2("", "")
  if needs_std != 0:
    free(hdr)
    hdr = str_join2("import \"std\"\n", "")
  h1:str = str_join2(hdr, imports as str)
  m0:str = str_join2(h1, "fn main() -> int:\n")
  m1:str = str_join2(m0, body as str)
  out:str = str_join2(m1, "  ret 0\n")
  free(imports)
  free(body)
  free(hdr)
  free(h1)
  free(m0)
  free(m1)
  ret out

fn compat_rewrite_input_mode(path:str) -> str:
  if path == 0:
    ret 0 as str
  src:str = io.read_all(path)
  if src == 0:
    ret 0 as str
  changed:int = 0
  if str_contains(src, "INPUT_INT") != 0 || str_contains(src, "INPUT_FLOAT") != 0 || str_contains(src, "INPUT_STR") != 0:
    changed = 1
    src = replace_substr(src, ", INPUT_INT)", ")")
    src = replace_substr(src, ",INPUT_INT)", ")")
    src = replace_substr(src, ", INPUT_FLOAT)", ")")
    src = replace_substr(src, ",INPUT_FLOAT)", ")")
    src = replace_substr(src, ", INPUT_STR)", ")")
    src = replace_substr(src, ",INPUT_STR)", ")")
  if changed == 0:
    free(src)
    ret 0 as str
  out_path:str = str_join2(path, ".compat.tn")
  io.write_all(out_path, src)
  free(src)
  ret out_path

fn hlsl_first_entry(path:str) -> str:
  if path == 0:
    ret 0 as str
  s:str = io.read_all(path)
  if s == 0:
    ret 0 as str
  i:int = 0
  while s[i] != 0:
    while s[i] == 32 || s[i] == 9 || s[i] == 10 || s[i] == 13:
      i = i + 1
    if starts_with_at(s, i, "void ") != 0:
      j:int = i + 5
      while s[j] == 32 || s[j] == 9:
        j = j + 1
      start:int = j
      while s[j] != 0 && s[j] != 40 && s[j] != 32 && s[j] != 9:
        j = j + 1
      if j > start:
        out:str = substr_dup(s, start, j)
        free(s)
        ret out
    while s[i] != 0 && s[i] != 10:
      i = i + 1
    if s[i] == 10:
      i = i + 1
  free(s)
  ret 0 as str

fn sanitize_name(s:str) -> str:
  if s == 0:
    ret 0 as str
  n:int = len(s)
  out:*char = (*char)malloc(n + 1)
  i:int = 0
  while i < n:
    c:int = s[i] as int
    good:int = 0
    if (c >= 48 && c <= 57) || (c >= 65 && c <= 90) || (c >= 97 && c <= 122) || c == 95:
      good = 1
    if good != 0:
      out[i] = s[i]
    else:
      out[i] = 95 as char
    i = i + 1
  out[n] = 0 as char
  ret out

fn hlsl_collect_entries(path:str) -> str:
  if path == 0:
    ret 0 as str
  s:str = io.read_all(path)
  if s == 0:
    ret 0 as str
  out:str = 0 as str
  i:int = 0
  while s[i] != 0:
    while s[i] == 32 || s[i] == 9 || s[i] == 10 || s[i] == 13:
      i = i + 1
    if starts_with_at(s, i, "void ") != 0:
      j:int = i + 5
      while s[j] == 32 || s[j] == 9:
        j = j + 1
      start:int = j
      while s[j] != 0 && s[j] != 40 && s[j] != 32 && s[j] != 9:
        j = j + 1
      if j > start:
        ent:str = substr_dup(s, start, j)
        line:str = str_join2(ent, "\n")
        if out == 0:
          out = line
        else:
          tmp:str = str_join2(out, line)
          free(out)
          free(line)
          out = tmp
        free(ent)
    while s[i] != 0 && s[i] != 10:
      i = i + 1
    if s[i] == 10:
      i = i + 1
  free(s)
  ret out

fn line0(s:str) -> str:
  if s == 0:
    ret 0 as str
  i:int = 0
  while s[i] != 0 && s[i] != 10:
    i = i + 1
  ret substr_dup(s, 0, i)

fn line1(s:str) -> str:
  if s == 0:
    ret 0 as str
  i:int = 0
  while s[i] != 0 && s[i] != 10:
    i = i + 1
  if s[i] == 10:
    i = i + 1
  j:int = i
  while s[j] != 0 && s[j] != 10:
    j = j + 1
  ret substr_dup(s, i, j)

fn line0_nonempty(s:str) -> str:
  if s == 0:
    ret 0 as str
  i:int = 0
  while s[i] != 0:
    while s[i] == 10 || s[i] == 13:
      i = i + 1
    j:int = i
    while s[j] != 0 && s[j] != 10 && s[j] != 13:
      j = j + 1
    if j > i:
      ret substr_dup(s, i, j)
    i = j
  ret substr_dup(s, 0, 0)

fn line1_nonempty(s:str) -> str:
  if s == 0:
    ret 0 as str
  i:int = 0
  // find first non-empty line
  while s[i] != 0:
    while s[i] == 10 || s[i] == 13:
      i = i + 1
    j:int = i
    while s[j] != 0 && s[j] != 10 && s[j] != 13:
      j = j + 1
    if j > i:
      i = j
      break
    i = j
  // find second non-empty line
  while s[i] != 0:
    while s[i] == 10 || s[i] == 13:
      i = i + 1
    k:int = i
    while s[k] != 0 && s[k] != 10 && s[k] != 13:
      k = k + 1
    if k > i:
      ret substr_dup(s, i, k)
    i = k
  ret substr_dup(s, 0, 0)

fn next_manifest_line(list:str, idx:*int) -> str:
  if list == 0 || idx == 0:
    ret 0 as str
  n:int = len(list)
  i:int = 0
  unsafe:
    i = *idx
  while i < n:
    while i < n:
      c:int = list[i] as int
      if c != 10 && c != 13:
        break
      i = i + 1
    if i >= n:
      break
    start:int = i
    while i < n:
      c2:int = list[i] as int
      if c2 == 10 || c2 == 13:
        break
      i = i + 1
    end:int = i
    while start < end && is_space(list[start] as int):
      start = start + 1
    while end > start && is_space(list[end - 1] as int):
      end = end - 1
    unsafe:
      *idx = i
    if end <= start:
      continue
    if (list[start] as int) == 35:
      continue
    ret substr_dup(list, start, end)
  unsafe:
    *idx = n
  ret 0 as str

fn trim_range_dup(s:str, a:int, b:int) -> str:
  if s == 0:
    ret 0 as str
  if b < a:
    ret 0 as str
  while a < b && is_space(s[a] as int):
    a = a + 1
  while b > a && is_space(s[b - 1] as int):
    b = b - 1
  ret substr_dup(s, a, b)

fn split_pair(line:str, left:*str, right:*str) -> int:
  if line == 0 || left == 0 || right == 0:
    ret 0 - 1
  i:int = 0
  while line[i] != 0 && line[i] != 124:
    i = i + 1
  if line[i] == 0:
    ret 0 - 1
  n:int = len(line)
  a:str = trim_range_dup(line, 0, i)
  b:str = trim_range_dup(line, i + 1, n)
  if a == 0 || b == 0:
    if a != 0:
      free(a)
    if b != 0:
      free(b)
    ret 0 - 1
  unsafe:
    *left = a
    *right = b
  ret 0

fn lock_strip_dep(lock:str, dep:str) -> str:
  if lock == 0 || dep == 0:
    ret 0 as str
  prefix:str = str_join2(dep, "@")
  pn:int = len(prefix)
  n:int = len(lock)
  out:*char = (*char)malloc(n + 1)
  w:int = 0
  i:int = 0
  while i < n:
    line_start:int = i
    while i < n:
      c:int = lock[i] as int
      if c == 10 || c == 13:
        break
      i = i + 1
    line_end:int = i
    // consume newline (\n or \r\n)
    if i < n && (lock[i] as int) == 13:
      i = i + 1
      if i < n && (lock[i] as int) == 10:
        i = i + 1
    else if i < n && (lock[i] as int) == 10:
      i = i + 1
    nl_end:int = i

    // keep the line unless it starts with "<dep>@"
    keep:int = 1
    if pn > 0 && (line_end - line_start) >= pn:
      k:int = 0
      ok:int = 1
      while k < pn:
        if lock[line_start + k] != prefix[k]:
          ok = 0
          break
        k = k + 1
      if ok != 0:
        keep = 0

    if keep != 0:
      j:int = line_start
      while j < nl_end:
        out[w] = lock[j]
        w = w + 1
        j = j + 1
  out[w] = 0 as char
  free(prefix)
  ret out

fn tool_path(name:str) -> str:
  if name == 0:
    ret 0 as str
  osn:str = os_name()
  cmd:str = 0 as str
  if streq(osn, "windows"):
    cmd = str_join2("where ", name)
  else:
    cmd = str_join2("which ", name)
  out:str = proc_out(cmd)
  free(cmd)
  if out == 0:
    ret 0 as str
  i:int = 0
  while out[i] != 0 && out[i] != 10 as char && out[i] != 13 as char:
    i = i + 1
  p:str = trim_range_dup(out, 0, i)
  free(out)
  if p == 0 || p[0] == 0 as char:
    if p != 0:
      free(p)
    ret 0 as str
  ret p

fn tool_exists(name:str) -> int:
  p:str = tool_path(name)
  if p == 0:
    ret 0
  free(p)
  ret 1

fn tezzc_path() -> str:
  over:str = tezzc_override_arg()
  if over != 0:
    if path_exists(over) != 0:
      ret quote_cmd_path(over)
  os:str = os_name()
  if streq(os, "windows"):
    if path_exists(".\\bin\\tezzc.exe") != 0:
      ret quote_cmd_path(".\\bin\\tezzc.exe")
    if path_exists(".\\bin\\tezzc-windows-x64.exe") != 0:
      ret quote_cmd_path(".\\bin\\tezzc-windows-x64.exe")
    if path_exists(".\\build\\tezzc.exe") != 0:
      ret quote_cmd_path(".\\build\\tezzc.exe")
    if path_exists(".\\tezzc.exe") != 0:
      ret quote_cmd_path(".\\tezzc.exe")
    p1:str = tool_path("tezzc.exe")
    if p1 != 0:
      q1:str = quote_cmd_path(p1)
      free(p1)
      ret q1
    p2:str = tool_path("tezzc-windows-x64.exe")
    if p2 != 0:
      q2:str = quote_cmd_path(p2)
      free(p2)
      ret q2
    p3:str = tool_path("tezzc")
    if p3 != 0:
      q3:str = quote_cmd_path(p3)
      free(p3)
      ret q3
    ret 0 as str
  if path_exists("./bin/tezzc") != 0:
    ret quote_cmd_path("./bin/tezzc")
  if path_exists("./bin/tezzc-linux-x64") != 0:
    ret quote_cmd_path("./bin/tezzc-linux-x64")
  if path_exists("./build/tezzc") != 0:
    ret quote_cmd_path("./build/tezzc")
  if path_exists("./tezzc") != 0:
    ret quote_cmd_path("./tezzc")
  p4:str = tool_path("tezzc")
  if p4 != 0:
    q4:str = quote_cmd_path(p4)
    free(p4)
    ret q4
  p5:str = tool_path("tezzc-linux-x64")
  if p5 != 0:
    q5:str = quote_cmd_path(p5)
    free(p5)
    ret q5
  p6:str = tool_path("tezzc.exe")
  if p6 != 0:
    q6:str = quote_cmd_path(p6)
    free(p6)
    ret q6
  ret 0 as str

fn run_to_file(cmd:str, outpath:str) -> int:
  if cmd == 0 || outpath == 0:
    ret 0 - 1
  os:str = os_name()
  if streq(os, "windows"):
    // If cmd already contains quotes, avoid nesting "cmd /c" quotes.
    // Fallback to proc_out + write_all to keep quoting intact.
    i:int = 0
    while cmd[i] != 0:
      if cmd[i] == (34 as char):
        out:str = proc_out(cmd)
        if out == 0:
          ret 1
        io.write_all(outpath, out)
        free(out)
        ret 0
      i = i + 1
    // prefer shell redirection to avoid large proc_out buffers
    p1b:str = str_join3("cmd /c \"", cmd, " > ")
    p2b:str = str_join2(p1b, outpath)
    p3b:str = str_join2(p2b, " 2>&1\"")
    r2:int = proc_run(p3b)
    free(p1b)
    free(p2b)
    free(p3b)
    if r2 != 0:
      // fallback to capture when cmd /c returns non-zero despite valid output
      out2:str = proc_out(cmd)
      if out2 == 0:
        ret r2
      io.write_all(outpath, out2)
      if str_contains(out2, "tezzc error") != 0:
        free(out2)
        ret 1
      free(out2)
      ret 0
    ret r2
  p1b:str = str_join3("sh -c \"", cmd, " > ")
  p2b:str = str_join2(p1b, outpath)
  p3b:str = str_join2(p2b, " 2>&1\"")
  r2:int = proc_run(p3b)
  free(p1b)
  free(p2b)
  free(p3b)
  ret r2

fn wsl_path(win_path:str) -> str:
  if win_path == 0:
    ret 0 as str
  cmd:str = str_join3("wsl -e wslpath -a -u \"", win_path, "\"")
  out:str = proc_out(cmd)
  free(cmd)
  if out != 0:
    // trim_line edits in-place; return the same buffer
    out = trim_line(out)
    if out[0] != 0:
      ret out
    free(out)
  // fallback: manual /mnt/<drive>/path conversion
  n:int = len(win_path)
  if n < 2 || win_path[1] != (58 as char):
    ret 0 as str
  drive:int = win_path[0] as int
  if drive >= 65 && drive <= 90:
    drive = drive + 32
  idx:int = 2
  if n > 2:
    if win_path[2] == (92 as char) || win_path[2] == (47 as char):
      idx = 3
  out_len:int = 7 + (n - idx)
  buf:*char = (*char)malloc(out_len + 1)
  if buf == 0:
    ret 0 as str
  unsafe:
    buf[0] = 47 as char
    buf[1] = 109 as char
    buf[2] = 110 as char
    buf[3] = 116 as char
    buf[4] = 47 as char
    buf[5] = drive as char
    buf[6] = 47 as char
    i:int = idx
    j:int = 7
    while i < n:
      c:char = win_path[i]
      if c == (92 as char):
        c = 47 as char
      buf[j] = c
      i = i + 1
      j = j + 1
    buf[j] = 0 as char
  ret buf as str

fn run_quiet(cmd:str) -> int:
  if cmd == 0:
    ret 0 - 1
  os:str = os_name()
  if streq(os, "windows"):
    p1:str = str_join3("cmd /c \"", cmd, " > nul\"")
    r:int = proc_run(p1)
    free(p1)
    ret r
  p1:str = str_join3("sh -c \"", cmd, " > /dev/null\"")
  r:int = proc_run(p1)
  free(p1)
  ret r

fn csv_op_policy(csv:str) -> str:
  if csv == 0:
    ret 0 as str
  idx:int = 0
  out:str = str_join2("", "op,policy\n")
  while 1:
    line:str = next_manifest_line(csv, &idx)
    if line == 0:
      break
    if starts_with(line, "op,policy") != 0:
      free(line)
      continue
    i:int = 0
    while line[i] != 0 && line[i] != 44:
      i = i + 1
    if line[i] == 44:
      j:int = i + 1
      while line[j] != 0 && line[j] != 44:
        j = j + 1
      if line[j] == 44:
        op:str = substr_dup(line, 0, i)
        pol:str = substr_dup(line, i + 1, j)
        l1:str = str_join3(op, ",", pol)
        l2:str = str_join2(l1, "\n")
        tmp:str = str_join2(out, l2)
        free(out)
        out = tmp
        free(op)
        free(pol)
        free(l1)
        free(l2)
    free(line)
  ret out

fn run_quiet_all(cmd:str) -> int:
  if cmd == 0:
    ret 0 - 1
  os:str = os_name()
  if streq(os, "windows"):
    p1:str = str_join3("cmd /c \"", cmd, " > nul 2>&1\"")
    r:int = proc_run(p1)
    free(p1)
    ret r
  p1:str = str_join3(cmd, " > /dev/null 2>&1", "")
  r:int = proc_run(p1)
  free(p1)
  ret r

fn proc_out_all(cmd:str) -> str:
  if cmd == 0:
    ret 0 as str
  os:str = os_name()
  if streq(os, "windows"):
    p1:str = str_join3("cmd /c \"", cmd, " 2>&1\"")
    out:str = proc_out(p1)
    free(p1)
    if out == 0 || out[0] == 0:
      ensure_dir("build")
      cap:str = "build/proc_out_all_capture.out"
      remove(cap)
      run_to_file(cmd, cap)
      if out != 0:
        free(out)
      out = io.read_all(cap)
      remove(cap)
    ret out
  p1:str = str_join3(cmd, " 2>&1", "")
  out2:str = proc_out(p1)
  free(p1)
  if out2 == 0 || out2[0] == 0:
    ensure_dir("build")
    cap2:str = "build/proc_out_all_capture.out"
    remove(cap2)
    run_to_file(cmd, cap2)
    if out2 != 0:
      free(out2)
    out2 = io.read_all(cap2)
    remove(cap2)
  ret out2

fn expect_fail(cmd:str, needle:str) -> int:
  if cmd == 0:
    ret 0 - 1
  if run_quiet_all(cmd) == 0:
    say "expected failure but command succeeded:"
    say cmd
    ret 1
  if needle == 0 || needle[0] == 0:
    ret 0
  out:str = proc_out_all(cmd)
  if out == 0 || out[0] == 0:
    ensure_dir("build")
    cap_cmd:str = str_join3(cmd, " 2>&1", "")
    cap_path:str = str_join2("build/", "expect_fail_capture.out")
    run_to_file(cap_cmd, cap_path)
    if out != 0:
      free(out)
    out = read_norm(cap_path)
    remove(cap_path)
    free(cap_cmd)
    free(cap_path)
  if out == 0:
    say "expected failure but no output captured:"
    say cmd
    ret 1
  ok:int = 1
  if needle != 0 && needle[0] != 0:
    if str_contains(out, needle) == 0:
      say "failure output missing expected text:"
      say needle
      ok = 0
  free(out)
  if ok == 0:
    ret 1
  ret 0

fn test_run(cmd:str, label:str) -> int:
  r:int = proc_run(cmd)
  if r != 0:
    // Some Windows runs can return non-zero despite succeeding.
    // For run commands, retry via proc_out and treat non-error output as success.
    if str_contains(cmd, " run ") != 0:
      out:str = proc_out(cmd)
      if out != 0:
        if str_contains(out, "tezzc error") == 0:
          free(out)
          ret 0
        free(out)
    say "test command failed:"
    if label != 0:
      say label
    say cmd
    ret r
  ret r

fn read_norm(path:str) -> str:
  s:str = io.read_all(path)
  if s == 0:
    ret 0 as str
  n:str = normalize_out(s)
  free(s)
  if n != 0:
    trim_line(n)
    t:str = trim_trailing_ws(n)
    free(n)
    n = t
  ret n

fn run_parity_manifest(path:str, mode:str, label:str, tezzc:str) -> int:
  list:str = io.read_all(path)
  if list == 0:
    ret 0

  os:str = os_name()
  out_dir:str = "build/"
  if streq(os, "windows"):
    out_dir = ".\\build\\"
  ensure_dir("build")

  idx:int = 0
  failed:int = 0

  while 1:
    start:str = next_manifest_line(list, &idx)
    if start == 0:
      break
    if streq(mode, "--bc") != 0:
      base:str = path_basename_no_ext(start)
      if base == 0 || base[0] == 0:
        if base != 0:
          free(base)
        failed = failed + 1
        free(start)
        continue
      out_bc_path:str = str_join3(out_dir, base, "_bcvm.out")
      cmd_vm:str = str_join3(tezzc, " run --bc ", start)
      if run_to_file(cmd_vm, out_bc_path) != 0:
        say label
        say " run failed:"
        say start
        failed = failed + 1
      remove(out_bc_path)
      free(out_bc_path)
      free(cmd_vm)
      free(base)
      free(start)
      continue

    base:str = path_basename_no_ext(start)
    if base == 0 || base[0] == 0:
      if base != 0:
        free(base)
      failed = failed + 1
      free(start)
      continue

    out_vm_path:str = str_join3(out_dir, base, "_vm.out")
    out_m_path:str = str_join3(out_dir, base, "_m.out")

    cmd_vm:str = str_join3(tezzc, " run --bc ", start)
    rv:int = run_to_file(cmd_vm, out_vm_path)
    if rv != 0:
      failed = failed + 1

    cmd_m1:str = str_join3(tezzc, " run ", mode)
    cmd_m2:str = str_join3(cmd_m1, " ", start)
    rm:int = run_to_file(cmd_m2, out_m_path)
    if rm != 0:
      failed = failed + 1

    out_vm:str = 0 as str
    out_m:str = 0 as str
    if rv == 0:
      out_vm = read_norm(out_vm_path)
      if out_vm == 0:
        failed = failed + 1
    if rm == 0:
      out_m = read_norm(out_m_path)
      if out_m == 0:
        failed = failed + 1

    if out_vm != 0 && out_m != 0 && strcmp(out_vm, out_m) != 0:
      say label
      say " mismatch:"
      say start
      failed = failed + 1

    if out_vm != 0:
      free(out_vm)
    if out_m != 0:
      free(out_m)
    remove(out_vm_path)
    remove(out_m_path)
    free(out_vm_path)
    free(out_m_path)
    free(cmd_vm)
    free(cmd_m1)
    free(cmd_m2)
    free(base)
    free(start)

  free(list)
  ret failed

fn clean_dir(path:str) -> int:
  if path == 0:
    ret 0 - 1
  if path_exists(path) == 0:
    ret 0
  if path_is_dir(path) == 0:
    ret remove(path)
  list:str = io.dir_list_rec(path)
  if list == 0:
    ret 0
  n:int = len(list)
  i:int = 0
  start:*char = list
  for ;;:
    c:int = list[i] as int
    if c == 0 || c == 10:
      list[i] = 0 as char
      if start != list + i:
        if path_is_dir(start) == 0:
          remove(start)
      if c == 0:
        break
      start = list + i + 1
    i = i + 1
  i = n
  while i > 0:
    while i > 0 && list[i - 1] == 0:
      i = i - 1
    if i == 0:
      break
    while i > 0 && list[i - 1] != 0:
      i = i - 1
    p:*char = list + i
    if p[0] != 0 && path_is_dir(p) != 0:
      rmdir(p)
  free(list)
  ret 0

fn append_line_file(path:str, line:str):
  if path == 0 || line == 0:
    ret
  prev:str = io.read_all(path)
  if prev == 0:
    one:str = str_join2(line, "\n")
    io.write_all(path, one)
    free(one)
    ret
  next:str = str_join3(prev, line, "\n")
  io.write_all(path, next)
  free(next)
  free(prev)

fn run_vm_manifest_once(list_path:str, tezzc:str, label:str) -> int:
  list:str = io.read_all(list_path)
  if list == 0:
    msg:str = str_join2("missing ", list_path)
    say msg
    free(msg)
    ret 1
  idx:int = 0
  failed:int = 0
  while 1:
    start:str = next_manifest_line(list, &idx)
    if start == 0:
      break
    cmd1:str = str_join3(tezzc, " run --bc ", start)
    if test_run(cmd1, label) != 0:
      failed = failed + 1
    free(cmd1)
    free(start)
  free(list)
  ret failed

fn run_vm_manifest_quiet_once(list_path:str, tezzc:str, label:str) -> int:
  list:str = io.read_all(list_path)
  if list == 0:
    msg:str = str_join2("missing ", list_path)
    say msg
    free(msg)
    ret 1
  idx:int = 0
  failed:int = 0
  while 1:
    start:str = next_manifest_line(list, &idx)
    if start == 0:
      break
    cmd1:str = str_join3(tezzc, " run --bc ", start)
    rc:int = run_quiet_all(cmd1)
    if rc != 0:
      failed = failed + 1
      say "runtime soak command failed:"
      if label != 0:
        say label
      say start
      out1:str = proc_out_all(cmd1)
      if out1 != 0:
        append_line_file("build/runtime_soak_fail.log", out1)
        free(out1)
    free(cmd1)
    free(start)
  free(list)
  ret failed

fn run_check_manifest(list_path:str, tezzc:str, label:str, tail_flags:str) -> int:
  list:str = io.read_all(list_path)
  if list == 0:
    msg:str = str_join2("missing ", list_path)
    say msg
    free(msg)
    ret 1
  idx:int = 0
  failed:int = 0
  while 1:
    start:str = next_manifest_line(list, &idx)
    if start == 0:
      break
    cmd1:str = str_join3(tezzc, " check ", start)
    cmd2:str = cmd1
    own_cmd2:int = 0
    if tail_flags != 0 && tail_flags[0] != 0:
      cmd2 = str_join3(cmd1, " ", tail_flags)
      own_cmd2 = 1
    if test_run(cmd2, label) != 0:
      failed = failed + 1
    if own_cmd2 != 0:
      free(cmd2)
    free(cmd1)
    free(start)
  free(list)
  ret failed

fn run_fail_manifest(list_path:str, tezzc:str, tail_flags:str) -> int:
  list:str = io.read_all(list_path)
  if list == 0:
    msg:str = str_join2("missing ", list_path)
    say msg
    free(msg)
    ret 1
  idx:int = 0
  failed:int = 0
  while 1:
    line:str = next_manifest_line(list, &idx)
    if line == 0:
      break
    in_path:str = 0 as str
    needle:str = 0 as str
    if split_pair(line, &in_path, &needle) != 0:
      failed = failed + 1
      free(line)
      continue
    cmd1:str = str_join3(tezzc, " check ", in_path)
    cmd2:str = cmd1
    own_cmd2:int = 0
    if tail_flags != 0 && tail_flags[0] != 0:
      cmd2 = str_join3(cmd1, " ", tail_flags)
      own_cmd2 = 1
    if expect_fail(cmd2, needle) != 0:
      failed = failed + 1
    if own_cmd2 != 0:
      free(cmd2)
    free(cmd1)
    if in_path != 0:
      free(in_path)
    if needle != 0:
      free(needle)
    free(line)
  free(list)
  ret failed

fn run_abi_manifest_tests(tezzc:str) -> int:
  abi_list:str = io.read_all("tests/abi_manifest.tnx")
  if abi_list == 0:
    say "missing tests/abi_manifest.tnx"
    ret 1
  os:str = os_name()
  os = norm_os(os)
  out_dir:str = "build/"
  if streq(os, "windows"):
    out_dir = ".\\build\\"
  ensure_dir("build")
  idx:int = 0
  failed:int = 0
  while 1:
    line:str = next_manifest_line(abi_list, &idx)
    if line == 0:
      break
    in_path:str = 0 as str
    out_path:str = 0 as str
    if split_pair(line, &in_path, &out_path) != 0:
      failed = failed + 1
      free(line)
      continue
    tmp_out:str = str_join2(out_dir, "abi_runtime_tmp.tnx")
    cmd_ab1:str = str_join3(tezzc, " abidump ", in_path)
    cmd_ab2a:str = str_join3(cmd_ab1, " ", tmp_out)
    cmd_ab2:str = str_join2(cmd_ab2a, " --freestanding")
    if test_run(cmd_ab2, "runtime abi abidump") != 0:
      failed = failed + 1
    else:
      exp_a:str = read_norm(out_path)
      act_a:str = read_norm(tmp_out)
      if exp_a == 0 || act_a == 0 || strcmp(exp_a, act_a) != 0:
        say "runtime abi mismatch:"
        say in_path
        failed = failed + 1
      if exp_a != 0:
        free(exp_a)
      if act_a != 0:
        free(act_a)
    remove(tmp_out)
    cmd_av1:str = str_join3(tezzc, " abiverify ", in_path)
    cmd_av2a:str = str_join3(cmd_av1, " ", out_path)
    cmd_av2:str = str_join2(cmd_av2a, " --freestanding")
    if test_run(cmd_av2, "runtime abi abiverify") != 0:
      failed = failed + 1
    free(cmd_ab1)
    free(cmd_ab2a)
    free(cmd_ab2)
    free(cmd_av1)
    free(cmd_av2a)
    free(cmd_av2)
    free(tmp_out)
    if in_path != 0:
      free(in_path)
    if out_path != 0:
      free(out_path)
    free(line)
  free(abi_list)
  ret failed

fn run_runtime_hardening_lane(tezzc:str) -> int:
  failed:int = 0
  failed = failed + run_vm_manifest_once("tests/runtime_hardening_manifest.tnx", tezzc, "runtime hardening")
  failed = failed + run_abi_manifest_tests(tezzc)
  failed = failed + run_check_manifest("tests/runtime_boundary_ok_manifest.tnx", tezzc, "runtime boundary", "--freestanding")
  failed = failed + run_fail_manifest("tests/runtime_boundary_fail_manifest.tnx", tezzc, "--freestanding")
  if failed == 0:
    say "RUNTIME HARDENING TESTS PASSED"
  ret failed

fn run_runtime_fuzz_lane(tezzc:str, rounds:int, long_iters:int) -> int:
  if rounds <= 0:
    rounds = 1
  if long_iters <= 0:
    long_iters = 256
  ensure_dir("build")
  triage_path:str = "build/fuzz_triage.tnx"
  remove(triage_path)
  failed:int = 0
  i:int = 0
  while i < rounds:
    round_s:str = int_to_str(i + 1)
    cmd1:str = str_join3(tezzc, " run --bc ", "tests/tnx_fuzz.tn")
    if test_run(cmd1, "runtime fuzz short") != 0:
      failed = failed + 1
      tri1a:str = str_join3("tests/tnx_fuzz.tn|round=", round_s, "|cmd=")
      tri1b:str = str_join2(tri1a, cmd1)
      append_line_file(triage_path, tri1b)
      free(tri1a)
      free(tri1b)
    free(cmd1)

    seed_s:str = int_to_str(1000 + i)
    iters_s:str = int_to_str(long_iters)
    c2a:str = str_join3(tezzc, " run --bc ", "tests/tnx_fuzz_long.tn")
    c2b:str = str_join3(c2a, " -- --seed ", seed_s)
    c2c:str = str_join3(c2b, " --iters ", iters_s)
    if test_run(c2c, "runtime fuzz long") != 0:
      failed = failed + 1
      tri2a:str = str_join3("tests/tnx_fuzz_long.tn|round=", round_s, "|seed=")
      tri2b:str = str_join3(tri2a, seed_s, "|iters=")
      tri2c:str = str_join3(tri2b, iters_s, "|cmd=")
      tri2d:str = str_join2(tri2c, c2c)
      append_line_file(triage_path, tri2d)
      free(tri2a)
      free(tri2b)
      free(tri2c)
      free(tri2d)
    free(c2a)
    free(c2b)
    free(c2c)
    free(seed_s)
    free(iters_s)
    free(round_s)
    i = i + 1
  if failed == 0:
    rounds_ok:str = int_to_str(rounds)
    summary:str = str_join3("runtime_fuzz: ok rounds=", rounds_ok, " (no triage)")
    append_line_file(triage_path, summary)
    free(rounds_ok)
    free(summary)
    say "RUNTIME FUZZ TESTS PASSED"
  else:
    msg:str = str_join2("runtime fuzz triage: ", triage_path)
    say msg
    free(msg)
  ret failed

fn run_runtime_soak_lane(tezzc:str, minutes:int) -> int:
  if minutes <= 0:
    minutes = 1
  ensure_dir("build")
  start_ms:int = time.now_ms()
  end_ms:int = start_ms + (minutes * 60000)
  rounds:int = 0
  failed:int = 0
  while time.now_ms() < end_ms:
    rounds = rounds + 1
    failed = failed + run_vm_manifest_quiet_once("tests/runtime_soak_manifest.tnx", tezzc, "runtime soak")
    if failed != 0:
      break
  if rounds == 0:
    rounds = 1
    failed = failed + run_vm_manifest_quiet_once("tests/runtime_soak_manifest.tnx", tezzc, "runtime soak")
  rounds_s:str = int_to_str(rounds)
  mins_s:str = int_to_str(minutes)
  sum1:str = str_join3("runtime_soak minutes=", mins_s, " rounds=")
  sum2:str = str_join2(sum1, rounds_s)
  io.write_all("build/runtime_soak_summary.txt", sum2)
  free(sum1)
  free(sum2)
  free(rounds_s)
  free(mins_s)
  if failed == 0:
    say "RUNTIME SOAK TESTS PASSED"
  ret failed

fn run_runtime_io_smoke(tezzc:str) -> int:
  ensure_dir("build")
  script_path:str = "build/runtime_io_smoke.tn"
  out_path:str = "build/runtime_io_smoke.out"
  if path_exists(out_path) != 0:
    remove(out_path)
  script_src:str = "import \"io\"\nfn main() -> int:\n  n:int = io.write_all(\"build/runtime_io_smoke.out\", \"tezz-io-smoke\")\n  if n <= 0:\n    say \"IO_SMOKE_WRITE_FAIL\"\n    ret 0 - 1\n  s:str = io.read_all(\"build/runtime_io_smoke.out\")\n  if s == 0:\n    say \"IO_SMOKE_READ_FAIL\"\n    ret 0 - 1\n  if strcmp(s, \"tezz-io-smoke\") != 0:\n    say \"IO_SMOKE_CONTENT_FAIL\"\n    ret 0 - 1\n  say \"IO_SMOKE_OK\"\n  ret 0\n"
  if io.write_all(script_path, script_src) < 0:
    say "runtime io smoke: failed to write generated script"
    ret 0 - 1
  cmd:str = str_join3(tezzc, " run --bc ", script_path)
  rc:int = proc_run(cmd)
  free(cmd)
  if rc != 0:
    say "runtime io smoke: bytecode run failed"
    ret 0 - 1
  if path_exists(out_path) == 0:
    say "runtime io smoke: output file not created"
    ret 0 - 1
  say "RUNTIME IO SMOKE PASSED"
  ret 0

fn run_simple_mode_smoke() -> int:
  ensure_dir("build")
  script_path:str = "build/simple_mode_smoke.tn"
  out_path:str = "build/simple_mode_smoke.out"
  if path_exists(out_path) != 0:
    remove(out_path)
  script_src:str = "import \"io\"\n\nsay \"simple-smoke-ok\"\nio.write_all(\"build/simple_mode_smoke.out\", \"ok\")\n"
  if io.write_all(script_path, script_src) < 0:
    say "simple mode smoke: failed to write generated script"
    ret 0 - 1
  osn:str = os_name()
  runner:str = "tezz"
  if streq(osn, "windows"):
    if path_exists(".\\tezz.cmd") != 0:
      runner = ".\\tezz.cmd"
    else:
      runner = "tezz.cmd"
  else:
    if path_exists("./tezz") != 0:
      runner = "./tezz"
  c0:str = str_join3(runner, " run ", script_path)
  c1:str = str_join2(c0, " --mode simple")
  rc:int = proc_run(c1)
  free(c0)
  free(c1)
  if rc != 0:
    say "simple mode smoke: command failed"
    ret 0 - 1
  if path_exists(out_path) == 0:
    say "simple mode smoke: output file not created"
    ret 0 - 1
  out:str = io.read_all(out_path)
  if out == 0:
    say "simple mode smoke: failed to read output"
    ret 0 - 1
  if strcmp(out, "ok") != 0:
    say "simple mode smoke: unexpected output"
    free(out)
    ret 0 - 1
  free(out)
  say "SIMPLE MODE SMOKE PASSED"
  ret 0

fn cmd_test() -> int:
  if user_args_count() >= 2:
    a0:str = arg(1)
    if streq(a0, "--help") || streq(a0, "-h"):
      print_usage_test()
      ret 0
  parity:int = 0
  parity_debug:int = 0
  cross:int = 0
  smoke:int = 0
  conformance:int = 0
  conformance_strict:int = 0
  stdlib_v1:int = 0
  tooling:int = 0
  gui_lane:int = 0
  runtime_hardening:int = 0
  runtime_fuzz:int = 0
  runtime_soak:int = 0
  io_smoke:int = 0
  simple_smoke:int = 0
  legacy_unstable:int = 0
  kernel_perf:int = 0
  fuzz_rounds:int = 4
  fuzz_iters:int = 512
  soak_hours:int = 0
  soak_minutes:int = 0
  host_win_arm64:int = 0
  host_macos:int = 0
  host_linux_arm64:int = 0
  accel:int = 0
  accel_onnx:int = 0
  ai:int = 1
  while ai < args_count():
    a:str = arg(ai)
    if streq(a, "--smoke"):
      smoke = 1
    if streq(a, "--conformance"):
      conformance = 1
    if streq(a, "--conformance-strict"):
      conformance_strict = 1
    if streq(a, "--stdlib-v1"):
      stdlib_v1 = 1
    if streq(a, "--tooling"):
      tooling = 1
    if streq(a, "--gui"):
      gui_lane = 1
    if streq(a, "--runtime-hardening"):
      runtime_hardening = 1
    if streq(a, "--runtime-fuzz"):
      runtime_fuzz = 1
    if streq(a, "--runtime-soak"):
      runtime_soak = 1
    if streq(a, "--io-smoke"):
      io_smoke = 1
    if streq(a, "--simple-smoke"):
      simple_smoke = 1
    if streq(a, "--legacy-unstable"):
      legacy_unstable = 1
    if streq(a, "--kernel-perf"):
      kernel_perf = 1
    if streq(a, "--soak-fast"):
      runtime_soak = 1
      soak_minutes = 1
    if streq(a, "--fuzz-rounds") && (ai + 1) < args_count():
      runtime_fuzz = 1
      fuzz_rounds = parse_i64(arg(ai + 1))
      ai = ai + 2
      continue
    if streq(a, "--fuzz-iters") && (ai + 1) < args_count():
      runtime_fuzz = 1
      fuzz_iters = parse_i64(arg(ai + 1))
      ai = ai + 2
      continue
    if streq(a, "--soak-hours") && (ai + 1) < args_count():
      runtime_soak = 1
      soak_hours = parse_i64(arg(ai + 1))
      ai = ai + 2
      continue
    if streq(a, "--soak-minutes") && (ai + 1) < args_count():
      runtime_soak = 1
      soak_minutes = parse_i64(arg(ai + 1))
      ai = ai + 2
      continue
    if streq(a, "--parity"):
      parity = 1
    if streq(a, "--parity-debug"):
      parity_debug = 1
    if streq(a, "--cross"):
      cross = 1
    if streq(a, "--host-win-arm64"):
      host_win_arm64 = 1
    if streq(a, "--host-macos"):
      host_macos = 1
    if streq(a, "--host-linux-arm64"):
      host_linux_arm64 = 1
    if streq(a, "--accel"):
      accel = 1
    if streq(a, "--accel-onnx"):
      accel_onnx = 1
    ai = ai + 1

  if conformance_strict != 0:
    conformance = 1

  tezzc:str = tezzc_path()
  if tezzc == 0:
    say "tezz test: compiler not found"
    ret 0 - 1
  os:str = os_name()
  os = norm_os(os)

  if runtime_hardening != 0 || runtime_fuzz != 0 || runtime_soak != 0 || io_smoke != 0 || simple_smoke != 0:
    ensure_dir("build")
    lane_failed:int = 0
    if io_smoke != 0:
      lane_failed = lane_failed + run_runtime_io_smoke(tezzc)
    if simple_smoke != 0:
      lane_failed = lane_failed + run_simple_mode_smoke()
    if runtime_hardening != 0:
      lane_failed = lane_failed + run_runtime_hardening_lane(tezzc)
    if runtime_fuzz != 0:
      lane_failed = lane_failed + run_runtime_fuzz_lane(tezzc, fuzz_rounds, fuzz_iters)
    if runtime_soak != 0:
      soak_total_minutes:int = soak_minutes
      if soak_total_minutes <= 0 && soak_hours > 0:
        soak_total_minutes = soak_hours * 60
      if soak_total_minutes <= 0:
        soak_total_minutes = 1
      lane_failed = lane_failed + run_runtime_soak_lane(tezzc, soak_total_minutes)
    if lane_failed != 0:
      ret 0 - 1
    say "RUNTIME LANES PASSED"
    ret 0

  if stdlib_v1 != 0:
    ensure_dir("build")
    lane_failed:int = 0
    lane_failed = lane_failed + run_vm_manifest_once("tests/stdlib_v1_manifest.tnx", tezzc, "stdlib v1")
    lane_failed = lane_failed + run_check_manifest("tests/stdlib_v1_check_manifest.tnx", tezzc, "stdlib v1 check", "")
    lane_failed = lane_failed + run_vm_manifest_once("tests/reference_apps_manifest.tnx", tezzc, "reference apps")
    lane_failed = lane_failed + run_check_manifest("tests/reference_apps_manifest.tnx", tezzc, "reference apps check", "")
    lane_failed = lane_failed + run_check_manifest("tests/snippets_check_manifest.tnx", tezzc, "snippet check", "")
    if lane_failed != 0:
      ret 0 - 1
    say "STDLIB V1 TESTS PASSED"
    ret 0

  if tooling != 0:
    ensure_dir("build")
    lane_failed2:int = 0
    lane_failed2 = lane_failed2 + run_vm_manifest_once("tests/tooling_manifest.tnx", tezzc, "tooling")
    lane_failed2 = lane_failed2 + run_check_manifest("tests/snippets_check_manifest.tnx", tezzc, "snippet check", "")
    if lane_failed2 != 0:
      ret 0 - 1
    say "TOOLING TESTS PASSED"
    ret 0

  if gui_lane != 0:
    ensure_dir("build")
    lane_failed3:int = 0
    lane_failed3 = lane_failed3 + run_vm_manifest_once("tests/gui_manifest.tnx", tezzc, "gui")
    lane_failed3 = lane_failed3 + run_check_manifest("tests/gui_check_manifest.tnx", tezzc, "gui check", "")
    if lane_failed3 != 0:
      ret 0 - 1
    say "GUI LANE PASSED"
    ret 0

  list_path:str = "tests/manifest.tnx"
  if conformance != 0:
    list_path = "tests/conformance_manifest.tnx"
  else if smoke != 0:
    list_path = "tests/smoke_manifest.tnx"
  list:str = io.read_all(list_path)
  if list == 0:
    msg0:str = str_join2("missing ", list_path)
    say msg0
    free(msg0)
    ret 0 - 1
  ensure_dir("build")
  exe_suffix:str = ""
  out_dir:str = "build/"
  if streq(os, "windows"):
    exe_suffix = ".exe"
    out_dir = ".\\build\\"

  // Auto-enable host-run gates on native hosts
  arch:str = detect_arch()
  if host_win_arm64 == 0 && streq(os, "windows") != 0 && streq(arch, "arm64") != 0:
    host_win_arm64 = 1
  if host_linux_arm64 == 0 && streq(os, "linux") != 0 && streq(arch, "arm64") != 0:
    host_linux_arm64 = 1
  if host_macos == 0 && streq(os, "macos") != 0:
    host_macos = 1
  if arch != 0:
    free(arch)

  idx:int = 0
  failed:int = 0

  if parity == 0 || smoke != 0 || conformance != 0:
    while 1:
      start:str = next_manifest_line(list, &idx)
      if start == 0:
        break
      // VM run (non-parity)
      cmd_vm:str = str_join3(tezzc, " run --bc ", start)
      if test_run(cmd_vm, "vm run") != 0:
        failed = failed + 1
      free(cmd_vm)
      free(start)

    if legacy_unstable != 0:
      failed = failed + run_vm_manifest_once("tests/legacy_unstable_manifest.tnx", tezzc, "vm run (legacy unstable)")

  if smoke != 0 || conformance != 0:
    if conformance != 0:
      conf_check_list:str = io.read_all("tests/conformance_check_manifest.tnx")
      if conf_check_list == 0:
        say "missing tests/conformance_check_manifest.tnx"
        failed = failed + 1
      else:
        idx = 0
        while 1:
          chk_path:str = next_manifest_line(conf_check_list, &idx)
          if chk_path == 0:
            break
          cmd_cc:str = str_join3(tezzc, " check ", chk_path)
          if test_run(cmd_cc, "conformance check") != 0:
            failed = failed + 1
          free(cmd_cc)
          free(chk_path)
        free(conf_check_list)

      conf_fail_list:str = io.read_all("tests/conformance_fail_manifest.tnx")
      if conf_fail_list == 0:
        say "missing tests/conformance_fail_manifest.tnx"
        failed = failed + 1
      else:
        idx = 0
        while 1:
          line:str = next_manifest_line(conf_fail_list, &idx)
          if line == 0:
            break
          in_path:str = 0 as str
          needle:str = 0 as str
          if split_pair(line, &in_path, &needle) != 0:
            failed = failed + 1
            free(line)
            continue
          cmd_cf:str = str_join3(tezzc, " check ", in_path)
          if expect_fail(cmd_cf, needle) != 0:
            failed = failed + 1
          free(cmd_cf)
          if in_path != 0:
            free(in_path)
          if needle != 0:
            free(needle)
          free(line)
        free(conf_fail_list)

      // Deterministic AST snapshots (formatter canonical output)
      conf_ast_list:str = io.read_all("tests/conformance_ast_manifest.tnx")
      if conf_ast_list == 0:
        say "missing tests/conformance_ast_manifest.tnx"
        failed = failed + 1
      else:
        idx = 0
        while 1:
          line:str = next_manifest_line(conf_ast_list, &idx)
          if line == 0:
            break
          in_path:str = 0 as str
          out_path:str = 0 as str
          if split_pair(line, &in_path, &out_path) != 0:
            failed = failed + 1
            free(line)
            continue
          base:str = path_basename_no_ext(in_path)
          if base == 0 || base[0] == 0:
            failed = failed + 1
            if base != 0:
              free(base)
            if in_path != 0:
              free(in_path)
            if out_path != 0:
              free(out_path)
            free(line)
            continue
          tmp_a:str = str_join2(out_dir, base)
          tmp_b:str = str_join2(tmp_a, "_conf_ast.tn")
          if io.copy_file(in_path, tmp_b) < 0:
            say "conformance ast copy failed:"
            say in_path
            failed = failed + 1
          else:
            cmd_af1:str = str_join3(tezzc, " fmt ", tmp_b)
            if run_quiet(cmd_af1) != 0:
              say "conformance ast fmt failed:"
              say in_path
              failed = failed + 1
            else:
              exp_af:str = read_norm(out_path)
              act_af:str = read_norm(tmp_b)
              if exp_af == 0 || act_af == 0 || strcmp(exp_af, act_af) != 0:
                say "conformance ast mismatch:"
                say in_path
                failed = failed + 1
              else:
                cmd_af2:str = str_join3(tezzc, " fmt ", tmp_b)
                if run_quiet(cmd_af2) != 0:
                  say "conformance ast roundtrip failed:"
                  say in_path
                  failed = failed + 1
                else:
                  act_af2:str = read_norm(tmp_b)
                  if act_af2 == 0 || strcmp(act_af, act_af2) != 0:
                    say "conformance ast non-deterministic:"
                    say in_path
                    failed = failed + 1
                  if act_af2 != 0:
                    free(act_af2)
                free(cmd_af2)
              if exp_af != 0:
                free(exp_af)
              if act_af != 0:
                free(act_af)
            free(cmd_af1)
          remove(tmp_b)
          free(tmp_a)
          free(tmp_b)
          free(base)
          if in_path != 0:
            free(in_path)
          if out_path != 0:
            free(out_path)
          free(line)
        free(conf_ast_list)

      // Deterministic IR snapshots (repro mode)
      conf_ir_list:str = io.read_all("tests/conformance_ir_manifest.tnx")
      if conf_ir_list == 0:
        say "missing tests/conformance_ir_manifest.tnx"
        failed = failed + 1
      else:
        idx = 0
        while 1:
          line:str = next_manifest_line(conf_ir_list, &idx)
          if line == 0:
            break
          in_path:str = 0 as str
          out_path:str = 0 as str
          if split_pair(line, &in_path, &out_path) != 0:
            failed = failed + 1
            free(line)
            continue
          base:str = path_basename_no_ext(in_path)
          if base == 0 || base[0] == 0:
            failed = failed + 1
            if base != 0:
              free(base)
            if in_path != 0:
              free(in_path)
            if out_path != 0:
              free(out_path)
            free(line)
            continue
          cmd_ir1:str = str_join3(tezzc, " ir ", in_path)
          cmd_ir2:str = str_join2(cmd_ir1, " --repro")
          tmp1a:str = str_join2(out_dir, base)
          tmp1b:str = str_join2(tmp1a, "_conf_ir_1.out")
          tmp2a:str = str_join2(out_dir, base)
          tmp2b:str = str_join2(tmp2a, "_conf_ir_2.out")
          r1:int = run_to_file(cmd_ir2, tmp1b)
          r2:int = run_to_file(cmd_ir2, tmp2b)
          exp_ir:str = read_norm(out_path)
          act_ir1t:str = 0 as str
          act_ir2t:str = 0 as str
          if r1 == 0:
            act_ir1t = read_norm(tmp1b)
          if r2 == 0:
            act_ir2t = read_norm(tmp2b)
          if exp_ir == 0 || act_ir1t == 0 || strcmp(exp_ir, act_ir1t) != 0:
            say "conformance ir mismatch:"
            say in_path
            failed = failed + 1
          if act_ir1t == 0 || act_ir2t == 0 || strcmp(act_ir1t, act_ir2t) != 0:
            say "conformance ir non-deterministic:"
            say in_path
            failed = failed + 1
          remove(tmp1b)
          remove(tmp2b)
          if cmd_ir1 != 0:
            free(cmd_ir1)
          if cmd_ir2 != 0:
            free(cmd_ir2)
          if tmp1a != 0:
            free(tmp1a)
          if tmp1b != 0:
            free(tmp1b)
          if tmp2a != 0:
            free(tmp2a)
          if tmp2b != 0:
            free(tmp2b)
          if act_ir1t != 0:
            free(act_ir1t)
          if act_ir2t != 0:
            free(act_ir2t)
          if exp_ir != 0:
            free(exp_ir)
          if base != 0:
            free(base)
          if in_path != 0:
            free(in_path)
          if out_path != 0:
            free(out_path)
          free(line)
        free(conf_ir_list)

      // Strict parser/type-edge diagnostics snapshots (opt-in)
      if conformance_strict != 0:
        conf_diag_list:str = io.read_all("tests/conformance_diag_manifest.tnx")
        if conf_diag_list == 0:
          say "missing tests/conformance_diag_manifest.tnx"
          failed = failed + 1
        else:
          idx = 0
          while 1:
            line:str = next_manifest_line(conf_diag_list, &idx)
            if line == 0:
              break
            in_path:str = 0 as str
            out_path:str = 0 as str
            if split_pair(line, &in_path, &out_path) != 0:
              failed = failed + 1
              free(line)
              continue
            cmd_d:str = str_join3(tezzc, " check ", in_path)
            rc_cmd:str = 0 as str
            if streq(os, "windows"):
              rc_cmd = str_join3("cmd /c \"", cmd_d, " > nul 2>&1\"")
            else:
              rc_cmd = str_join3("sh -c \"", cmd_d, " > /dev/null 2>&1\"")
            rc_d:int = proc_run(rc_cmd)
            free(rc_cmd)
            if rc_d == 0:
              say "conformance strict expected failure but succeeded:"
              say in_path
              failed = failed + 1
            else:
              cap_cmd_d:str = 0 as str
              if streq(os, "windows"):
                cap_cmd_d = str_join3("cmd /c \"(", cmd_d, ") 2>&1\"")
              else:
                cap_cmd_d = str_join3(cmd_d, " 2>&1 | cat", "")
              cap_path_d:str = str_join2("build/", "conformance_diag_capture.out")
              run_to_file(cap_cmd_d, cap_path_d)
              out_d:str = read_norm(cap_path_d)
              remove(cap_path_d)
              exp_d:str = read_norm(out_path)
              exp_d2:str = normalize_slashes(exp_d)
              act_d2:str = normalize_slashes(out_d)
              exp_d3:str = trim_trailing_ws(exp_d2)
              act_d3:str = trim_trailing_ws(act_d2)
              if exp_d3 == 0 || act_d3 == 0 || strcmp(exp_d3, act_d3) != 0:
                say "conformance strict diagnostics mismatch:"
                say in_path
                failed = failed + 1
              if cap_cmd_d != 0:
                free(cap_cmd_d)
              if cap_path_d != 0:
                free(cap_path_d)
              if out_d != 0:
                free(out_d)
              if exp_d != 0:
                free(exp_d)
              if exp_d2 != 0:
                free(exp_d2)
              if act_d2 != 0:
                free(act_d2)
              if exp_d3 != 0:
                free(exp_d3)
              if act_d3 != 0:
                free(act_d3)
            free(cmd_d)
            if in_path != 0:
              free(in_path)
            if out_path != 0:
              free(out_path)
            free(line)
          free(conf_diag_list)
    free(list)
    if failed != 0:
      ret 0 - 1
    if conformance != 0:
      say "CONFORMANCE TESTS PASSED"
    else:
      say "SMOKE TESTS PASSED"
    ret 0

  // Optional accelerator tests (gated)
  if accel != 0:
    acc_list:str = io.read_all("tests/accel_manifest.tnx")
    if acc_list == 0:
      say "missing tests/accel_manifest.tnx"
      failed = failed + 1
    else:
      idx = 0
      while 1:
        start:str = next_manifest_line(acc_list, &idx)
        if start == 0:
          break
        // prefer native path for accelerator coverage
        cmd_acc1:str = str_join3(tezzc, " run --native ", start)
        cmd_acc:str = str_join2(cmd_acc1, " -- --require")
        if test_run(cmd_acc, "accel run") != 0:
          failed = failed + 1
        free(cmd_acc1)
        free(cmd_acc)
        free(start)
      free(acc_list)

  // Optional accelerator ONNX tests (gated)
  if accel_onnx != 0:
    onnx_list:str = io.read_all("tests/accel_onnx_manifest.tnx")
    if onnx_list == 0:
      say "missing tests/accel_onnx_manifest.tnx"
      failed = failed + 1
    else:
      idx = 0
      while 1:
        start:str = next_manifest_line(onnx_list, &idx)
        if start == 0:
          break
        cmd_ox1:str = str_join3(tezzc, " run --native ", start)
        cmd_ox:str = str_join2(cmd_ox1, " -- --require-onnx")
        if test_run(cmd_ox, "accel onnx run") != 0:
          failed = failed + 1
        free(cmd_ox1)
        free(cmd_ox)
        free(start)
      free(onnx_list)

  // buildexe parity tests (VM vs EXE)
  be_target:str = "x86_64"
  if streq(os, "linux"):
    be_target = "linux"
  else if streq(os, "macos"):
    be_target = "macos"
  be_list:str = io.read_all("tests/buildexe_manifest.tnx")
  if be_list != 0:
    ensure_dir("build")
    idx = 0
    if parity != 0 && parity_debug != 0:
      say "parity: buildexe start"
    while 1:
      start:str = next_manifest_line(be_list, &idx)
      if start == 0:
        break
      base:str = path_basename_no_ext(start)
      cmd_vm:str = 0 as str
      out_vm:str = 0 as str
      out_vm_path:str = 0 as str
      if base != 0 && base[0] != 0:
        // VM output
        cmd_vm = str_join3(tezzc, " run --bc ", start)
        if parity == 0:
          if test_run(cmd_vm, "vm run") != 0:
            failed = failed + 1
        else:
          out_vm_path = str_join3(out_dir, base, "_vm.out")
          if run_to_file(cmd_vm, out_vm_path) != 0:
            say "test command failed:"
            say "vm run (capture)"
            say cmd_vm
            failed = failed + 1
          else:
            out_vm = read_norm(out_vm_path)
            if out_vm == 0:
              failed = failed + 1
          remove(out_vm_path)

        // build exe (x86_64, run on host)
        out1:str = str_join2(out_dir, base)
        out2:str = str_join2(out1, "_be")
        out3:str = str_join2(out2, exe_suffix)
        cmd_be1:str = str_join3(tezzc, " buildexe ", start)
        cmd_be2:str = str_join3(cmd_be1, " ", out3)
        cmd_be3a:str = str_join3(cmd_be2, " --target ", be_target)
        cmd_be3:str = str_join2(cmd_be3a, " --verify")
        if test_run(cmd_be3, "buildexe host verify") != 0:
          failed = failed + 1
        else:
          if parity == 0:
            if test_run(out3, "run exe host") != 0:
              failed = failed + 1
          else:
            out_exe_path:str = str_join3(out_dir, base, "_exe.out")
            out_exe:str = 0 as str
            if run_to_file(out3, out_exe_path) != 0:
              say "test command failed:"
              say "run exe host (capture)"
              say out3
              failed = failed + 1
            else:
              out_exe = read_norm(out_exe_path)
              if out_exe == 0:
                failed = failed + 1
              else:
                if out_vm != 0 && strcmp(out_vm, out_exe) != 0:
                  say "buildexe mismatch: "
                  say start
                  failed = failed + 1
                free(out_exe)
            remove(out_exe_path)
            free(out_exe_path)

        free(out1)
        free(out2)
        free(out3)
        free(cmd_be1)
        free(cmd_be2)
        free(cmd_be3a)
        free(cmd_be3)

        // Windows-only: also validate arm64/x86 emitters (verify only)
        if streq(os, "windows"):
          out_w1:str = str_join2(out_dir, base)
          out_w2:str = str_join2(out_w1, "_be_arm64")
          out_w3:str = str_join2(out_w2, exe_suffix)
          cmd_w1:str = str_join3(tezzc, " buildexe ", start)
          cmd_w2:str = str_join3(cmd_w1, " ", out_w3)
          cmd_w3:str = str_join2(cmd_w2, " --target arm64 --verify")
          if test_run(cmd_w3, "buildexe arm64 verify") != 0:
            failed = failed + 1
          free(out_w1)
          free(out_w2)
          free(out_w3)
          free(cmd_w1)
          free(cmd_w2)
          free(cmd_w3)

          out_x1:str = str_join2(out_dir, base)
          out_x2:str = str_join2(out_x1, "_be_x86")
          out_x3:str = str_join2(out_x2, exe_suffix)
          cmd_x1:str = str_join3(tezzc, " buildexe ", start)
          cmd_x2:str = str_join3(cmd_x1, " ", out_x3)
          cmd_x3:str = str_join2(cmd_x2, " --target x86 --verify")
          if test_run(cmd_x3, "buildexe x86 verify") != 0:
            failed = failed + 1
          else:
            if parity == 0:
              if test_run(out_x3, "run exe x86") != 0:
                failed = failed + 1
            else:
              out_x86_path:str = str_join3(out_dir, base, "_x86.out")
              out_x86:str = 0 as str
              if run_to_file(out_x3, out_x86_path) != 0:
                say "test command failed:"
                say "run exe x86 (capture)"
                say out_x3
                failed = failed + 1
              else:
                out_x86 = read_norm(out_x86_path)
                if out_x86 == 0:
                  failed = failed + 1
                else:
                  if out_vm != 0 && strcmp(out_vm, out_x86) != 0:
                    say "buildexe mismatch (x86): "
                    say start
                    failed = failed + 1
                  free(out_x86)
              remove(out_x86_path)
              free(out_x86_path)
          free(out_x1)
          free(out_x2)
          free(out_x3)
          free(cmd_x1)
          free(cmd_x2)
          free(cmd_x3)
      else:
        failed = failed + 1

      if out_vm != 0:
        free(out_vm)
      if cmd_vm != 0:
        free(cmd_vm)
      if out_vm_path != 0:
        free(out_vm_path)
      if base != 0:
        free(base)
      free(start)
    free(be_list)
    if parity != 0 && parity_debug != 0:
      say "parity: buildexe done"

  // buildexe verify-only tests (x86 on Windows)
  if streq(os, "windows"):
    be_x86_list:str = io.read_all("tests/buildexe_x86_manifest.tnx")
    if be_x86_list != 0:
      ensure_dir("build")
      idx = 0
      while 1:
        start:str = next_manifest_line(be_x86_list, &idx)
        if start == 0:
          break
        base:str = path_basename_no_ext(start)
        if base != 0 && base[0] != 0:
          out1:str = str_join2(out_dir, base)
          out2:str = str_join2(out1, "_be_x86")
          out3:str = str_join2(out2, exe_suffix)
          cmd_be1:str = str_join3(tezzc, " buildexe ", start)
          cmd_be2:str = str_join3(cmd_be1, " ", out3)
          cmd_be3:str = str_join2(cmd_be2, " --target x86 --verify")
          if test_run(cmd_be3, "buildexe x86 verify") != 0:
            failed = failed + 1
          free(out1)
          free(out2)
          free(out3)
          free(cmd_be1)
          free(cmd_be2)
          free(cmd_be3)
        else:
          failed = failed + 1

        if base != 0:
          free(base)
        free(start)
    free(be_x86_list)
    if parity != 0 && parity_debug != 0:
      say "parity: x86 buildexe done"

  // Module system negative tests (lock/dep enforcement)
  if parity == 0:
    // missing dep in tezz.mod
    cmd_md:str = str_join3(tezzc, " check ", "tests/module_missing_dep.tn")
    if expect_fail(cmd_md, "missing dep") != 0:
      failed = failed + 1
    free(cmd_md)

    // versioned import on path not allowed
    cmd_mv:str = str_join3(tezzc, " check ", "tests/module_path_ver_fail.tn")
    if expect_fail(cmd_mv, "versioned import not allowed") != 0:
      failed = failed + 1
    free(cmd_mv)

    // missing lock entry for a pinned dep
    lock_orig:str = io.read_all("tezz.lock")
    if lock_orig != 0:
      lock_tmp:str = lock_strip_dep(lock_orig, "io")
      if lock_tmp != 0:
        io.write_all("tezz.lock", lock_tmp)
        cmd_ml:str = str_join3(tezzc, " check ", "tests/module_lock_missing_in_lock.tn")
        if expect_fail(cmd_ml, "missing io@") != 0:
          failed = failed + 1
        free(cmd_ml)
        free(lock_tmp)
      io.write_all("tezz.lock", lock_orig)
      free(lock_orig)

  // ELF verify tests (cross-target, no run)
  if streq(os, "linux") != 0 || cross != 0:
    elf_list:str = io.read_all("tests/buildexe_elf_manifest.tnx")
    if elf_list != 0:
      ensure_dir("build")
      idx = 0
      while 1:
        start:str = next_manifest_line(elf_list, &idx)
        if start == 0:
          break
        base:str = path_basename_no_ext(start)
        if base != 0 && base[0] != 0:
          out1:str = str_join2(out_dir, base)
          out2:str = str_join2(out1, "_be_elf")
          cmd1:str = str_join3(tezzc, " buildexe ", start)
          cmd2:str = str_join3(cmd1, " ", out2)
          cmd3:str = str_join2(cmd2, " --target linux --verify")
          if test_run(cmd3, "buildexe elf verify") != 0:
            failed = failed + 1
          free(out1)
          free(out2)
          free(cmd1)
          free(cmd2)
          free(cmd3)
        else:
          failed = failed + 1
        if base != 0:
          free(base)
        free(start)
      free(elf_list)

  // Mach-O verify tests (cross-target, no run)
  if streq(os, "macos") != 0 || cross != 0:
    macho_list:str = io.read_all("tests/buildexe_macho_manifest.tnx")
    if macho_list != 0:
      ensure_dir("build")
      idx = 0
      while 1:
        start:str = next_manifest_line(macho_list, &idx)
        if start == 0:
          break
        base:str = path_basename_no_ext(start)
        if base != 0 && base[0] != 0:
          out1:str = str_join2(out_dir, base)
          out2:str = str_join2(out1, "_be_macho")
          cmd1:str = str_join3(tezzc, " buildexe ", start)
          cmd2:str = str_join3(cmd1, " ", out2)
          cmd3:str = str_join2(cmd2, " --target macos --verify")
          if test_run(cmd3, "buildexe macho verify") != 0:
            failed = failed + 1
          free(out1)
          free(out2)
          free(cmd1)
          free(cmd2)
          free(cmd3)
        else:
          failed = failed + 1
        if base != 0:
          free(base)
        free(start)
      free(macho_list)

  // Linux arm64 run tests via WSL + QEMU (optional)
  if streq(os, "windows") && cross != 0:
    arm_list:str = io.read_all("tests/buildexe_arm64_manifest.tnx")
    if arm_list != 0:
      qemu_ok:int = 0
      qout:str = proc_out("wsl -e sh -lc \"command -v qemu-aarch64\"")
      if qout != 0:
        qout = trim_line(qout)
        if qout[0] != 0:
          qemu_ok = 1
      if qout != 0:
        free(qout)
      if qemu_ok == 0:
        say "arm64 parity skipped: qemu-aarch64 not found"
        free(arm_list)
      else:
        ensure_dir("build")
        idx = 0
        while 1:
          start:str = next_manifest_line(arm_list, &idx)
          if start == 0:
            break
          base:str = path_basename_no_ext(start)
          if base == 0 || base[0] == 0:
            failed = failed + 1
            if base != 0:
              free(base)
            free(start)
            continue
          // VM output
          cmd_vm:str = str_join3(tezzc, " run --bc ", start)
          out_vm_path:str = 0 as str
          out_vm:str = 0 as str
          if parity == 0:
            if test_run(cmd_vm, "vm run") != 0:
              failed = failed + 1
          else:
            out_vm_path = str_join3(out_dir, base, "_vm.out")
            if run_to_file(cmd_vm, out_vm_path) != 0:
              say "test command failed:"
              say "vm run (capture)"
              say cmd_vm
              failed = failed + 1
            else:
              out_vm = read_norm(out_vm_path)
              if out_vm == 0:
                failed = failed + 1
            remove(out_vm_path)
            free(out_vm_path)
          free(cmd_vm)

          // build arm64 ELF
          out1:str = str_join2(out_dir, base)
          out2:str = str_join2(out1, "_be_arm64_elf")
          cmd1:str = str_join3(tezzc, " buildexe ", start)
          cmd2:str = str_join3(cmd1, " ", out2)
          cmd3:str = str_join2(cmd2, " --target linux-arm64 --verify")
          if test_run(cmd3, "buildexe linux-arm64 verify") != 0:
            failed = failed + 1
          else:
            wslp:str = wsl_path(out2)
            if wslp == 0:
              failed = failed + 1
            else:
              // run under qemu-aarch64 (copy to /tmp to avoid DrvFs exec issues)
              cmdr3:str = str_join3("wsl -e sh -lc \"cp ", wslp, " /tmp/tezz_arm64_tmp && chmod +x /tmp/tezz_arm64_tmp && qemu-aarch64 /tmp/tezz_arm64_tmp; rm -f /tmp/tezz_arm64_tmp\"")
              if parity == 0:
                if test_run(cmdr3, "run exe arm64") != 0:
                  failed = failed + 1
              else:
                out_arm_path:str = str_join3(out_dir, base, "_arm64.out")
                out_arm:str = 0 as str
                if run_to_file(cmdr3, out_arm_path) != 0:
                  say "test command failed:"
                  say "run exe arm64 (capture)"
                  say cmdr3
                  failed = failed + 1
                else:
                  out_arm = read_norm(out_arm_path)
                  if out_arm == 0:
                    failed = failed + 1
                  else:
                    if out_vm != 0 && strcmp(out_vm, out_arm) != 0:
                      say "buildexe mismatch (arm64): "
                      say start
                      failed = failed + 1
                    free(out_arm)
                remove(out_arm_path)
                free(out_arm_path)
              free(cmdr3)
              free(wslp)
          free(out1)
          free(out2)
          free(cmd1)
          free(cmd2)
          free(cmd3)
          if out_vm != 0:
            free(out_vm)
          free(base)
          free(start)
        free(arm_list)

  // Windows ARM64 host-run (optional, requires ARM64 host)
  if streq(os, "windows") && host_win_arm64 != 0:
    arm_list2:str = io.read_all("tests/buildexe_arm64_manifest.tnx")
    if arm_list2 != 0:
      ensure_dir("build")
      idx = 0
      while 1:
        start:str = next_manifest_line(arm_list2, &idx)
        if start == 0:
          break
        base:str = path_basename_no_ext(start)
        if base == 0 || base[0] == 0:
          failed = failed + 1
          if base != 0:
            free(base)
          free(start)
          continue
        // VM output
        cmd_vm:str = str_join3(tezzc, " run --bc ", start)
        out_vm_path:str = 0 as str
        out_vm:str = 0 as str
        if parity == 0:
          if test_run(cmd_vm, "vm run") != 0:
            failed = failed + 1
        else:
          out_vm_path = str_join3(out_dir, base, "_vm.out")
          if run_to_file(cmd_vm, out_vm_path) != 0:
            say "test command failed:"
            say "vm run (capture)"
            say cmd_vm
            failed = failed + 1
          else:
            out_vm = read_norm(out_vm_path)
            if out_vm == 0:
              failed = failed + 1
          remove(out_vm_path)
          free(out_vm_path)
        free(cmd_vm)

        // build arm64 PE and run on host
        out1:str = str_join2(out_dir, base)
        out2:str = str_join2(out1, "_be_arm64")
        out3:str = str_join2(out2, exe_suffix)
        cmd1:str = str_join3(tezzc, " buildexe ", start)
        cmd2:str = str_join3(cmd1, " ", out3)
        cmd3:str = str_join2(cmd2, " --target arm64 --verify")
        if test_run(cmd3, "buildexe arm64 verify") != 0:
          failed = failed + 1
        else:
          if parity == 0:
            if test_run(out3, "run exe arm64") != 0:
              failed = failed + 1
          else:
            out_arm_path:str = str_join3(out_dir, base, "_arm64.out")
            out_arm:str = 0 as str
            if run_to_file(out3, out_arm_path) != 0:
              say "test command failed:"
              say "run exe arm64 (capture)"
              say out3
              failed = failed + 1
            else:
              out_arm = read_norm(out_arm_path)
              if out_arm == 0:
                failed = failed + 1
              else:
                if out_vm != 0 && strcmp(out_vm, out_arm) != 0:
                  say "buildexe mismatch (arm64 host): "
                  say start
                  failed = failed + 1
                free(out_arm)
            remove(out_arm_path)
            free(out_arm_path)
        free(out1)
        free(out2)
        free(out3)
        free(cmd1)
        free(cmd2)
        free(cmd3)
        if out_vm != 0:
          free(out_vm)
        free(base)
        free(start)
      free(arm_list2)

  // Linux ARM64 host-run (optional, requires ARM64 Linux host)
  if streq(os, "linux") && host_linux_arm64 != 0:
    arm_list3:str = io.read_all("tests/buildexe_arm64_manifest.tnx")
    if arm_list3 != 0:
      ensure_dir("build")
      idx = 0
      while 1:
        start:str = next_manifest_line(arm_list3, &idx)
        if start == 0:
          break
        base:str = path_basename_no_ext(start)
        if base == 0 || base[0] == 0:
          failed = failed + 1
          if base != 0:
            free(base)
          free(start)
          continue
        // VM output
        cmd_vm:str = str_join3(tezzc, " run --bc ", start)
        out_vm_path:str = 0 as str
        out_vm:str = 0 as str
        if parity == 0:
          if test_run(cmd_vm, "vm run") != 0:
            failed = failed + 1
        else:
          out_vm_path = str_join3(out_dir, base, "_vm.out")
          if run_to_file(cmd_vm, out_vm_path) != 0:
            say "test command failed:"
            say "vm run (capture)"
            say cmd_vm
            failed = failed + 1
          else:
            out_vm = read_norm(out_vm_path)
            if out_vm == 0:
              failed = failed + 1
          remove(out_vm_path)
          free(out_vm_path)
        free(cmd_vm)

        // build arm64 ELF and run on host
        out1:str = str_join2(out_dir, base)
        out2:str = str_join2(out1, "_be_arm64_elf")
        cmd1:str = str_join3(tezzc, " buildexe ", start)
        cmd2:str = str_join3(cmd1, " ", out2)
        cmd3:str = str_join2(cmd2, " --target linux-arm64 --verify")
        if test_run(cmd3, "buildexe linux-arm64 verify") != 0:
          failed = failed + 1
        else:
          if parity == 0:
            if test_run(out2, "run exe arm64") != 0:
              failed = failed + 1
          else:
            out_arm_path:str = str_join3(out_dir, base, "_arm64.out")
            out_arm:str = 0 as str
            if run_to_file(out2, out_arm_path) != 0:
              say "test command failed:"
              say "run exe arm64 (capture)"
              say out2
              failed = failed + 1
            else:
              out_arm = read_norm(out_arm_path)
              if out_arm == 0:
                failed = failed + 1
              else:
                if out_vm != 0 && strcmp(out_vm, out_arm) != 0:
                  say "buildexe mismatch (arm64 host): "
                  say start
                  failed = failed + 1
                free(out_arm)
            remove(out_arm_path)
            free(out_arm_path)
        free(out1)
        free(out2)
        free(cmd1)
        free(cmd2)
        free(cmd3)
        if out_vm != 0:
          free(out_vm)
        free(base)
        free(start)
      free(arm_list3)

  // macOS host-run for Mach-O tests (optional)
  if streq(os, "macos") && host_macos != 0:
    macho_list2:str = io.read_all("tests/buildexe_macho_manifest.tnx")
    if macho_list2 != 0:
      ensure_dir("build")
      idx = 0
      while 1:
        start:str = next_manifest_line(macho_list2, &idx)
        if start == 0:
          break
        base:str = path_basename_no_ext(start)
        if base == 0 || base[0] == 0:
          failed = failed + 1
          if base != 0:
            free(base)
          free(start)
          continue
        cmd_vm:str = str_join3(tezzc, " run --bc ", start)
        out_vm_path:str = 0 as str
        out_vm:str = 0 as str
        if parity == 0:
          if test_run(cmd_vm, "vm run") != 0:
            failed = failed + 1
        else:
          out_vm_path = str_join3(out_dir, base, "_vm.out")
          if run_to_file(cmd_vm, out_vm_path) != 0:
            say "test command failed:"
            say "vm run (capture)"
            say cmd_vm
            failed = failed + 1
          else:
            out_vm = read_norm(out_vm_path)
            if out_vm == 0:
              failed = failed + 1
          remove(out_vm_path)
          free(out_vm_path)
        free(cmd_vm)

        out1:str = str_join2(out_dir, base)
        out2:str = str_join2(out1, "_be_macho")
        cmd1:str = str_join3(tezzc, " buildexe ", start)
        cmd2:str = str_join3(cmd1, " ", out2)
        cmd3:str = str_join2(cmd2, " --target macos --verify")
        if test_run(cmd3, "buildexe macho verify") != 0:
          failed = failed + 1
        else:
          if parity == 0:
            if test_run(out2, "run exe macho") != 0:
              failed = failed + 1
          else:
            out_m_path:str = str_join3(out_dir, base, "_macho.out")
            out_m:str = 0 as str
            if run_to_file(out2, out_m_path) != 0:
              say "test command failed:"
              say "run exe macho (capture)"
              say out2
              failed = failed + 1
            else:
              out_m = read_norm(out_m_path)
              if out_m == 0:
                failed = failed + 1
              else:
                if out_vm != 0 && strcmp(out_vm, out_m) != 0:
                  say "buildexe mismatch (macho host): "
                  say start
                  failed = failed + 1
                free(out_m)
            remove(out_m_path)
            free(out_m_path)
        free(out1)
        free(out2)
        free(cmd1)
        free(cmd2)
        free(cmd3)
        if out_vm != 0:
          free(out_vm)
        free(base)
        free(start)
      free(macho_list2)

  // Formatter golden tests (fmt -> parse -> fmt stable)
  fmt_list:str = io.read_all("tests/fmt_manifest.tnx")
  if fmt_list != 0:
    ensure_dir("build")
    idx = 0
    while 1:
      line:str = next_manifest_line(fmt_list, &idx)
      if line == 0:
        break
      in_path:str = 0 as str
      out_path:str = 0 as str
      if split_pair(line, &in_path, &out_path) != 0:
        failed = failed + 1
        free(line)
        continue
      base:str = path_basename_no_ext(in_path)
      if base == 0 || base[0] == 0:
        failed = failed + 1
        if base != 0:
          free(base)
        free(in_path)
        free(out_path)
        free(line)
        continue
      tmp1a:str = str_join2(out_dir, base)
      tmp1b:str = str_join2(tmp1a, "_fmt1.tn")
      cmd1:str = str_join3(tezzc, " fmt ", tmp1b)
      if io.copy_file(in_path, tmp1b) < 0:
        say "fmt failed:"
        say in_path
        failed = failed + 1
      else:
        exp:str = 0 as str
        act1:str = 0 as str
        if run_quiet(cmd1) != 0:
          say "fmt failed:"
          say in_path
          failed = failed + 1
        else:
          exp = read_norm(out_path)
          act1 = read_norm(tmp1b)
        if exp == 0 || act1 == 0 || strcmp(exp, act1) != 0:
          say "fmt mismatch:"
          say in_path
          failed = failed + 1
          if act1 != 0:
            free(act1)
          if exp != 0:
            free(exp)
        else:
          cmd2:str = str_join3(tezzc, " fmt ", tmp1b)
          if run_quiet(cmd2) != 0:
            say "fmt roundtrip failed:"
            say in_path
            failed = failed + 1
          else:
            act2:str = read_norm(tmp1b)
            if act2 == 0 || strcmp(act1, act2) != 0:
              say "fmt roundtrip mismatch:"
              say in_path
              failed = failed + 1
            if act2 != 0:
              free(act2)
          free(cmd2)
          if act1 != 0:
            free(act1)
          if exp != 0:
            free(exp)
        remove(tmp1b)
      free(cmd1)
      free(tmp1a)
      free(tmp1b)
      free(base)
      free(in_path)
      free(out_path)
      free(line)
    free(fmt_list)

  // Lint diagnostics golden tests
  lint_list:str = io.read_all("tests/lint_manifest.tnx")
  if lint_list != 0:
    idx = 0
    while 1:
      line:str = next_manifest_line(lint_list, &idx)
      if line == 0:
        break
      in_path:str = 0 as str
      out_path:str = 0 as str
      if split_pair(line, &in_path, &out_path) != 0:
        failed = failed + 1
        free(line)
        continue
      cmdl:str = str_join3(tezzc, " lint ", in_path)
      outl:str = proc_out_all(cmdl)
      exp:str = read_norm(out_path)
      act:str = normalize_out(outl)
      exp2:str = normalize_slashes(exp)
      act2:str = normalize_slashes(act)
      exp3:str = trim_trailing_ws(exp2)
      act3:str = trim_trailing_ws(act2)
      if exp3 == 0 || act3 == 0 || strcmp(exp3, act3) != 0:
        say "lint mismatch:"
        say in_path
        failed = failed + 1
      if cmdl != 0:
        free(cmdl)
      if outl != 0:
        free(outl)
      if exp3 != 0:
        free(exp3)
      if act3 != 0:
        free(act3)
      if exp2 != 0:
        free(exp2)
      if act2 != 0:
        free(act2)
      if exp != 0:
        free(exp)
      if act != 0:
        free(act)
      if in_path != 0:
        free(in_path)
      if out_path != 0:
        free(out_path)
      free(line)
    free(lint_list)

  // Borrow/ownership diagnostics golden tests (negative fixtures)
  borrow_list:str = io.read_all("tests/borrow_manifest.tnx")
  if borrow_list != 0:
    idx = 0
    while 1:
      line:str = next_manifest_line(borrow_list, &idx)
      if line == 0:
        break
      in_path:str = 0 as str
      out_path:str = 0 as str
      if split_pair(line, &in_path, &out_path) != 0:
        failed = failed + 1
        free(line)
        continue
      cmd_b:str = str_join3(tezzc, " check ", in_path)
      if run_quiet_all(cmd_b) == 0:
        say "borrow check unexpectedly succeeded:"
        say in_path
        failed = failed + 1
      out_b:str = proc_out_all(cmd_b)
      exp_b:str = read_norm(out_path)
      act_b:str = normalize_out(out_b)
      exp_b2:str = normalize_slashes(exp_b)
      act_b2:str = normalize_slashes(act_b)
      exp_b3:str = trim_trailing_ws(exp_b2)
      act_b3:str = trim_trailing_ws(act_b2)
      if exp_b3 == 0 || act_b3 == 0 || strcmp(exp_b3, act_b3) != 0:
        say "borrow mismatch:"
        say in_path
        failed = failed + 1
      if cmd_b != 0:
        free(cmd_b)
      if out_b != 0:
        free(out_b)
      if exp_b3 != 0:
        free(exp_b3)
      if act_b3 != 0:
        free(act_b3)
      if exp_b2 != 0:
        free(exp_b2)
      if act_b2 != 0:
        free(act_b2)
      if exp_b != 0:
        free(exp_b)
      if act_b != 0:
        free(act_b)
      if in_path != 0:
        free(in_path)
      if out_path != 0:
        free(out_path)
      free(line)
    free(borrow_list)

  // Attribute diagnostics golden tests (negative fixtures)
  attr_list:str = io.read_all("tests/attr_manifest.tnx")
  if attr_list != 0:
    idx = 0
    while 1:
      line:str = next_manifest_line(attr_list, &idx)
      if line == 0:
        break
      in_path:str = 0 as str
      out_path:str = 0 as str
      if split_pair(line, &in_path, &out_path) != 0:
        failed = failed + 1
        free(line)
        continue
      cmd_a:str = str_join3(tezzc, " check ", in_path)
      if run_quiet_all(cmd_a) == 0:
        say "attr check unexpectedly succeeded:"
        say in_path
        failed = failed + 1
      out_a:str = proc_out_all(cmd_a)
      exp_a:str = read_norm(out_path)
      act_a:str = normalize_out(out_a)
      exp_a2:str = normalize_slashes(exp_a)
      act_a2:str = normalize_slashes(act_a)
      exp_a3:str = trim_trailing_ws(exp_a2)
      act_a3:str = trim_trailing_ws(act_a2)
      if exp_a3 == 0 || act_a3 == 0 || strcmp(exp_a3, act_a3) != 0:
        say "attr mismatch:"
        say in_path
        failed = failed + 1
      if cmd_a != 0:
        free(cmd_a)
      if out_a != 0:
        free(out_a)
      if exp_a3 != 0:
        free(exp_a3)
      if act_a3 != 0:
        free(act_a3)
      if exp_a2 != 0:
        free(exp_a2)
      if act_a2 != 0:
        free(act_a2)
      if exp_a != 0:
        free(exp_a)
      if act_a != 0:
        free(act_a)
      if in_path != 0:
        free(in_path)
      if out_path != 0:
        free(out_path)
      free(line)
    free(attr_list)

  // ABI/FFI golden tests (abidump + abiverify)
  abi_list:str = io.read_all("tests/abi_manifest.tnx")
  if abi_list != 0:
    ensure_dir("build")
    idx = 0
    while 1:
      line:str = next_manifest_line(abi_list, &idx)
      if line == 0:
        break
      in_path:str = 0 as str
      out_path:str = 0 as str
      if split_pair(line, &in_path, &out_path) != 0:
        failed = failed + 1
        free(line)
        continue
      tmp_out:str = str_join2(out_dir, "abi_tmp.tnx")
      cmd_ab1:str = str_join3(tezzc, " abidump ", in_path)
      cmd_ab2a:str = str_join3(cmd_ab1, " ", tmp_out)
      cmd_ab2:str = str_join2(cmd_ab2a, " --freestanding")
      if test_run(cmd_ab2, "abidump") != 0:
        failed = failed + 1
      else:
        exp_a:str = read_norm(out_path)
        act_a:str = read_norm(tmp_out)
        if exp_a == 0 || act_a == 0 || strcmp(exp_a, act_a) != 0:
          say "abidump mismatch:"
          say in_path
          failed = failed + 1
        if exp_a != 0:
          free(exp_a)
        if act_a != 0:
          free(act_a)
      remove(tmp_out)

      cmd_av1:str = str_join3(tezzc, " abiverify ", in_path)
      cmd_av2a:str = str_join3(cmd_av1, " ", out_path)
      cmd_av2:str = str_join2(cmd_av2a, " --freestanding")
      if test_run(cmd_av2, "abiverify") != 0:
        failed = failed + 1
      free(cmd_ab1)
      free(cmd_ab2a)
      free(cmd_ab2)
      free(cmd_av1)
      free(cmd_av2a)
      free(cmd_av2)
      free(tmp_out)
      if in_path != 0:
        free(in_path)
      if out_path != 0:
        free(out_path)
      free(line)
    free(abi_list)

  // IR golden tests (optimizer pipeline snapshots)
  ir_list:str = io.read_all("tests/ir_manifest.tnx")
  if ir_list != 0:
    idx = 0
    while 1:
      line:str = next_manifest_line(ir_list, &idx)
      if line == 0:
        break
      in_path:str = 0 as str
      out_path:str = 0 as str
      if split_pair(line, &in_path, &out_path) != 0:
        failed = failed + 1
        free(line)
        continue
      cmd_ir:str = str_join3(tezzc, " ir ", in_path)
      out_ir:str = proc_out_all(cmd_ir)
      exp_ir:str = read_norm(out_path)
      act_ir:str = normalize_out(out_ir)
      exp_ir2:str = trim_trailing_ws(exp_ir)
      act_ir2:str = trim_trailing_ws(act_ir)
      if exp_ir2 == 0 || act_ir2 == 0 || strcmp(exp_ir2, act_ir2) != 0:
        say "ir mismatch:"
        say in_path
        failed = failed + 1
      if cmd_ir != 0:
        free(cmd_ir)
      if out_ir != 0:
        free(out_ir)
      if exp_ir2 != 0:
        free(exp_ir2)
      if act_ir2 != 0:
        free(act_ir2)
      if exp_ir != 0:
        free(exp_ir)
      if act_ir != 0:
        free(act_ir)
      if in_path != 0:
        free(in_path)
      if out_path != 0:
        free(out_path)
      free(line)
    free(ir_list)

  // Runtime error-path golden tests (separate manifest group)
  err_list:str = io.read_all("tests/error_manifest.tnx")
  if err_list != 0:
    ensure_dir("build")
    idx = 0
    while 1:
      line:str = next_manifest_line(err_list, &idx)
      if line == 0:
        break
      in_path:str = 0 as str
      out_path:str = 0 as str
      if split_pair(line, &in_path, &out_path) != 0:
        failed = failed + 1
        free(line)
        continue
      base:str = path_basename_no_ext(in_path)
      if base == 0 || base[0] == 0:
        failed = failed + 1
        if base != 0:
          free(base)
        free(in_path)
        free(out_path)
        free(line)
        continue
      tmp1a:str = str_join2(out_dir, base)
      tmp1b:str = str_join2(tmp1a, "_err.out")
      cmd1:str = str_join3(tezzc, " run --bc ", in_path)
      if run_to_file(cmd1, tmp1b) != 0:
        say "error-path failed:"
        say in_path
        failed = failed + 1
      else:
        exp:str = read_norm(out_path)
        act:str = read_norm(tmp1b)
        if exp == 0 || act == 0 || strcmp(exp, act) != 0:
          say "error-path mismatch:"
          say in_path
          failed = failed + 1
        if exp != 0:
          free(exp)
        if act != 0:
          free(act)
      remove(tmp1b)
      free(cmd1)
      free(tmp1a)
      free(tmp1b)
      free(base)
      free(in_path)
      free(out_path)
      free(line)
    free(err_list)

  // Kernel perf report baseline (optional)
  if kernel_perf != 0 && path_exists("kernel_perf_report.tnx") != 0:
    cmd_kp:str = str_join2(tezzc, " run --bc bench/kernel_perf.tn")
    out_kp:str = proc_out(cmd_kp)
    if out_kp == 0:
      say "kernel perf failed"
      failed = failed + 1
    else:
      out_kp = normalize_out(out_kp)
      out_kp = trim_line(out_kp)
      idxp:int = 0
      hdr:str = next_manifest_line(out_kp, &idxp)
      if hdr != 0:
        free(hdr)
      report:str = str_join2("", "op,policy,ns\n")
      while 1:
        opnm:str = next_manifest_line(out_kp, &idxp)
        if opnm == 0:
          break
        pol:str = next_manifest_line(out_kp, &idxp)
        nsstr:str = next_manifest_line(out_kp, &idxp)
        if pol == 0 || nsstr == 0:
          if pol != 0:
            free(pol)
          if nsstr != 0:
            free(nsstr)
          free(opnm)
          failed = failed + 1
          break
        nsval:int = parse_i64(nsstr)
        if nsval <= 0:
          failed = failed + 1
        line1:str = str_join3(opnm, ",", pol)
        line2:str = str_join3(line1, ",", nsstr)
        line3:str = str_join2(line2, "\n")
        tmprep:str = str_join2(report, line3)
        free(report)
        report = tmprep
        free(line1)
        free(line2)
        free(line3)
        free(opnm)
        free(pol)
        free(nsstr)
      io.write_all("build/kernel_perf_report.tnx", report)
      key:str = csv_op_policy(report)
      free(report)

      base:str = read_norm("kernel_perf_report.tnx")
      if base == 0:
        failed = failed + 1
      else:
        keyb:str = csv_op_policy(base)
        if keyb == 0 || key == 0 || strcmp(keyb, key) != 0:
          say "kernel perf baseline mismatch (op/policy)"
          failed = failed + 1
        free(base)
        if keyb != 0:
          free(keyb)
      if key != 0:
        free(key)
      free(out_kp)
    free(cmd_kp)

  // Freestanding kernel examples (build-only validation)
  os_list:str = io.read_all("tests/os_freestanding_manifest.tnx")
  if os_list != 0:
    ensure_dir("build")
    idx = 0
    while 1:
      start:str = next_manifest_line(os_list, &idx)
      if start == 0:
        break
      base:str = path_basename_no_ext(start)
      if base == 0 || base[0] == 0:
        failed = failed + 1
        if base != 0:
          free(base)
        free(start)
        continue
      outk1:str = str_join2(out_dir, base)
      outk2:str = str_join2(outk1, "_fs.s")
      cmdk1:str = str_join3(tezzc, " buildir ", start)
      cmdk2:str = str_join3(cmdk1, " ", outk2)
      cmdk3:str = str_join2(cmdk2, " --freestanding")
      if test_run(cmdk3, "freestanding build") != 0:
        failed = failed + 1
      remove(outk2)
      free(outk1)
      free(outk2)
      free(cmdk1)
      free(cmdk2)
      free(cmdk3)
      free(base)
      free(start)
    free(os_list)

  // GUI lane coverage (headless-safe host checks + retained tree behavior).
  if parity == 0:
    failed = failed + run_vm_manifest_once("tests/gui_manifest.tnx", tezzc, "gui")
    failed = failed + run_check_manifest("tests/gui_check_manifest.tnx", tezzc, "gui check", "")

  // BC parity tests (opt-in; use --parity)
  if parity != 0:
    if parity_debug != 0:
      say "parity: bcvm start"
    failed = failed + run_parity_manifest("tests/bcvm_manifest.tnx", "--bc", "bcvm", tezzc)
    if parity_debug != 0:
      say "parity: bcvm done"

  // Module/lock enforcement (negative test)
  if path_exists("tests/module_lock_bad_ver.tn") != 0:
    cmd_fail:str = str_join3(tezzc, " check ", "tests/module_lock_bad_ver.tn")
    if expect_fail(cmd_fail, "version mismatch") != 0:
      failed = failed + 1
    free(cmd_fail)

  // Duplicate/ambiguous module name detection (negative test)
  if path_exists("tests/module_dupname_fail.tn") != 0:
    cmd_dup:str = str_join3(tezzc, " check ", "tests/module_dupname_fail.tn")
    if expect_fail(cmd_dup, "ambiguous module name") != 0:
      failed = failed + 1
    free(cmd_dup)

  free(list)

  if failed != 0:
    ret 0 - 1
  say "ALL TESTS PASSED"
  ret 0

fn cmd_bench() -> int:
  list:str = io.read_all("bench/manifest.tnx")
  if list == 0:
    say "missing bench/manifest.tnx"
    ret 0 - 1
  micro:str = io.read_all("bench/micro_manifest.tnx")
  if micro != 0:
    tmpm:str = str_join3(list, "\n", micro)
    free(list)
    list = tmpm
    free(micro)

  tezzc:str = tezzc_path()
  os:str = os_name()
  exe_suffix:str = ""
  out_dir:str = "build/"
  if streq(os, "windows"):
    exe_suffix = ".exe"
    out_dir = ".\\build\\"

  run_bc:int = 0
  run_native:int = 0
  vectorize:int = 1
  profile:int = 0
  tune:int = 0
  profile_runs:int = 5
  kernel_perf:int = 0
  gate:int = 0
  perf_max_pct:int = 100
  baseline_path:str = "bench/perf_baseline.tnx"
  target:str = "x86_64"
  if streq(os, "windows") == 0:
    target = "linux"

  any_mode:int = 0
  ai:int = 1
  while ai < args_count():
    a:str = arg(ai)
    if streq(a, "--bc"):
      run_bc = 1
      any_mode = 1
      ai = ai + 1
      continue
    if streq(a, "--native"):
      run_native = 1
      any_mode = 1
      ai = ai + 1
      continue
    if streq(a, "--all"):
      run_bc = 1
      run_native = 1
      any_mode = 1
      ai = ai + 1
      continue
    if streq(a, "--vectorize"):
      vectorize = 1
      ai = ai + 1
      continue
    if streq(a, "--no-vectorize"):
      vectorize = 0
      ai = ai + 1
      continue
    if streq(a, "--profile"):
      profile = 1
      if (ai + 1) < args_count():
        n:int = parse_i64(arg(ai + 1))
        if n > 0:
          profile_runs = n
          ai = ai + 1
      ai = ai + 1
      continue
    if streq(a, "--tune"):
      tune = 1
      ai = ai + 1
      continue
    if streq(a, "--gate"):
      gate = 1
      ai = ai + 1
      continue
    if streq(a, "--baseline") && (ai + 1) < args_count():
      baseline_path = arg(ai + 1)
      ai = ai + 2
      continue
    if starts_with(a, "--baseline=") != 0:
      baseline_path = a + 11
      ai = ai + 1
      continue
    if streq(a, "--perf-max-pct") && (ai + 1) < args_count():
      perf_max_pct = parse_i64(arg(ai + 1))
      ai = ai + 2
      continue
    if starts_with(a, "--perf-max-pct=") != 0:
      perf_max_pct = parse_i64(a + 15)
      ai = ai + 1
      continue
    if streq(a, "--kernel-perf"):
      kernel_perf = 1
      ai = ai + 1
      continue
    if starts_with(a, "--profile=") != 0:
      profile = 1
      n2:int = parse_i64(a + 10)
      if n2 > 0:
        profile_runs = n2
      ai = ai + 1
      continue
    if streq(a, "--target") && (ai + 1) < args_count():
      target = arg(ai + 1)
      ai = ai + 2
      continue
    ai = ai + 1

  if any_mode == 0:
    run_bc = 1
    run_native = 1

  if run_native != 0 || profile != 0 || tune != 0:
    ensure_dir("build")

  if gate != 0 && profile == 0:
    profile = 1
    profile_runs = 5

  if tune != 0 && profile == 0:
    profile = 1
    profile_runs = 3

  csv:str = str_join2("", "name,lang,mode,ns\n")
  runlog:str = 0 as str
  if profile != 0:
    runlog = str_join2("", "name,mode,min,median,avg,stddev,p95,runs\n")
  idx:int = 0

  while 1:
    start:str = next_manifest_line(list, &idx)
    if start == 0:
      break
    // optional per-entry mode: "path | bc" or "path | native"
    path:str = start
    mode:str = 0 as str
    left:str = 0 as str
    right:str = 0 as str
    if split_pair(start, &left, &right) == 0:
      free(start)
      path = left
      mode = right
    run_bc_item:int = run_bc
    run_native_item:int = run_native
    if mode != 0:
      if streq(mode, "bc") != 0:
        run_native_item = 0
      else if streq(mode, "native") != 0:
        run_bc_item = 0
    say path
    if run_bc_item != 0:
      // Bytecode VM run
      cbc0:str = str_join3(tezzc, " run ", path)
      cmd_bc:str = str_join2(cbc0, " --bc")
      free(cbc0)
      if profile != 0:
        times_bc:[int;64]
        tcount_bc:int = 0
        best_name_bc:str = 0 as str
        rbc:int = 0
        while rbc < profile_runs:
          out_bc:str = proc_out(cmd_bc)
          if out_bc != 0:
            out_bc = normalize_out(out_bc)
            out_bc = trim_line(out_bc)
            name_bc:str = line0_nonempty(out_bc)
            ns_bc:str = line1_nonempty(out_bc)
            if name_bc != 0 && ns_bc != 0 && len(name_bc) > 0 && len(ns_bc) > 0:
              nvbc:int = parse_i64(ns_bc)
              if nvbc > 0 && tcount_bc < 64:
                times_bc[tcount_bc] = nvbc
                tcount_bc = tcount_bc + 1
              if best_name_bc == 0:
                best_name_bc = name_bc
                name_bc = 0 as str
            if name_bc != 0:
              free(name_bc)
            if ns_bc != 0:
              free(ns_bc)
            free(out_bc)
          rbc = rbc + 1
        if tcount_bc > 0 && best_name_bc != 0:
          minbc:int = stats_min(times_bc, tcount_bc)
          medbc:int = stats_median(times_bc, tcount_bc)
          avgbc:int = stats_avg(times_bc, tcount_bc)
          sdbc:int = stats_stddev(times_bc, tcount_bc)
          p95bc:int = stats_p95(times_bc, tcount_bc)
          say str_join3("  bc: ", best_name_bc, " (profile)")
          ns_best_bc:str = int_to_str(minbc)
          lb1:str = str_join3(best_name_bc, ",tezz,bc,", ns_best_bc)
          lb2:str = str_join2(lb1, "\n")
          tmpcsvbc:str = str_join2(csv, lb2)
          free(csv)
          csv = tmpcsvbc
          free(lb1)
          free(lb2)
          free(ns_best_bc)

          if runlog != 0:
            sminbc:str = int_to_str(minbc)
            smedbc:str = int_to_str(medbc)
            savgbc:str = int_to_str(avgbc)
            ssdbc:str = int_to_str(sdbc)
            sp95bc:str = int_to_str(p95bc)
            srunsbc:str = int_to_str(tcount_bc)
            rb1:str = str_join3(best_name_bc, ",bc,", sminbc)
            rb2:str = str_join3(rb1, ",", smedbc)
            rb3:str = str_join3(rb2, ",", savgbc)
            rb4:str = str_join3(rb3, ",", ssdbc)
            rb5:str = str_join3(rb4, ",", sp95bc)
            rb6:str = str_join3(rb5, ",", srunsbc)
            rb7:str = str_join2(rb6, "\n")
            tmpbc:str = str_join2(runlog, rb7)
            free(runlog)
            runlog = tmpbc
            free(sminbc)
            free(smedbc)
            free(savgbc)
            free(ssdbc)
            free(sp95bc)
            free(srunsbc)
            free(rb1)
            free(rb2)
            free(rb3)
            free(rb4)
            free(rb5)
            free(rb6)
            free(rb7)
          free(best_name_bc)
        else:
          say "  bc: (no output)"
      else:
        out_bc:str = proc_out(cmd_bc)
        if out_bc != 0:
          out_bc = normalize_out(out_bc)
          out_bc = trim_line(out_bc)
          name_bc:str = line0_nonempty(out_bc)
          ns_bc:str = line1_nonempty(out_bc)
          if name_bc != 0 && ns_bc != 0 && len(name_bc) > 0 && len(ns_bc) > 0:
            say str_join2("  bc: ", out_bc)
            lb1:str = str_join3(name_bc, ",tezz,bc,", ns_bc)
            lb2:str = str_join2(lb1, "\n")
            tmpcsvbc:str = str_join2(csv, lb2)
            free(csv)
            csv = tmpcsvbc
            free(lb1)
            free(lb2)
          else:
            say "  bc: (no output)"
          if name_bc != 0:
            free(name_bc)
          if ns_bc != 0:
            free(ns_bc)
          free(out_bc)
        else:
          say "  bc: (no output)"

      free(cmd_bc)

    if run_native_item != 0:
      base:str = path_basename_no_ext(path)
      if base == 0 || base[0] == 0:
        if base != 0:
          free(base)
        if mode != 0:
          free(mode)
        free(path)
        continue
      out1:str = str_join2(out_dir, base)
      out2:str = str_join2(out1, "_bench")
      out3:str = str_join2(out2, exe_suffix)

      cmd1:str = str_join3(tezzc, " buildexe ", path)
      cmd2:str = str_join3(cmd1, " ", out3)
      cmd3:str = str_join3(cmd2, " --target ", target)
      if vectorize != 0:
        cmd4:str = str_join2(cmd3, " --vectorize")
        free(cmd3)
        cmd3 = cmd4

      if proc_run(cmd3) != 0:
        say "  native: (build failed)"
      else:
        if tune != 0:
          blocks:[int;6]
          unrolls:[int;6]
          bcount:int = 4
          ucount:int = 4
          blocks[0] = 64
          blocks[1] = 128
          blocks[2] = 256
          blocks[3] = 512
          unrolls[0] = 1
          unrolls[1] = 2
          unrolls[2] = 4
          unrolls[3] = 8

          best_name2:str = 0 as str
          best_min:int = 0
          best_med:int = 0
          best_avg:int = 0
          best_sd:int = 0
          best_p95:int = 0
          best_runs:int = 0
          best_block:int = 0
          best_unroll:int = 0
          src0:str = io.read_all(path)
          tmp_path:str = 0 as str
          if src0 != 0:
            tmp_path = str_join3(out_dir, base, "_tune.tn")

          bi:int = 0
          while bi < bcount:
            block:int = blocks[bi]
            ui:int = 0
            while ui < ucount:
              unroll:int = unrolls[ui]
              if src0 != 0 && tmp_path != 0:
                tuned:str = tune_source(src0, block, unroll)
                if tuned != 0:
                  io.write_all(tmp_path, tuned)
                  free(tuned)
                cmdt1:str = str_join3(tezzc, " buildexe ", tmp_path)
                cmdt2:str = str_join3(cmdt1, " ", out3)
                cmdt3:str = str_join3(cmdt2, " --target ", target)
                if vectorize != 0:
                  cmdt4:str = str_join2(cmdt3, " --vectorize")
                  free(cmdt3)
                  cmdt3 = cmdt4

                if proc_run(cmdt3) != 0:
                  free(cmdt1)
                  free(cmdt2)
                  free(cmdt3)
                  ui = ui + 1
                  continue

                free(cmdt1)
                free(cmdt2)
                free(cmdt3)

              times2:[int;64]
              tcount2:int = 0
              r2:int = 0
              while r2 < profile_runs:
                out_exe:str = proc_out(out3)
                if out_exe != 0:
                  out_exe = normalize_out(out_exe)
                  out_exe = trim_line(out_exe)
                  name_exe:str = line0_nonempty(out_exe)
                  ns_exe:str = line1_nonempty(out_exe)
                  if name_exe != 0 && ns_exe != 0 && len(name_exe) > 0 && len(ns_exe) > 0:
                    nv2:int = parse_i64(ns_exe)
                    if nv2 > 0 && tcount2 < 64:
                      times2[tcount2] = nv2
                      tcount2 = tcount2 + 1
                    if best_name2 == 0:
                      best_name2 = name_exe
                      name_exe = 0 as str
                  if name_exe != 0:
                    free(name_exe)
                  if ns_exe != 0:
                    free(ns_exe)
                  free(out_exe)
                r2 = r2 + 1

              if tcount2 > 0:
                minv2:int = stats_min(times2, tcount2)
                medv2:int = stats_median(times2, tcount2)
                avgv2:int = stats_avg(times2, tcount2)
                sdv2:int = stats_stddev(times2, tcount2)
                p952:int = stats_p95(times2, tcount2)
                if best_min == 0 || minv2 < best_min:
                  best_min = minv2
                  best_med = medv2
                  best_avg = avgv2
                  best_sd = sdv2
                  best_p95 = p952
                  best_runs = tcount2
                  best_block = block
                  best_unroll = unroll

              ui = ui + 1
            bi = bi + 1

          if best_name2 != 0 && best_min > 0:
            say str_join3("  native: ", best_name2, " (tune)")
            bb:str = int_to_str(best_block)
            uu:str = int_to_str(best_unroll)
            t1:str = str_join3("    block=", bb, ", unroll=")
            t2:str = str_join2(t1, uu)
            say t2
            free(t1)
            free(t2)
            free(bb)
            free(uu)

            ns_best2:str = int_to_str(best_min)
            l1:str = str_join3(best_name2, ",tezz,native,", ns_best2)
            l2:str = str_join2(l1, "\n")
            tmpcsv:str = str_join2(csv, l2)
            free(csv)
            csv = tmpcsv
            free(l1)
            free(l2)
            free(ns_best2)

            if runlog != 0:
              smin2:str = int_to_str(best_min)
              smed2:str = int_to_str(best_med)
              savg2:str = int_to_str(best_avg)
              ssd2:str = int_to_str(best_sd)
              sp952:str = int_to_str(best_p95)
              sruns2:str = int_to_str(best_runs)
              r1b:str = str_join3(best_name2, ",native,", smin2)
              r2b:str = str_join3(r1b, ",", smed2)
              r3b:str = str_join3(r2b, ",", savg2)
              r4b:str = str_join3(r3b, ",", ssd2)
              r5b:str = str_join3(r4b, ",", sp952)
              r6b:str = str_join3(r5b, ",", sruns2)
              r7b:str = str_join2(r6b, "\n")
              tmpb:str = str_join2(runlog, r7b)
              free(runlog)
              runlog = tmpb
              free(smin2)
              free(smed2)
              free(savg2)
              free(ssd2)
              free(sp952)
              free(sruns2)
              free(r1b)
              free(r2b)
              free(r3b)
              free(r4b)
              free(r5b)
              free(r6b)
              free(r7b)
            free(best_name2)
          else:
            say "  native: (no output)"
          if tmp_path != 0:
            remove(tmp_path)
            free(tmp_path)
          if src0 != 0:
            free(src0)
        else:
          if profile != 0:
            times2:[int;64]
            tcount2:int = 0
            best_name2:str = 0 as str
            r2:int = 0
            while r2 < profile_runs:
              out_exe:str = proc_out(out3)
              if out_exe != 0:
                out_exe = normalize_out(out_exe)
                out_exe = trim_line(out_exe)
                name_exe:str = line0_nonempty(out_exe)
                ns_exe:str = line1_nonempty(out_exe)
                if name_exe != 0 && ns_exe != 0 && len(name_exe) > 0 && len(ns_exe) > 0:
                  nv2:int = parse_i64(ns_exe)
                  if nv2 > 0 && tcount2 < 64:
                    times2[tcount2] = nv2
                    tcount2 = tcount2 + 1
                  if best_name2 == 0:
                    best_name2 = name_exe
                    name_exe = 0 as str
                if name_exe != 0:
                  free(name_exe)
                if ns_exe != 0:
                  free(ns_exe)
                free(out_exe)
              r2 = r2 + 1
            if tcount2 > 0 && best_name2 != 0:
              minv2:int = stats_min(times2, tcount2)
              medv2:int = stats_median(times2, tcount2)
              avgv2:int = stats_avg(times2, tcount2)
              sdv2:int = stats_stddev(times2, tcount2)
              p952:int = stats_p95(times2, tcount2)
              say str_join3("  native: ", best_name2, " (profile)")
              ns_best2:str = int_to_str(minv2)
              l1:str = str_join3(best_name2, ",tezz,native,", ns_best2)
              l2:str = str_join2(l1, "\n")
              tmpcsv:str = str_join2(csv, l2)
              free(csv)
              csv = tmpcsv
              free(l1)
              free(l2)
              free(ns_best2)

              if runlog != 0:
                smin2:str = int_to_str(minv2)
                smed2:str = int_to_str(medv2)
                savg2:str = int_to_str(avgv2)
                ssd2:str = int_to_str(sdv2)
                sp952:str = int_to_str(p952)
                sruns2:str = int_to_str(tcount2)
                r1b:str = str_join3(best_name2, ",native,", smin2)
                r2b:str = str_join3(r1b, ",", smed2)
                r3b:str = str_join3(r2b, ",", savg2)
                r4b:str = str_join3(r3b, ",", ssd2)
                r5b:str = str_join3(r4b, ",", sp952)
                r6b:str = str_join3(r5b, ",", sruns2)
                r7b:str = str_join2(r6b, "\n")
                tmpb:str = str_join2(runlog, r7b)
                free(runlog)
                runlog = tmpb
                free(smin2)
                free(smed2)
                free(savg2)
                free(ssd2)
                free(sp952)
                free(sruns2)
                free(r1b)
                free(r2b)
                free(r3b)
                free(r4b)
                free(r5b)
                free(r6b)
                free(r7b)
              free(best_name2)
            else:
              say "  native: (no output)"
          else:
            out_exe:str = proc_out(out3)
            if out_exe != 0:
              out_exe = normalize_out(out_exe)
              out_exe = trim_line(out_exe)
              name_exe:str = line0_nonempty(out_exe)
              ns_exe:str = line1_nonempty(out_exe)
              if name_exe != 0 && ns_exe != 0 && len(name_exe) > 0 && len(ns_exe) > 0:
                say str_join2("  native: ", out_exe)
                l1:str = str_join3(name_exe, ",tezz,native,", ns_exe)
                l2:str = str_join2(l1, "\n")
                tmpcsv:str = str_join2(csv, l2)
                free(csv)
                csv = tmpcsv
                free(l1)
                free(l2)
              else:
                say "  native: (no output)"
              if name_exe != 0:
                free(name_exe)
              if ns_exe != 0:
                free(ns_exe)
              free(out_exe)
            else:
              say "  native: (no output)"

      free(cmd1)
      free(cmd2)
      free(cmd3)
      free(out1)
      free(out2)
      free(out3)
      if base != 0:
        free(base)

    if mode != 0:
      free(mode)
    free(path)
  if run_bc != 0 && run_native != 0:
    names:[str;256]
    bc_ns:[int;256]
    native_ns:[int;256]
    ncount:int = 0
    li:int = 0
    lstart:int = 0
    while 1:
      ch:int = csv[li] as int
      if ch == 0 || ch == 10:
        if li > lstart:
          line:str = substr_dup(csv, lstart, li)
          if starts_with(line, "name,") == 0:
            a:int = 0
            while line[a] != 0 && line[a] != 44:
              a = a + 1
            if line[a] == 44:
              b:int = a + 1
              while line[b] != 0 && line[b] != 44:
                b = b + 1
              if line[b] == 44:
                c2:int = b + 1
                while line[c2] != 0 && line[c2] != 44:
                  c2 = c2 + 1
                if line[c2] == 44:
                  name:str = substr_dup(line, 0, a)
                  lang:str = substr_dup(line, a + 1, b)
                  mode:str = substr_dup(line, b + 1, c2)
                  ns_str:str = substr_dup(line, c2 + 1, len(line))
                  if streq(lang, "tezz") != 0 && (streq(mode, "bc") != 0 || streq(mode, "native") != 0):
                    ns_val:int = parse_i64(ns_str)
                    idx:int = 0 - 1
                    ii:int = 0
                    while ii < ncount:
                      if streq(names[ii], name) != 0:
                        idx = ii
                        break
                      ii = ii + 1
                    stored:int = 0
                    if idx < 0 && ncount < 256:
                      names[ncount] = name
                      bc_ns[ncount] = 0
                      native_ns[ncount] = 0
                      idx = ncount
                      ncount = ncount + 1
                      stored = 1
                    if idx >= 0:
                      if streq(mode, "bc") != 0:
                        bc_ns[idx] = ns_val
                      else:
                        native_ns[idx] = ns_val
                    if stored == 0:
                      free(name)
                  else:
                    free(name)
                  free(lang)
                  free(mode)
                  free(ns_str)
          free(line)
        if ch == 0:
          break
        lstart = li + 1
      li = li + 1

    deltas:str = str_join2("", "name,bc_ns,native_ns,delta_pct\n")
    any_delta:int = 0
    di:int = 0
    while di < ncount:
      if bc_ns[di] > 0 && native_ns[di] > 0:
        delta:int = (bc_ns[di] - native_ns[di]) * 100 / native_ns[di]
        sbc:str = int_to_str(bc_ns[di])
        snat:str = int_to_str(native_ns[di])
        sdel:str = int_to_str(delta)
        d1:str = str_join3(names[di], ",", sbc)
        d2:str = str_join3(d1, ",", snat)
        d3:str = str_join3(d2, ",", sdel)
        d4:str = str_join2(d3, "\n")
        tmpd:str = str_join2(deltas, d4)
        free(deltas)
        deltas = tmpd
        free(sbc)
        free(snat)
        free(sdel)
        free(d1)
        free(d2)
        free(d3)
        free(d4)
        any_delta = 1
      di = di + 1
    di = 0
    while di < ncount:
      if names[di] != 0:
        free(names[di])
      di = di + 1
    if any_delta != 0:
      if runlog == 0:
        h1:str = "# deltas (bc vs native)\n"
        tmp1:str = str_join2(h1, deltas)
        runlog = tmp1
      else:
        h2:str = "\n# deltas (bc vs native)\n"
        t1:str = str_join2(runlog, h2)
        t2:str = str_join2(t1, deltas)
        free(runlog)
        runlog = t2
        free(t1)
      free(deltas)
    else:
      free(deltas)

  if kernel_perf != 0:
    ensure_dir("build")
    report:str = str_join2("", "op,policy,ns\n")
    cmd1:str = str_join2(tezzc, " run --bc bench/kernel_perf.tn")
    out:str = proc_out(cmd1)
    if out != 0:
      out = normalize_out(out)
      out = trim_line(out)
      idxp:int = 0
      // First line is a header; skip it.
      hdr:str = next_manifest_line(out, &idxp)
      if hdr != 0:
        free(hdr)
      while 1:
        opnm:str = next_manifest_line(out, &idxp)
        if opnm == 0:
          break
        pol:str = next_manifest_line(out, &idxp)
        nsstr:str = next_manifest_line(out, &idxp)
        if pol == 0 || nsstr == 0:
          if pol != 0:
            free(pol)
          if nsstr != 0:
            free(nsstr)
          free(opnm)
          break
        line1:str = str_join3(opnm, ",", pol)
        line2:str = str_join3(line1, ",", nsstr)
        line3:str = str_join2(line2, "\n")
        tmprep:str = str_join2(report, line3)
        free(report)
        report = tmprep
        free(line1)
        free(line2)
        free(line3)
        free(opnm)
        free(pol)
        free(nsstr)
      free(out)
    free(cmd1)
    io.write_all("build/kernel_perf_report.tnx", report)
    free(report)

  io.write_all("build/bench.tnx", csv)
  if runlog != 0:
    io.write_all("build/bench_run.tnx", runlog)

  if gate != 0:
    if runlog == 0:
      say "bench gate: missing runlog (use --profile)"
      if runlog != 0:
        free(runlog)
      free(csv)
      free(list)
      ret 0 - 1
    base:str = io.read_all(baseline_path)
    if base == 0:
      say "bench gate: missing baseline"
      if runlog != 0:
        free(runlog)
      free(csv)
      free(list)
      ret 0 - 1
    idxg:int = 0
    bad:int = 0
    checked:int = 0
    while 1:
      line:str = next_manifest_line(runlog, &idxg)
      if line == 0:
        break
      if starts_with(line, "name,") != 0:
        free(line)
        continue
      name:str = csv_field(line, 0)
      mode:str = csv_field(line, 1)
      p95s:str = csv_field(line, 6)
      cur:int = 0
      if p95s != 0:
        cur = parse_i64(p95s)
      base_p95:int = bench_find_p95(base, name, mode)
      if base_p95 > 0 && cur > 0:
        delta:int = (cur - base_p95) * 100 / base_p95
        checked = checked + 1
        if delta > perf_max_pct:
          bad = bad + 1
          sb:str = int_to_str(base_p95)
          sc:str = int_to_str(cur)
          sd:str = int_to_str(delta)
          m1:str = str_join3("perf regression: ", name, " ")
          m2:str = str_join3(m1, mode, " ")
          m3:str = str_join3(m2, sb, " -> ")
          m4:str = str_join3(m3, sc, " (")
          m5:str = str_join3(m4, sd, "%)")
          say m5
          free(sb)
          free(sc)
          free(sd)
          free(m1)
          free(m2)
          free(m3)
          free(m4)
          free(m5)
      if name != 0:
        free(name)
      if mode != 0:
        free(mode)
      if p95s != 0:
        free(p95s)
      free(line)
    free(base)
    if checked == 0:
      say "bench gate: no comparable entries"
      if runlog != 0:
        free(runlog)
      free(csv)
      free(list)
      ret 0 - 1
    if bad != 0:
      say "bench gate: FAILED"
      if runlog != 0:
        free(runlog)
      free(csv)
      free(list)
      ret 0 - 1
    say "bench gate: OK"
  if runlog != 0:
    free(runlog)
  free(csv)
  free(list)
  ret 0

fn cmd_bench_ext() -> int:
  list:str = io.read_all("bench/external_manifest.tnx")
  if list == 0:
    say "missing bench/external_manifest.tnx"
    ret 0 - 1

  ensure_dir("build")
  os:str = os_name()
  csv:str = io.read_all("build/bench.tnx")
  if csv == 0:
    csv = str_join2("", "name,lang,mode,ns\n")

  idx:int = 0
  while 1:
    start:str = next_manifest_line(list, &idx)
    if start == 0:
      break
    a:int = 0
    while start[a] != 0 && start[a] != 44:
      a = a + 1
    if start[a] == 44:
      b:int = a + 1
      while start[b] != 0 && start[b] != 44:
        b = b + 1
      if start[b] == 44:
        name:str = substr_dup(start, 0, a)
        lang:str = substr_dup(start, a + 1, b)
        cmd:str = substr_dup(start, b + 1, len(start))
        if streq(os, "windows") != 0:
          tmpcmd:str = win_fix_cmd_slash(cmd)
          free(cmd)
          cmd = tmpcmd
        out:str = proc_out(cmd)
        if out != 0:
          out = normalize_out(out)
          out = trim_line(out)
          nname:str = line0_nonempty(out)
          ns:str = line1_nonempty(out)
          if nname == 0:
            nname = name
          if ns != 0:
            l1:str = str_join3(nname, ",", lang)
            l2:str = str_join2(l1, ",external,")
            l3:str = str_join2(l2, ns)
            l4:str = str_join2(l3, "\n")
            tmpcsv:str = str_join2(csv, l4)
            free(csv)
            csv = tmpcsv
            free(l1)
            free(l2)
            free(l3)
            free(l4)
          if nname != 0 && nname != name:
            free(nname)
          if ns != 0:
            free(ns)
          free(out)
        free(name)
        free(lang)
        free(cmd)
    free(start)

  io.write_all("build/bench.tnx", csv)
  free(csv)
  free(list)
  ret 0

fn cmd_clean() -> int:
  if path_exists("build") != 0:
    clean_dir("build")
  ret 0

fn doctor_ok(label:str, detail:str):
  p0:str = str_join2("[OK] ", label)
  if detail == 0 || detail[0] == 0:
    say p0
    free(p0)
    ret
  p1:str = str_join3(p0, " :: ", detail)
  say p1
  free(p0)
  free(p1)

fn doctor_warn(label:str, detail:str):
  p0:str = str_join2("[WARN] ", label)
  if detail == 0 || detail[0] == 0:
    say p0
    free(p0)
    ret
  p1:str = str_join3(p0, " :: ", detail)
  say p1
  free(p0)
  free(p1)

fn doctor_fail(label:str, detail:str):
  p0:str = str_join2("[FAIL] ", label)
  if detail == 0 || detail[0] == 0:
    say p0
    free(p0)
    ret
  p1:str = str_join3(p0, " :: ", detail)
  say p1
  free(p0)
  free(p1)

fn run_installer_mode(mode:str) -> int:
  nonce:str = int_to_str(time.now_ms())
  osn:str = os_name()
  if streq(osn, "windows"):
    ps_url:str = str_join3("https://tn.tezzcorp.com/download/install.ps1?nocache=", nonce, "")
    c0:str = str_join3("powershell -NoProfile -ExecutionPolicy Bypass -Command \"iwr ", ps_url, " -OutFile $env:TEMP\\tezz-install.ps1; powershell -ExecutionPolicy Bypass -File $env:TEMP\\tezz-install.ps1 -Mode ")
    c1:str = str_join3(c0, mode, "")
    c2:str = str_join2(c1, "\"")
    free(ps_url)
    free(c0)
    r1:int = proc_run(c2)
    free(c1)
    free(c2)
    free(nonce)
    ret r1

  sh_url:str = str_join3("https://tn.tezzcorp.com/download/install.sh?nocache=", nonce, "")
  c3a:str = str_join3("curl -fsSL ", sh_url, " | bash -s -- ")
  c3:str = str_join3(c3a, mode, "")
  r2:int = proc_run(c3)
  free(c3a)
  free(c3)
  if r2 != 0:
    c4a:str = str_join3("wget -qO- ", sh_url, " | bash -s -- ")
    c4:str = str_join3(c4a, mode, "")
    r2 = proc_run(c4)
    free(c4a)
    free(c4)
  free(sh_url)
  free(nonce)
  ret r2

fn run_installer_mode_windows_scoped(mode:str, scope:str, path_mode:str) -> int:
  nonce:str = int_to_str(time.now_ms())
  ps_url:str = str_join3("https://tn.tezzcorp.com/download/install.ps1?nocache=", nonce, "")
  p0:str = str_join3("powershell -NoProfile -ExecutionPolicy Bypass -Command \"$env:TEZZ_INSTALL_SCOPE='", scope, "'; ")
  p1:str = str_join3("$env:TEZZ_INSTALL_AUTO_PATH='", path_mode, "'; iwr ")
  p2:str = str_join3(ps_url, " -OutFile $env:TEMP\\tezz-install.ps1; powershell -ExecutionPolicy Bypass -File $env:TEMP\\tezz-install.ps1 -Mode ", mode)
  p3:str = str_join2(p0, p1)
  p4:str = str_join2(p3, p2)
  p5:str = str_join2(p4, "\"")

  free(nonce)
  free(ps_url)
  free(p0)
  free(p1)
  free(p2)
  free(p3)
  free(p4)

  rr:int = proc_run(p5)
  free(p5)
  ret rr

fn run_installer_mode_fix() -> int:
  osn:str = os_name()
  if streq(osn, "windows"):
    r_user_install:int = run_installer_mode_windows_scoped("install", "user", "user")
    if r_user_install == 0:
      ret 0
    r_user_reinstall:int = run_installer_mode_windows_scoped("reinstall", "user", "user")
    if r_user_reinstall == 0:
      ret 0
    ret r_user_reinstall
  ret run_installer_mode("install")

fn rerun_doctor_strict(tezzc:str, sdk_root:str) -> int:
  if tezzc == 0 || sdk_root == 0 || sdk_root[0] == 0:
    ret 0 - 1
  tool_path:str = path_join(sdk_root, "tools/tezz.tn")
  if path_exists(tool_path) == 0:
    free(tool_path)
    ret 0 - 1

  tezzc_q:str = quote_cmd_path(tezzc)
  tool_q:str = quote_cmd_path(tool_path)
  sdk_q:str = quote_cmd_path(sdk_root)
  free(tool_path)
  if tezzc_q == 0 || tool_q == 0 || sdk_q == 0:
    if tezzc_q != 0:
      free(tezzc_q)
    if tool_q != 0:
      free(tool_q)
    if sdk_q != 0:
      free(sdk_q)
    ret 0 - 1

  c0:str = str_join3(tezzc_q, " run ", tool_q)
  c1:str = str_join2(c0, " -- doctor --strict --tezzc ")
  c2:str = str_join2(c1, tezzc_q)
  c3:str = str_join2(c2, " --sdk-root ")
  c4:str = str_join2(c3, sdk_q)

  free(c0)
  free(c1)
  free(c2)
  free(c3)
  free(tezzc_q)
  free(tool_q)
  free(sdk_q)

  rr:int = proc_run(c4)
  free(c4)
  ret rr

fn cmd_doctor() -> int:
  strict:int = 0
  fix:int = 0
  ai:int = 1
  ucnt:int = user_args_count()
  while ai < ucnt:
    a:str = arg(ai)
    if streq(a, "--strict"):
      strict = 1
      ai = ai + 1
      continue
    if streq(a, "--fix"):
      fix = 1
      ai = ai + 1
      continue
    if streq(a, "--help") || streq(a, "-h"):
      print_usage_doctor()
      ret 0
    if starts_with(a, "--") != 0:
      p0:str = str_join2("doctor: unknown option: ", a)
      say p0
      free(p0)
      print_usage_doctor()
      ret 0 - 1
    ai = ai + 1

  say "TezzNative doctor v1"
  failed:int = 0
  warned:int = 0

  osn:str = os_name()
  arch:str = detect_arch()
  host0:str = str_join3("host: ", osn, " / ")
  host1:str = str_join2(host0, arch)
  say host1
  free(host0)
  free(host1)
  free(arch)

  has_tezz:int = tool_exists("tezz")
  if has_tezz == 0 && streq(osn, "windows"):
    if tool_exists("tezz.cmd") != 0:
      has_tezz = 1
  if has_tezz != 0:
    doctor_ok("PATH tezz", "found")
  else:
    doctor_warn("PATH tezz", "not found in PATH (use full launcher path or add bin dir)")
    warned = warned + 1

  tezzc:str = tezzc_path()
  if tezzc == 0:
    doctor_fail("compiler", "tezzc not found (bin/tezzc, build/tezzc, or PATH)")
    failed = failed + 1
  else:
    doctor_ok("compiler", tezzc)
    if path_exists("tools/tezz.tn") != 0:
      c1:str = str_join3(tezzc, " check ", "tools/tezz.tn")
      if proc_run(c1) != 0:
        doctor_fail("compiler smoke", "tezzc check tools/tezz.tn failed")
        failed = failed + 1
      else:
        doctor_ok("compiler smoke", "tezzc check tools/tezz.tn")
      free(c1)
    else:
      doctor_ok("compiler smoke", "skipped (tools/tezz.tn not in cwd)")

  sdk_root:str = sdk_root_arg()
  own_sdk_root:int = 0
  sdk_root_core_ok:int = 0
  if sdk_root == 0 || sdk_root[0] == 0:
    sdk_env:str = env_value("TEZZ_SDK_ROOT")
    if sdk_env != 0 && sdk_env[0] != 0:
      sdk_root = sdk_env
      own_sdk_root = 1
      doctor_ok("env TEZZ_SDK_ROOT", sdk_root)
    else:
      if sdk_env != 0:
        free(sdk_env)
      doctor_warn("env TEZZ_SDK_ROOT", "not set")
      warned = warned + 1
  if (sdk_root == 0 || sdk_root[0] == 0) && tezzc != 0:
    sdk_guess:str = infer_sdk_root_from_tezzc(tezzc)
    if sdk_guess != 0 && sdk_guess[0] != 0:
      sdk_root = sdk_guess
      own_sdk_root = 1
      doctor_ok("sdk root inferred", sdk_root)
  if sdk_root != 0 && sdk_root[0] != 0:
    sdk_tool:str = path_join(sdk_root, "tools/tezz.tn")
    sdk_lib_std:str = path_join(sdk_root, "lib/std.tn")
    sdk_lib_io:str = path_join(sdk_root, "lib/io.tn")
    sdk_lib_net:str = path_join(sdk_root, "lib/net.tn")
    sdk_lib_tls:str = path_join(sdk_root, "lib/tls.tn")
    sdk_bin:str = path_join(sdk_root, "bin")
    sdk_bin_tezzc_exe:str = path_join(sdk_root, "bin/tezzc.exe")
    sdk_bin_tezzc:str = path_join(sdk_root, "bin/tezzc")
    sdk_build_tezzc_exe:str = path_join(sdk_root, "build/tezzc.exe")
    sdk_build_tezzc:str = path_join(sdk_root, "build/tezzc")
    if path_exists(sdk_tool) != 0 && path_exists(sdk_lib_std) != 0 && path_exists(sdk_lib_io) != 0 && path_exists(sdk_lib_net) != 0 && path_exists(sdk_lib_tls) != 0:
      doctor_ok("sdk root", sdk_root)
      sdk_root_core_ok = 1
    else:
      doctor_warn("sdk root", "missing core files under --sdk-root (tools/lib)")
      warned = warned + 1
    if path_exists(sdk_bin) != 0 && (path_exists(sdk_bin_tezzc_exe) != 0 || path_exists(sdk_bin_tezzc) != 0):
      doctor_ok("sdk bin", sdk_bin)
    else if path_exists(sdk_bin) != 0:
      doctor_warn("sdk bin", "bin directory present but tezzc binary missing")
      warned = warned + 1
    else if path_exists(sdk_build_tezzc_exe) != 0 || path_exists(sdk_build_tezzc) != 0:
      doctor_ok("sdk bin", "not present; using source-tree build compiler")
    else:
      doctor_warn("sdk bin", "bin directory missing in sdk root")
      warned = warned + 1
    if streq(osn, "windows"):
      sdk_cmd:str = path_join(sdk_root, "tezz.cmd")
      sdk_ps1:str = path_join(sdk_root, "tezz.ps1")
      if path_exists(sdk_cmd) != 0 && path_exists(sdk_ps1) != 0:
        doctor_ok("launcher", "tezz.cmd + tezz.ps1 present")
      else:
        doctor_warn("launcher", "missing tezz.cmd/tezz.ps1 under sdk root")
        warned = warned + 1
      free(sdk_cmd)
      free(sdk_ps1)
    else:
      sdk_sh:str = path_join(sdk_root, "tezz")
      if path_exists(sdk_sh) != 0:
        doctor_ok("launcher", "tezz launcher present")
      else:
        doctor_warn("launcher", "missing tezz launcher under sdk root")
        warned = warned + 1
      free(sdk_sh)
    free(sdk_tool)
    free(sdk_lib_std)
    free(sdk_lib_io)
    free(sdk_lib_net)
    free(sdk_lib_tls)
    free(sdk_bin)
    free(sdk_bin_tezzc_exe)
    free(sdk_bin_tezzc)
    free(sdk_build_tezzc_exe)
    free(sdk_build_tezzc)
  else:
    doctor_warn("sdk root", "not resolved (pass --sdk-root or set TEZZ_SDK_ROOT)")
    warned = warned + 1

  sdk_hits:int = 0
  if path_exists("tools/tezz.tn") != 0:
    sdk_hits = sdk_hits + 1
  if path_exists("lib/std.tn") != 0:
    sdk_hits = sdk_hits + 1
  if path_exists("lib/io.tn") != 0:
    sdk_hits = sdk_hits + 1
  if path_exists("lib/net.tn") != 0:
    sdk_hits = sdk_hits + 1
  if path_exists("lib/tls.tn") != 0:
    sdk_hits = sdk_hits + 1
  if sdk_hits == 5:
    doctor_ok("sdk core", "tools + lib files present")
  else:
    if sdk_root_core_ok != 0:
      doctor_ok("sdk core", "resolved via TEZZ_SDK_ROOT")
    else:
      if sdk_hits == 0:
        doctor_warn("sdk core", "not found in cwd (run from sdk/project root)")
      else:
        doctor_warn("sdk core", "partial files in cwd")
      warned = warned + 1

  if path_exists("tezz.mod") != 0:
    doctor_ok("project", "tezz.mod detected")
  else:
    doctor_warn("project", "tezz.mod not found in cwd")
    warned = warned + 1

  doctor_ok("updater", "available: tezz update --check | tezz update")

  strict_fail:int = 0
  if strict != 0 && warned != 0:
    strict_fail = 1

  if fix != 0 && (failed != 0 || warned != 0):
    say "doctor: running auto-repair via update --install"
    rfix:int = run_installer_mode_fix()
    if rfix != 0:
      if own_sdk_root != 0 && sdk_root != 0:
        free(sdk_root)
      if tezzc != 0:
        free(tezzc)
      say "doctor: auto-repair failed"
      ret 0 - 1
    say "doctor: auto-repair complete; re-running strict checks..."
    rr:int = rerun_doctor_strict(tezzc, sdk_root)
    if own_sdk_root != 0 && sdk_root != 0:
      free(sdk_root)
    if tezzc != 0:
      free(tezzc)
    if rr != 0:
      say "doctor: FAIL (post-fix strict check)"
      ret 0 - 1
    ret 0

  if own_sdk_root != 0 && sdk_root != 0:
    free(sdk_root)
  if tezzc != 0:
    free(tezzc)

  if failed == 0:
    if strict_fail != 0:
      say "doctor: FAIL (strict mode)"
      ret 0 - 1
    if warned == 0:
      say "doctor: PASS"
    else:
      say "doctor: PASS (with warnings)"
    ret 0
  say "doctor: FAIL"
  ret 0 - 1

fn cmd_update() -> int:
  if user_args_count() >= 2:
    a0:str = arg(1)
    if streq(a0, "--help") || streq(a0, "-h"):
      print_usage_update()
      ret 0
  mode:str = "update"
  ai:int = 1
  while ai < args_count():
    a:str = arg(ai)
    if streq(a, "--check"):
      mode = "check"
    else if streq(a, "--install"):
      mode = "install"
    else if streq(a, "--reinstall"):
      mode = "reinstall"
    else if streq(a, "--uninstall"):
      mode = "uninstall"
    ai = ai + 1

  ret run_installer_mode(mode)

fn resolve_lsp_script(tezzc:str) -> str:
  if path_exists("tools/tezz_lsp.tn") != 0:
    ret dup_lit("tools/tezz_lsp.tn")

  sdk_root:str = sdk_root_arg()
  own_sdk_root:int = 0

  if sdk_root == 0 || sdk_root[0] == 0:
    sdk_env:str = env_value("TEZZ_SDK_ROOT")
    if sdk_env != 0 && sdk_env[0] != 0:
      sdk_root = sdk_env
      own_sdk_root = 1
    else:
      if sdk_env != 0:
        free(sdk_env)
      if tezzc != 0:
        sdk_guess:str = infer_sdk_root_from_tezzc(tezzc)
        if sdk_guess != 0 && sdk_guess[0] != 0:
          sdk_root = sdk_guess
          own_sdk_root = 1
        else if sdk_guess != 0:
          free(sdk_guess)

  if sdk_root != 0 && sdk_root[0] != 0:
    lsp_path:str = path_join(sdk_root, "tools/tezz_lsp.tn")
    if own_sdk_root != 0:
      free(sdk_root)
    if path_exists(lsp_path) != 0:
      ret lsp_path
    free(lsp_path)
  else if own_sdk_root != 0 && sdk_root != 0:
    free(sdk_root)

  ret 0 as str

fn cmd_lsp() -> int:
  tezzc:str = tezzc_path()
  if tezzc == 0:
    say "lsp: compiler not found"
    ret 0 - 1
  lsp_src:str = resolve_lsp_script(tezzc)
  if lsp_src == 0:
    say "lsp: tools/tezz_lsp.tn not found (set --sdk-root or TEZZ_SDK_ROOT)"
    free(tezzc)
    ret 0 - 1
  tezzc_q:str = quote_cmd_path(tezzc)
  src_q:str = quote_cmd_path(lsp_src)
  cmd1:str = str_join3(tezzc_q, " run ", src_q)
  r:int = proc_run(cmd1)
  free(cmd1)
  free(src_q)
  free(tezzc_q)
  free(lsp_src)
  free(tezzc)
  ret r

fn cmd_ai() -> int:
  if user_args_count() >= 2:
    a0:str = arg(1)
    if streq(a0, "--help") || streq(a0, "-h") || streq(a0, "help"):
      ret print_usage_ai()
  say "tezz ai is not available in tezz core CLI"
  ret 0 - 1

fn cmd_tsm() -> int:
  if user_args_count() >= 2:
    a0:str = arg(1)
    if streq(a0, "--help") || streq(a0, "-h") || streq(a0, "help"):
      ret print_usage_tsm()
  say "tezz tsm is not available in tezz core CLI"
  ret 0 - 1

fn cmd_release_artifacts() -> int:
  if user_args_count() >= 2:
    a0:str = arg(1)
    if streq(a0, "--help") || streq(a0, "-h"):
      print_usage_release_artifacts()
      ret 0

  out_path:str = "build/release_artifacts.tnx"
  verify_repro:int = 0
  require_sign:int = 0
  sign_key_arg:str = 0 as str
  sign_key_file:str = 0 as str

  ai:int = 1
  while ai < args_count():
    a:str = arg(ai)
    if streq(a, "--tezzc") || streq(a, "--sdk-root"):
      if ai + 1 < args_count():
        ai = ai + 2
      else:
        ai = ai + 1
      continue
    if streq(a, "--out"):
      if ai + 1 >= args_count():
        say "release-artifacts: missing value for --out"
        ret 0 - 1
      out_path = arg(ai + 1)
      ai = ai + 2
      continue
    if streq(a, "--verify-repro"):
      verify_repro = 1
      ai = ai + 1
      continue
    if streq(a, "--require-sign"):
      require_sign = 1
      ai = ai + 1
      continue
    if streq(a, "--sign-key"):
      if ai + 1 >= args_count():
        say "release-artifacts: missing value for --sign-key"
        ret 0 - 1
      sign_key_arg = arg(ai + 1)
      ai = ai + 2
      continue
    if streq(a, "--sign-key-file"):
      if ai + 1 >= args_count():
        say "release-artifacts: missing value for --sign-key-file"
        ret 0 - 1
      sign_key_file = arg(ai + 1)
      ai = ai + 2
      continue
    say "release-artifacts: unknown arg"
    say a
    ret 0 - 1

  sign_key_local:str = 0 as str
  if sign_key_arg != 0:
    if sign_key_arg[0] != 0:
      sign_key_local = sign_key_arg
  if sign_key_local == 0 && sign_key_file != 0:
    if sign_key_file[0] != 0:
      if path_exists(sign_key_file) == 0:
        say "release-artifacts: sign key file not found"
        say sign_key_file
        ret 0 - 1
      key_raw0:str = io.read_all(sign_key_file)
      if key_raw0 == 0:
        say "release-artifacts: unable to read sign key file"
        say sign_key_file
        ret 0 - 1
      key_trim:str = trim_line(key_raw0)
      if key_trim[0] == 0:
        say "release-artifacts: empty sign key file"
        say sign_key_file
        ret 0 - 1
      sign_key_local = key_trim
  if sign_key_local != 0:
    if sign_key_local[0] != 0:
      ensure_dir("build")
      io.write_all("build/release_sign.key", sign_key_local)

  if verify_repro == 0:
    if release_write_manifest(out_path, require_sign, 0, sign_key_local) != 0:
      ret 0 - 1
  else:
    osn_r:str = os_name()
    runner_r:str = "tezz"
    if streq(osn_r, "windows"):
      if path_exists(".\\tezz.cmd") != 0:
        runner_r = ".\\tezz.cmd"
      else:
        runner_r = "tezz.cmd"
    else:
      if path_exists("./tezz") != 0:
        runner_r = "./tezz"

    c0:str = str_join3(runner_r, " ", "release-artifacts --out ")
    c1:str = str_join2(c0, "build/release_artifacts.reprocheck.tnx")
    cmd2:str = c1
    if require_sign != 0:
      c2:str = str_join2(cmd2, " --require-sign")
      cmd2 = c2
      key_file_for_repro:str = "build/release_sign.key"
      if sign_key_file != 0:
        if sign_key_file[0] != 0:
          key_file_for_repro = sign_key_file
      c3a:str = str_join2(cmd2, " --sign-key-file ")
      c3:str = str_join2(c3a, key_file_for_repro)
      cmd2 = c3

    remove("build/release_artifacts.reprocheck.tnx")
    if proc_run(cmd2) != 0:
      remove("build/release_artifacts.reprocheck.tnx")
      say "release-artifacts: reproducibility replay failed"
      ret 0 - 1

    verify_main:str = "build/release_artifacts.tnx"
    if release_write_manifest(verify_main, require_sign, 0, sign_key_local) != 0:
      ret 0 - 1

    m_a:str = io.read_all("build/release_artifacts.tnx")
    m_b:str = io.read_all("build/release_artifacts.reprocheck.tnx")
    same_rc:int = 1
    if m_a == 0:
      say "release-artifacts: repro missing primary manifest"
    if m_b == 0:
      say "release-artifacts: repro missing replay manifest"
    if m_a != 0 && m_b != 0:
      if streq(m_a, m_b) != 0:
        same_rc = 0
    remove("build/release_artifacts.reprocheck.tnx")

    if same_rc != 0:
      if m_a != 0:
        io.write_all("build/release_repro_primary_debug.tnx", m_a)
      if m_b != 0:
        io.write_all("build/release_repro_replay_debug.tnx", m_b)
      say "release-artifacts: reproducibility compare failed"
      ret 0 - 1
    say "release-artifacts: reproducible manifest check OK"
  ret 0

fn repro_artifact_path() -> str:
  if path_exists("bin/tezzc") != 0:
    ret "bin/tezzc"
  if path_exists("bin/tezzc.exe") != 0:
    ret "bin/tezzc.exe"
  if path_exists("build/tezzc") != 0:
    ret "build/tezzc"
  if path_exists("build/tezzc.exe") != 0:
    ret "build/tezzc.exe"
  ret 0 as str

fn build_core_cmd() -> str:
  osn:str = norm_os(os_name())
  cmd:str = 0 as str
  if streq(osn, "windows") != 0:
    cmd = str_join2("powershell -ExecutionPolicy Bypass -File tools/build_core_strict.ps1", "")
  else:
    cmd = str_join2("bash tools/build_core_strict.sh", "")
  free(osn)
  ret cmd

fn cmd_reprocheck() -> int:
  if user_args_count() >= 2:
    a0:str = arg(1)
    if streq(a0, "--help") || streq(a0, "-h"):
      print_usage_reprocheck()
      ret 0

  cmd_b:str = build_core_cmd()
  if cmd_b == 0:
    say "reprocheck: build command unavailable"
    ret 0 - 1
  osn_b:str = norm_os(os_name())
  is_win:int = 0
  if streq(osn_b, "windows") != 0:
    is_win = 1
    if path_exists("tools/build_core_strict.ps1") == 0:
      free(cmd_b)
      free(osn_b)
      say "reprocheck: missing tools/build_core_strict.ps1"
      ret 0 - 1
  else:
    if path_exists("tools/build_core_strict.sh") == 0:
      free(cmd_b)
      free(osn_b)
      say "reprocheck: missing tools/build_core_strict.sh"
      ret 0 - 1
  free(osn_b)
  art1p:str = 0 as str
  art2p:str = 0 as str
  sz1:int = 0
  sz2:int = 0
  crc1:int = 0
  crc2:int = 0
  if is_win != 0:
    // On Windows we can't overwrite the running build/tezzc.exe.
    // Build both passes to the same output name so the PE image doesn't embed a different filename.
    tmp_out:str = "build/repro/tezzc.exe"
    out1:str = "build/tezzc.repro1.exe"
    out2:str = "build/tezzc.repro2.exe"

    cmd1:str = str_join3(cmd_b, " -OutPath ", tmp_out)
    if proc_run(cmd1) != 0:
      free(cmd1)
      free(cmd_b)
      say "reprocheck: build pass 1 failed"
      ret 0 - 1
    free(cmd1)
    if path_exists(tmp_out) == 0:
      free(cmd_b)
      say "reprocheck: compiler artifact not found after pass 1"
      ret 0 - 1
    remove(out1)
    if io.move_file(tmp_out, out1) != 0:
      free(cmd_b)
      say "reprocheck: failed to move pass 1 compiler artifact"
      ret 0 - 1
    art1p = str_join2(out1, "")
    sz1 = file_size(art1p)
    crc1 = crc32_file(art1p)

    cmd2:str = str_join3(cmd_b, " -OutPath ", tmp_out)
    if proc_run(cmd2) != 0:
      free(cmd2)
      free(cmd_b)
      free(art1p)
      say "reprocheck: build pass 2 failed"
      ret 0 - 1
    free(cmd2)
    free(cmd_b)
    if path_exists(tmp_out) == 0:
      free(art1p)
      say "reprocheck: compiler artifact not found after pass 2"
      ret 0 - 1
    remove(out2)
    if io.move_file(tmp_out, out2) != 0:
      free(art1p)
      say "reprocheck: failed to move pass 2 compiler artifact"
      ret 0 - 1
    art2p = str_join2(out2, "")
    sz2 = file_size(art2p)
    crc2 = crc32_file(art2p)
  else:
    if proc_run(cmd_b) != 0:
      free(cmd_b)
      say "reprocheck: build pass 1 failed"
      ret 0 - 1

    art1:str = repro_artifact_path()
    if art1 == 0:
      free(cmd_b)
      say "reprocheck: compiler artifact not found after pass 1"
      ret 0 - 1

    art1p = str_join2(art1, "")
    sz1 = file_size(art1p)
    crc1 = crc32_file(art1p)

    if proc_run(cmd_b) != 0:
      free(cmd_b)
      free(art1p)
      say "reprocheck: build pass 2 failed"
      ret 0 - 1
    free(cmd_b)

    art2:str = repro_artifact_path()
    if art2 == 0:
      free(art1p)
      say "reprocheck: compiler artifact not found after pass 2"
      ret 0 - 1

    art2p = str_join2(art2, "")
    sz2 = file_size(art2p)
    crc2 = crc32_file(art2p)

  h1:str = hex8(crc1)
  h2:str = hex8(crc2)
  s1:str = int_to_str(sz1)
  s2:str = int_to_str(sz2)
  result:str = "FAIL"
  if sz1 == sz2 && crc1 == crc2:
    result = "PASS"

  ensure_dir("build")
  r0a:str = str_join3("artifact_pass1 = ", art1p, "\n")
  r0:str = str_join3(r0a, "artifact_pass2 = ", art2p)
  r0b:str = str_join2(r0, "\n")
  r1a:str = str_join3(r0b, "size_pass1 = ", s1)
  r1:str = str_join2(r1a, "\n")
  r2a:str = str_join3(r1, "size_pass2 = ", s2)
  r2:str = str_join2(r2a, "\n")
  r3a:str = str_join3(r2, "crc_pass1 = ", h1)
  r3:str = str_join2(r3a, "\n")
  r4a:str = str_join3(r3, "crc_pass2 = ", h2)
  r4:str = str_join2(r4a, "\n")
  r5a:str = str_join3(r4, "result = ", result)
  rpt:str = str_join2(r5a, "\n")
  io.write_all("build/reproducible_build.tnx", rpt)

  free(h1)
  free(h2)
  free(s1)
  free(s2)
  free(r0a)
  free(r0)
  free(r0b)
  free(r1a)
  free(r1)
  free(r2a)
  free(r2)
  free(r3a)
  free(r3)
  free(r4a)
  free(r4)
  free(r5a)
  free(rpt)
  free(art1p)
  free(art2p)

  if sz1 == sz2 && crc1 == crc2:
    say "reprocheck: OK"
    ret 0
  say "reprocheck: FAILED"
  ret 0 - 1

fn policy_file_has(path:str, token:str) -> int:
  if path == 0 || token == 0:
    ret 0
  target:str = 0 as str
  own_target:int = 0
  if path_exists(path) != 0:
    target = path
  else:
    sdk_root:str = sdk_root_arg()
    own_sdk_root:int = 0
    if sdk_root == 0 || sdk_root[0] == 0:
      sdk_env:str = env_value("TEZZ_SDK_ROOT")
      if sdk_env != 0 && sdk_env[0] != 0:
        sdk_root = sdk_env
        own_sdk_root = 1
      else:
        if sdk_env != 0:
          free(sdk_env)
    if sdk_root != 0 && sdk_root[0] != 0:
      cand:str = path_join(sdk_root, path)
      if path_exists(cand) != 0:
        target = cand
        own_target = 1
      else:
        free(cand)
    if own_sdk_root != 0 && sdk_root != 0:
      free(sdk_root)
  if target == 0:
    ret 0
  body:str = io.read_all(target)
  if own_target != 0:
    free(target)
  if body == 0:
    ret 0
  ok:int = str_contains(body, token)
  free(body)
  ret ok

fn policy_path_exists(path:str) -> int:
  if path == 0:
    ret 0
  if path_exists(path) != 0:
    ret 1
  sdk_root:str = sdk_root_arg()
  own_sdk_root:int = 0
  if sdk_root == 0 || sdk_root[0] == 0:
    sdk_env:str = env_value("TEZZ_SDK_ROOT")
    if sdk_env != 0 && sdk_env[0] != 0:
      sdk_root = sdk_env
      own_sdk_root = 1
    else:
      if sdk_env != 0:
        free(sdk_env)
  if sdk_root == 0 || sdk_root[0] == 0:
    if own_sdk_root != 0 && sdk_root != 0:
      free(sdk_root)
    ret 0
  cand:str = path_join(sdk_root, path)
  ok:int = 0
  if path_exists(cand) != 0:
    ok = 1
  free(cand)
  if own_sdk_root != 0 && sdk_root != 0:
    free(sdk_root)
  ret ok

fn policy_manifest_nonempty(path:str) -> int:
  target:str = 0 as str
  own_target:int = 0
  if path_exists(path) != 0:
    target = path
  else:
    sdk_root:str = sdk_root_arg()
    own_sdk_root:int = 0
    if sdk_root == 0 || sdk_root[0] == 0:
      sdk_env:str = env_value("TEZZ_SDK_ROOT")
      if sdk_env != 0 && sdk_env[0] != 0:
        sdk_root = sdk_env
        own_sdk_root = 1
      else:
        if sdk_env != 0:
          free(sdk_env)
    if sdk_root != 0 && sdk_root[0] != 0:
      cand:str = path_join(sdk_root, path)
      if path_exists(cand) != 0:
        target = cand
        own_target = 1
      else:
        free(cand)
    if own_sdk_root != 0 && sdk_root != 0:
      free(sdk_root)
  if target == 0:
    ret 0
  body:str = io.read_all(target)
  if own_target != 0:
    free(target)
  if body == 0:
    ret 0
  // Scan for a non-empty, non-comment line without allocating substrings.
  // Manifests are line-based; a single real entry is enough to treat as non-empty.
  i:int = 0
  while body[i] != 0 as char:
    // skip blank lines
    while body[i] == 10 as char || body[i] == 13 as char:
      i = i + 1
    // skip leading spaces/tabs
    while body[i] == 32 as char || body[i] == 9 as char:
      i = i + 1
    if body[i] == 0 as char:
      break
    if body[i] == 35 as char:
      // comment line: skip to newline
      while body[i] != 0 as char && body[i] != 10 as char && body[i] != 13 as char:
        i = i + 1
      continue
    free(body)
    ret 1
  free(body)
  ret 0

fn cmd_release_policy_check() -> int:
  if user_args_count() >= 2:
    a0:str = arg(1)
    if streq(a0, "--help") || streq(a0, "-h"):
      print_usage_release_policy_check()
      ret 0

  bad:int = 0
  if policy_file_has("docs/security_response_policy.md", "## Disclosure Policy") == 0:
    say "release-policy-check: missing disclosure section in docs/security_response_policy.md"
    bad = 1
  if policy_file_has("docs/security_response_policy.md", "## Severity and SLA") == 0:
    say "release-policy-check: missing severity/SLA section in docs/security_response_policy.md"
    bad = 1
  if policy_file_has("docs/release_candidate_runbook.md", "## RC Workflow") == 0:
    say "release-policy-check: missing RC workflow in docs/release_candidate_runbook.md"
    bad = 1
  if policy_file_has("docs/release_candidate_runbook.md", "rollback") == 0:
    say "release-policy-check: missing rollback plan in docs/release_candidate_runbook.md"
    bad = 1
  if policy_file_has("docs/lts_compatibility_policy.md", "## LTS Policy") == 0:
    say "release-policy-check: missing LTS policy in docs/lts_compatibility_policy.md"
    bad = 1
  if policy_file_has("docs/lts_compatibility_policy.md", "## Compatibility Contract") == 0:
    say "release-policy-check: missing compatibility contract in docs/lts_compatibility_policy.md"
    bad = 1
  if policy_file_has("docs/LANGUAGE_SPEC.md", "## Lexical Structure") == 0:
    say "release-policy-check: missing lexical structure in docs/LANGUAGE_SPEC.md"
    bad = 1
  if policy_file_has("docs/LANGUAGE_SPEC.md", "## Types") == 0:
    say "release-policy-check: missing types section in docs/LANGUAGE_SPEC.md"
    bad = 1
  if policy_file_has("docs/LANGUAGE_SPEC.md", "## Production Contract") == 0:
    say "release-policy-check: missing production contract in docs/LANGUAGE_SPEC.md"
    bad = 1
  if policy_file_has("docs/LANGUAGE_SPEC.md", "## GUI Support") == 0:
    say "release-policy-check: missing GUI support section in docs/LANGUAGE_SPEC.md"
    bad = 1
  if policy_file_has("docs/LANGUAGE_SPEC.md", "host-window backend") == 0:
    say "release-policy-check: missing host-window backend contract in docs/LANGUAGE_SPEC.md"
    bad = 1
  if policy_file_has("docs/LANGUAGE_SPEC.md", "lib/tnui.tn") == 0:
    say "release-policy-check: missing tnui contract in docs/LANGUAGE_SPEC.md"
    bad = 1
  if policy_file_has("docs/LANGUAGE_SPEC.md", "lib/tkui.tn") != 0:
    say "release-policy-check: legacy tkui reference found in docs/LANGUAGE_SPEC.md"
    bad = 1
  if policy_file_has("docs/v1_release.md", "## Support Matrix") == 0:
    say "release-policy-check: missing support matrix in docs/v1_release.md"
    bad = 1
  if policy_file_has("docs/v1_release.md", "## Release Inputs") == 0:
    say "release-policy-check: missing release inputs in docs/v1_release.md"
    bad = 1
  if policy_file_has("docs/v1_release.md", "## Promotion Rule") == 0:
    say "release-policy-check: missing promotion rule in docs/v1_release.md"
    bad = 1
  if policy_file_has("docs/v1_release.md", "GUI lane") == 0:
    say "release-policy-check: missing GUI lane contract in docs/v1_release.md"
    bad = 1
  if policy_file_has("docs/native_exe_plan.md", "## Backend Matrix") == 0:
    say "release-policy-check: missing backend matrix in docs/native_exe_plan.md"
    bad = 1
  if policy_file_has("bench/perf_baseline_m6.tnx", "bench_sum,bc") == 0:
    say "release-policy-check: missing bench_sum,bc in bench/perf_baseline_m6.tnx"
    bad = 1
  if policy_file_has("bench/perf_baseline_m6.tnx", "bench_fib,native") == 0:
    say "release-policy-check: missing bench_fib,native in bench/perf_baseline_m6.tnx"
    bad = 1
  if policy_file_has("bench/perf_compare_matrix.tnx", ",c,") == 0:
    say "release-policy-check: missing C entries in bench/perf_compare_matrix.tnx"
    bad = 1
  if policy_file_has("bench/perf_compare_matrix.tnx", ",python,") == 0:
    say "release-policy-check: missing Python entries in bench/perf_compare_matrix.tnx"
    bad = 1
  if policy_file_has("bench/perf_baseline_tznum.tnx", "micro_tznum_matmul_nn,bc") == 0:
    say "release-policy-check: missing micro_tznum_matmul_nn,bc in bench/perf_baseline_tznum.tnx"
    bad = 1
  if policy_file_has("bench/perf_baseline_tznum.tnx", "micro_tznum_rmsnorm_nn,bc") == 0:
    say "release-policy-check: missing micro_tznum_rmsnorm_nn,bc in bench/perf_baseline_tznum.tnx"
    bad = 1
  if policy_path_exists("tools/tznum_native_parity_gate.sh") == 0:
    say "release-policy-check: missing tools/tznum_native_parity_gate.sh"
    bad = 1
  if policy_path_exists("tools/tznum_perf_gate.sh") == 0:
    say "release-policy-check: missing tools/tznum_perf_gate.sh"
    bad = 1
  if policy_path_exists("tools/runtime_io_gate.sh") == 0:
    say "release-policy-check: missing tools/runtime_io_gate.sh"
    bad = 1
  if policy_path_exists("tools/simple_mode_gate.sh") == 0:
    say "release-policy-check: missing tools/simple_mode_gate.sh"
    bad = 1
  if policy_path_exists("tools/startup_latency_gate.sh") == 0:
    say "release-policy-check: missing tools/startup_latency_gate.sh"
    bad = 1
  if policy_path_exists("tools/tier1_perf_gate.sh") == 0:
    say "release-policy-check: missing tools/tier1_perf_gate.sh"
    bad = 1
  if policy_path_exists("tools/build_core_strict.ps1") == 0:
    say "release-policy-check: missing tools/build_core_strict.ps1"
    bad = 1
  if policy_path_exists("tools/package_sdk.sh") == 0:
    say "release-policy-check: missing tools/package_sdk.sh"
    bad = 1
  if policy_path_exists("tools/package_sdk.ps1") == 0:
    say "release-policy-check: missing tools/package_sdk.ps1"
    bad = 1
  if policy_path_exists("tools/publish_download_bundle.sh") == 0:
    say "release-policy-check: missing tools/publish_download_bundle.sh"
    bad = 1
  if policy_path_exists("tools/publish_download_bundle.ps1") == 0:
    say "release-policy-check: missing tools/publish_download_bundle.ps1"
    bad = 1
  if policy_file_has("../.github/workflows/tezz-deploy.yml", "publish_download_bundle.sh") == 0:
    say "release-policy-check: missing download bundle staging in ../.github/workflows/tezz-deploy.yml"
    bad = 1
  if policy_path_exists("bin/tezz") == 0:
    say "release-policy-check: missing bin/tezz launcher"
    bad = 1
  if policy_path_exists("bin/tezz.cmd") == 0:
    say "release-policy-check: missing bin/tezz.cmd launcher"
    bad = 1
  if policy_path_exists("bin/tezz.ps1") == 0:
    say "release-policy-check: missing bin/tezz.ps1 launcher"
    bad = 1
  if policy_file_has("../.github/workflows/tezz-production-gates.yml", "bin/tezzc") == 0:
    say "release-policy-check: missing bin artifact upload in ../.github/workflows/tezz-production-gates.yml"
    bad = 1
  if policy_manifest_nonempty("web/tn_site/public/index.php") == 0:
    say "release-policy-check: empty web/tn_site/public/index.php"
    bad = 1
  if policy_file_has("../.github/workflows/tezz-production-gates.yml", "windows-latest") == 0:
    say "release-policy-check: missing Windows CI lane in ../.github/workflows/tezz-production-gates.yml"
    bad = 1
  if policy_file_has("../.github/workflows/tezz-production-gates.yml", "macos-") == 0:
    say "release-policy-check: missing macOS CI lane in ../.github/workflows/tezz-production-gates.yml"
    bad = 1
  if policy_file_has("../.github/workflows/tezz-production-gates.yml", "test --gui") == 0:
    say "release-policy-check: missing GUI lane in ../.github/workflows/tezz-production-gates.yml"
    bad = 1
  if policy_file_has("../.github/workflows/tezz-production-gates.yml", "SDL2") == 0:
    say "release-policy-check: missing SDL2 host-gui deps in ../.github/workflows/tezz-production-gates.yml"
    bad = 1
  if policy_file_has("../.github/workflows/tezz-runtime-io-gate.yml", "windows-latest") == 0:
    say "release-policy-check: missing Windows runtime lane in ../.github/workflows/tezz-runtime-io-gate.yml"
    bad = 1
  if policy_file_has("../.github/workflows/tezz-runtime-io-gate.yml", "macos-") == 0:
    say "release-policy-check: missing macOS runtime lane in ../.github/workflows/tezz-runtime-io-gate.yml"
    bad = 1
  if policy_file_has("../.github/workflows/tezz-runtime-io-gate.yml", "SDL2") == 0:
    say "release-policy-check: missing SDL2 host-gui deps in ../.github/workflows/tezz-runtime-io-gate.yml"
    bad = 1
  if policy_file_has("src/tnrt.c", "tn_fb_host_windowing") == 0:
    say "release-policy-check: missing host window runtime export in src/tnrt.c"
    bad = 1
  if policy_file_has("src/stdlib_tn.c", "fb_host_windowing") == 0:
    say "release-policy-check: missing host window VM builtin in src/stdlib_tn.c"
    bad = 1
  if policy_file_has("lib/gui.tn", "gui_ime_active") == 0:
    say "release-policy-check: missing IME state API in lib/gui.tn"
    bad = 1
  if policy_file_has("lib/wm.tn", "wm_begin_frame") == 0:
    say "release-policy-check: missing compositor lifecycle API in lib/wm.tn"
    bad = 1
  if policy_file_has("lib/tnui.tn", "slider(") == 0:
    say "release-policy-check: missing native slider control in lib/tnui.tn"
    bad = 1
  if policy_path_exists("examples/gui_first_app.tn") == 0:
    say "release-policy-check: missing examples/gui_first_app.tn"
    bad = 1
  if policy_file_has("tezz.mod", "dep.tnui = 0.1.0") == 0:
    say "release-policy-check: missing dep.tnui in tezz.mod"
    bad = 1
  if policy_file_has("tezz.mod", "dep.tkui") != 0:
    say "release-policy-check: legacy dep.tkui found in tezz.mod"
    bad = 1
  if policy_manifest_nonempty("tests/conformance_fail_manifest.tnx") == 0:
    say "release-policy-check: empty tests/conformance_fail_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/conformance_ast_manifest.tnx") == 0:
    say "release-policy-check: empty tests/conformance_ast_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/conformance_ir_manifest.tnx") == 0:
    say "release-policy-check: empty tests/conformance_ir_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/conformance_diag_manifest.tnx") == 0:
    say "release-policy-check: empty tests/conformance_diag_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/fmt_manifest.tnx") == 0:
    say "release-policy-check: empty tests/fmt_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/lint_manifest.tnx") == 0:
    say "release-policy-check: empty tests/lint_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/borrow_manifest.tnx") == 0:
    say "release-policy-check: empty tests/borrow_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/attr_manifest.tnx") == 0:
    say "release-policy-check: empty tests/attr_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/abi_manifest.tnx") == 0:
    say "release-policy-check: empty tests/abi_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/ir_manifest.tnx") == 0:
    say "release-policy-check: empty tests/ir_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/error_manifest.tnx") == 0:
    say "release-policy-check: empty tests/error_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/buildexe_manifest.tnx") == 0:
    say "release-policy-check: empty tests/buildexe_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/buildexe_elf_manifest.tnx") == 0:
    say "release-policy-check: empty tests/buildexe_elf_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/buildexe_macho_manifest.tnx") == 0:
    say "release-policy-check: empty tests/buildexe_macho_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/buildexe_x86_manifest.tnx") == 0:
    say "release-policy-check: empty tests/buildexe_x86_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/runtime_soak_manifest.tnx") == 0:
    say "release-policy-check: empty tests/runtime_soak_manifest.tnx"
    bad = 1
  if policy_file_has("tests/runtime_hardening_manifest.tnx", "tests/runtime_call_multiarg.tn") == 0:
    say "release-policy-check: missing tests/runtime_call_multiarg.tn in tests/runtime_hardening_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/os_freestanding_manifest.tnx") == 0:
    say "release-policy-check: empty tests/os_freestanding_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/bcvm_manifest.tnx") == 0:
    say "release-policy-check: empty tests/bcvm_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/gui_manifest.tnx") == 0:
    say "release-policy-check: empty tests/gui_manifest.tnx"
    bad = 1
  if policy_manifest_nonempty("tests/gui_check_manifest.tnx") == 0:
    say "release-policy-check: empty tests/gui_check_manifest.tnx"
    bad = 1
  if policy_file_has("tests/gui_manifest.tnx", "tests/gui_window_smoke.tn") == 0:
    say "release-policy-check: missing tests/gui_window_smoke.tn in tests/gui_manifest.tnx"
    bad = 1
  if policy_file_has("tests/gui_manifest.tnx", "tests/gui_wm_runtime.tn") == 0:
    say "release-policy-check: missing tests/gui_wm_runtime.tn in tests/gui_manifest.tnx"
    bad = 1
  if policy_file_has("tests/gui_check_manifest.tnx", "tests/gui_tnui_controls_compile.tn") == 0:
    say "release-policy-check: missing tests/gui_tnui_controls_compile.tn in tests/gui_check_manifest.tnx"
    bad = 1
  if policy_file_has("tests/gui_check_manifest.tnx", "examples/gui_first_app.tn") == 0:
    say "release-policy-check: missing examples/gui_first_app.tn in tests/gui_check_manifest.tnx"
    bad = 1

  if bad == 0:
    say "release-policy-check: OK"
    ret 0
  say "release-policy-check: FAILED"
  ret 0 - 1

fn cmd_release() -> int:
  // V1 gate: strict conformance + stdlib/tooling + lint + runtime lanes + verify
  // M6 gate: signed release artifacts + reproducible compiler build check.
  // TZNUM gate: native parity + matmul/rmsnorm benchmark blockers.
  osn:str = os_name()
  runner:str = "tezz"
  if streq(osn, "windows"):
    if path_exists(".\\tezz.cmd") != 0:
      runner = ".\\tezz.cmd"
    else:
      runner = "tezz.cmd"
  else:
    if path_exists("./tezz") != 0:
      runner = "./tezz"

  failed:int = 0
  cmd_tc:str = str_join3(runner, " ", "test --conformance --conformance-strict")
  if proc_run(cmd_tc) != 0:
    failed = 1
  free(cmd_tc)

  cmd_ts:str = str_join3(runner, " ", "test --stdlib-v1")
  if proc_run(cmd_ts) != 0:
    failed = 1
  free(cmd_ts)

  cmd_tl:str = str_join3(runner, " ", "test --tooling")
  if proc_run(cmd_tl) != 0:
    failed = 1
  free(cmd_tl)

  cmd_tg:str = str_join3(runner, " ", "test --gui")
  if proc_run(cmd_tg) != 0:
    failed = 1
  free(cmd_tg)

  // Lint smoke gate (run early before long runtime lanes).
  cmd1:str = str_join3(runner, " ", "lint tests/lint_smoke.tn")
  if proc_run(cmd1) != 0:
    failed = 1
  free(cmd1)

  cmd2:str = str_join3(runner, " ", "lint tests/lint_suppress.tn")
  if proc_run(cmd2) != 0:
    failed = 1
  free(cmd2)

  // Runtime IO stability gate (release blocker).
  cmd_io:str = str_join3(runner, " ", "test --io-smoke")
  if proc_run(cmd_io) != 0:
    failed = 1
  free(cmd_io)

  cmd_sm:str = str_join3(runner, " ", "test --simple-smoke")
  if proc_run(cmd_sm) != 0:
    failed = 1
  free(cmd_sm)

  cmd_rh:str = str_join3(runner, " ", "test --runtime-hardening")
  if proc_run(cmd_rh) != 0:
    failed = 1
  free(cmd_rh)

  cmd_rf:str = str_join3(runner, " ", "test --runtime-fuzz --fuzz-rounds 2 --fuzz-iters 256")
  if proc_run(cmd_rf) != 0:
    failed = 1
  free(cmd_rf)

  cmd_v:str = str_join3(runner, " ", "verify --strict")
  if proc_run(cmd_v) != 0:
    failed = 1
  free(cmd_v)

  rel_sign_key:str = release_sign_key()
  has_rel_sign_key:int = 0
  if rel_sign_key != 0:
    if rel_sign_key[0] != 0:
      has_rel_sign_key = 1
  if has_rel_sign_key == 0:
    say "release: missing signing key for signed artifacts"
    say "set TEZZ_RELEASE_SIGN_KEY (or TEZZ_SIGN_KEY) or create build/release_sign.key"
    failed = 1
  else:
    ensure_dir("build")
    io.write_all("build/release_sign.key", rel_sign_key)
    cmd_ra:str = str_join3(runner, " ", "release-artifacts --verify-repro --require-sign --sign-key-file build/release_sign.key")
    if proc_run(cmd_ra) != 0:
      failed = 1
    free(cmd_ra)
  if rel_sign_key != 0:
    free(rel_sign_key)

  cmd_rc:str = str_join3(runner, " ", "reprocheck")
  if proc_run(cmd_rc) != 0:
    failed = 1
  free(cmd_rc)

  cmd_rp:str = str_join3(runner, " ", "release-policy-check")
  if proc_run(cmd_rp) != 0:
    failed = 1
  free(cmd_rp)

  if path_exists("tools/m6_perf_gate.sh") == 0:
    say "release: missing tools/m6_perf_gate.sh"
    failed = 1
  else:
    cmd_pg:str = str_join2("bash tools/m6_perf_gate.sh", "")
    if proc_run(cmd_pg) != 0:
      failed = 1
    free(cmd_pg)

  if path_exists("tools/tznum_perf_gate.sh") == 0:
    say "release: missing tools/tznum_perf_gate.sh"
    failed = 1
  else:
    cmd_tzpg:str = str_join2("bash tools/tznum_perf_gate.sh", "")
    if proc_run(cmd_tzpg) != 0:
      failed = 1
    free(cmd_tzpg)

  if failed == 0:
    say "release: OK"
    ret 0
  say "release: FAILED"
  ret 0 - 1

fn cmd_fmt() -> int:
  if user_args_count() >= 2:
    a0:str = arg(1)
    if streq(a0, "--help") || streq(a0, "-h"):
      print_usage_fmt()
      ret 0
  if user_args_count() < 2:
    print_usage_fmt()
    ret 0 - 1
  path:str = arg(1)
  os:str = os_name()
  exe_suffix:str = ""
  if streq(os, "windows"):
    exe_suffix = ".exe"
  tezzc:str = tezzc_path()
  cmd1:str = str_join3(tezzc, " fmt ", path)
  r:int = proc_run(cmd1)
  free(cmd1)
  ret r

fn cmd_lint() -> int:
  if user_args_count() >= 2:
    a0:str = arg(1)
    if streq(a0, "--help") || streq(a0, "-h"):
      print_usage_lint()
      ret 0
  if user_args_count() < 2:
    print_usage_lint()
    ret 0 - 1
  path:str = arg(1)
  os:str = os_name()
  exe_suffix:str = ""
  if streq(os, "windows"):
    exe_suffix = ".exe"
  tezzc:str = tezzc_path()
  cmd1:str = str_join3(tezzc, " lint ", path)
  r:int = proc_run(cmd1)
  free(cmd1)
  ret r

fn cmd_manifest() -> int:
  mod:str = io.read_all("tezz.mod")
  if mod == 0:
    say "missing tezz.mod"
    ret 0 - 1

  name:str = mod_get_value(mod, "name")
  ver:str = mod_get_value(mod, "version")
  root:str = project_module_root(mod)

  names:[str;64]
  vers:[str;64]
  dep_n:int = 0

  i:int = 0
  line:int = 0
  while 1:
    c:int = mod[i] as int
    if c == 0 || c == 10:
      end:int = i
      s:int = line
      while s < end && (mod[s] == 32 || mod[s] == 9):
        s = s + 1
      if starts_with_at(mod, s, "dep.") != 0:
        s = s + 4
        ns:int = s
        while s < end && mod[s] != 32 && mod[s] != 9 && mod[s] != 61:
          s = s + 1
        ne:int = s
        while s < end && mod[s] != 61:
          s = s + 1
        if s < end && mod[s] == 61:
          s = s + 1
          while s < end && (mod[s] == 32 || mod[s] == 9):
            s = s + 1
          vs:int = s
          ve:int = end
          while ve > vs && (mod[ve-1] == 32 || mod[ve-1] == 9 || mod[ve-1] == 13):
            ve = ve - 1
          if dep_n < 64:
            names[dep_n] = substr_dup(mod, ns, ne)
            vers[dep_n] = substr_dup(mod, vs, ve)
            dep_n = dep_n + 1
      if c == 0:
        break
      line = i + 1
    i = i + 1

  lines:[str;128]
  line_n:int = 0
  j:int = 0

  i = 0
  while i < dep_n:
    dep_path:str = dep_module_path(root, names[i])
    data:str = io.read_all(dep_path)
    if data == 0:
      say "missing lib file: "
      say dep_path
      free(dep_path)
      ret 0 - 1
    free(data)
    nv:str = str_join3(names[i], "@", vers[i])
    lines[line_n] = nv
    line_n = line_n + 1
    free(dep_path)
    i = i + 1

  // sort lines for determinism
  a:int = 0
  while a < line_n:
    b:int = a + 1
    while b < line_n:
      if strcmp(lines[a], lines[b]) > 0:
        tmp:str = lines[a]
        lines[a] = lines[b]
        lines[b] = tmp
      b = b + 1
    a = a + 1

  ensure_dir("build")

  total:int = 0
  if name != 0:
    total = total + len("name = ") + len(name) + 1
  if ver != 0:
    total = total + len("version = ") + len(ver) + 1
  if root != 0:
    total = total + len("module_root = ") + len(root) + 1

  i = 0
  while i < line_n:
    total = total + len(lines[i]) + 1
    i = i + 1

  out:*char = (*char)malloc(total + 1)
  w:int = 0
  if name != 0:
    pre:str = "name = "
    j = 0
    while pre[j] != 0:
      out[w] = pre[j]
      w = w + 1
      j = j + 1
    j = 0
    while name[j] != 0:
      out[w] = name[j]
      w = w + 1
      j = j + 1
    out[w] = 10 as char
    w = w + 1
  if ver != 0:
    pre2:str = "version = "
    j = 0
    while pre2[j] != 0:
      out[w] = pre2[j]
      w = w + 1
      j = j + 1
    j = 0
    while ver[j] != 0:
      out[w] = ver[j]
      w = w + 1
      j = j + 1
    out[w] = 10 as char
    w = w + 1
  if root != 0:
    pre3:str = "module_root = "
    j = 0
    while pre3[j] != 0:
      out[w] = pre3[j]
      w = w + 1
      j = j + 1
    j = 0
    while root[j] != 0:
      out[w] = root[j]
      w = w + 1
      j = j + 1
    out[w] = 10 as char
    w = w + 1

  i = 0
  while i < line_n:
    j = 0
    while lines[i][j] != 0:
      out[w] = lines[i][j]
      w = w + 1
      j = j + 1
    out[w] = 10 as char
    w = w + 1
    i = i + 1

  out[w] = 0 as char
  io.write_all("build/tezz.manifest", out)

  free(out)
  i = 0
  while i < line_n:
    free(lines[i])
    i = i + 1
  if name != 0:
    free(name)
  if ver != 0:
    free(ver)
  if root != 0:
    free(root)
  i = 0
  while i < dep_n:
    free(names[i])
    free(vers[i])
    i = i + 1
  free(mod)
  ret 0

fn write_lock(out_path:str) -> int:
  mod:str = io.read_all("tezz.mod")
  if mod == 0:
    say "missing tezz.mod"
    ret 0 - 1

  root:str = project_module_root(mod)
  reglib:str = mod_get_value(mod, "registry_lib")
  reg:str = 0 as str
  base:str = reglib
  own_base:int = 0
  if base == 0:
    reg = mod_get_value(mod, "registry")
    if reg != 0:
      base = url_dir(reg)
      own_base = 1
  if base == 0:
    base = "https://tn.tezzcorp.com/lib/"
    own_base = 0

  names:[str;64]
  vers:[str;64]
  dep_n:int = 0

  i:int = 0
  line:int = 0
  while 1:
    c:int = mod[i] as int
    if c == 0 || c == 10:
      end:int = i
      s:int = line
      while s < end && (mod[s] == 32 || mod[s] == 9):
        s = s + 1
      if starts_with_at(mod, s, "dep.") != 0:
        s = s + 4
        ns:int = s
        while s < end && mod[s] != 32 && mod[s] != 9 && mod[s] != 61:
          s = s + 1
        ne:int = s
        while s < end && mod[s] != 61:
          s = s + 1
        if s < end && mod[s] == 61:
          s = s + 1
          while s < end && (mod[s] == 32 || mod[s] == 9):
            s = s + 1
          vs:int = s
          ve:int = end
          while ve > vs && (mod[ve-1] == 32 || mod[ve-1] == 9 || mod[ve-1] == 13):
            ve = ve - 1
          if dep_n < 64:
            names[dep_n] = substr_dup(mod, ns, ne)
            vers[dep_n] = substr_dup(mod, vs, ve)
            dep_n = dep_n + 1
      if c == 0:
        break
      line = i + 1
    i = i + 1

  lines:[str;128]
  line_n:int = 0

  i = 0
  while i < dep_n:
    dep_path:str = dep_module_path(root, names[i])
    data:str = io.read_all(dep_path)
    if data == 0:
      say "missing lib file: "
      say dep_path
      free(dep_path)
      ret 0 - 1
    free(data)
    crc:int = crc32_source_file(dep_path)
    crc_hex:str = hex8(crc)
    crc_owned:int = 1
    if crc_hex == 0:
      crc_hex = "00000000"
      crc_owned = 0

    base2:str = base
    own_base2:int = 0
    bl:int = len(base)
    if bl > 0 && base[bl-1] != 47:
      base2 = str_join2(base, "/")
      own_base2 = 1
    url1:str = str_join2(base2, names[i])
    url2:str = str_join2(url1, ".tn")

    nv:str = str_join3(names[i], "@", vers[i])
    line1:str = str_join2(nv, " ")
    line2:str = str_join2(line1, crc_hex)
    line3:str = str_join2(line2, " ")
    line4:str = str_join2(line3, url2)
    lines[line_n] = line4
    line_n = line_n + 1

    free(dep_path)
    if crc_owned != 0:
      free(crc_hex)
    free(url1)
    free(url2)
    free(nv)
    free(line1)
    free(line2)
    free(line3)
    if own_base2 != 0:
      free(base2)
    i = i + 1

  // sort lines for determinism
  a:int = 0
  while a < line_n:
    b:int = a + 1
    while b < line_n:
      if strcmp(lines[a], lines[b]) > 0:
        tmp:str = lines[a]
        lines[a] = lines[b]
        lines[b] = tmp
      b = b + 1
    a = a + 1

  total:int = 0
  i = 0
  while i < line_n:
    total = total + len(lines[i]) + 1
    i = i + 1
  out:*char = (*char)malloc(total + 1)
  w:int = 0
  i = 0
  while i < line_n:
    j:int = 0
    while lines[i][j] != 0:
      out[w] = lines[i][j]
      w = w + 1
      j = j + 1
    out[w] = 10 as char
    w = w + 1
    i = i + 1
  out[w] = 0 as char

  meta:str = provenance_meta_line("lock-meta", out, line_n)
  full:str = str_join3(meta, "\n", out)
  io.write_all(out_path, full)
  free(full)
  free(meta)
  free(out)
  i = 0
  while i < line_n:
    free(lines[i])
    i = i + 1
  i = 0
  while i < dep_n:
    free(names[i])
    free(vers[i])
    i = i + 1
  if own_base != 0 && base != 0:
    free(base)
  if reglib != 0:
    free(reglib)
  if reg != 0:
    free(reg)
  if root != 0:
    free(root)
  free(mod)
  ret 0

fn cmd_lock() -> int:
  ret write_lock("tezz.lock")

fn write_registry(out_path:str) -> int:
  mod:str = io.read_all("tezz.mod")
  if mod == 0:
    say "missing tezz.mod"
    ret 0 - 1

  root:str = project_module_root(mod)
  reglib:str = mod_get_value(mod, "registry_lib")
  reg:str = 0 as str
  base:str = reglib
  own_base:int = 0
  if base == 0:
    reg = mod_get_value(mod, "registry")
    if reg != 0:
      base = url_dir(reg)
      own_base = 1
  if base == 0:
    base = "https://tn.tezzcorp.com/lib/"
    own_base = 0

  names:[str;64]
  vers:[str;64]
  dep_n:int = 0

  i:int = 0
  line:int = 0
  while 1:
    c:int = mod[i] as int
    if c == 0 || c == 10:
      end:int = i
      s:int = line
      while s < end && (mod[s] == 32 || mod[s] == 9):
        s = s + 1
      if starts_with_at(mod, s, "dep.") != 0:
        s = s + 4
        ns:int = s
        while s < end && mod[s] != 32 && mod[s] != 9 && mod[s] != 61:
          s = s + 1
        ne:int = s
        while s < end && mod[s] != 61:
          s = s + 1
        if s < end && mod[s] == 61:
          s = s + 1
          while s < end && (mod[s] == 32 || mod[s] == 9):
            s = s + 1
          vs:int = s
          ve:int = end
          while ve > vs && (mod[ve-1] == 32 || mod[ve-1] == 9 || mod[ve-1] == 13):
            ve = ve - 1
          if dep_n < 64:
            names[dep_n] = substr_dup(mod, ns, ne)
            vers[dep_n] = substr_dup(mod, vs, ve)
            dep_n = dep_n + 1
      if c == 0:
        break
      line = i + 1
    i = i + 1

  lines:[str;128]
  line_n:int = 0

  i = 0
  while i < dep_n:
    dep_path:str = dep_module_path(root, names[i])
    crc:int = crc32_source_file(dep_path)
    crc_hex:str = hex8(crc)

    base2:str = base
    own_base2:int = 0
    bl:int = len(base)
    if bl > 0 && base[bl-1] != 47:
      base2 = str_join2(base, "/")
      own_base2 = 1
    url1:str = str_join2(base2, names[i])
    url2:str = str_join2(url1, ".tn")

    nv:str = str_join3(names[i], "@", vers[i])
    line1:str = str_join2(nv, " ")
    line2:str = str_join2(line1, url2)
    line3:str = str_join2(line2, " ")
    line4:str = str_join2(line3, crc_hex)
    lines[line_n] = line4
    line_n = line_n + 1

    free(dep_path)
    free(crc_hex)
    free(url1)
    free(url2)
    free(nv)
    free(line1)
    free(line2)
    free(line3)
    if own_base2 != 0:
      free(base2)
    i = i + 1

  // sort lines for determinism
  a:int = 0
  while a < line_n:
    b:int = a + 1
    while b < line_n:
      if strcmp(lines[a], lines[b]) > 0:
        tmp:str = lines[a]
        lines[a] = lines[b]
        lines[b] = tmp
      b = b + 1
    a = a + 1

  ensure_dir("build")

  total:int = 0
  i = 0
  while i < line_n:
    total = total + len(lines[i]) + 1
    i = i + 1

  out:*char = (*char)malloc(total + 1)
  w:int = 0
  i = 0
  while i < line_n:
    j:int = 0
    while lines[i][j] != 0:
      out[w] = lines[i][j]
      w = w + 1
      j = j + 1
    out[w] = 10 as char
    w = w + 1
    i = i + 1
  out[w] = 0 as char

  meta:str = provenance_meta_line("registry-meta", out, line_n)
  full:str = str_join3(meta, "\n", out)
  io.write_all(out_path, full)
  free(full)
  free(meta)
  free(out)
  i = 0
  while i < line_n:
    free(lines[i])
    i = i + 1
  i = 0
  while i < dep_n:
    free(names[i])
    free(vers[i])
    i = i + 1
  if own_base != 0 && base != 0:
    free(base)
  if reglib != 0:
    free(reglib)
  if reg != 0:
    free(reg)
  if root != 0:
    free(root)
  free(mod)
  ret 0

fn append_buf_str(out:*char, w:int, s:str) -> int:
  if out == 0 || s == 0:
    ret w
  j:int = 0
  while s[j] != 0:
    out[w] = s[j]
    w = w + 1
    j = j + 1
  ret w

fn write_registry_for_publish(out_path:str) -> int:
  mod:str = io.read_all("tezz.mod")
  if mod == 0:
    say "missing tezz.mod"
    ret 0 - 1

  root:str = project_module_root(mod)
  reglib:str = mod_get_value(mod, "registry_lib")
  reg:str = 0 as str
  base:str = reglib
  own_base:int = 0
  if base == 0:
    reg = mod_get_value(mod, "registry")
    if reg != 0:
      base = url_dir(reg)
      own_base = 1
  if base == 0:
    base = "https://tn.tezzcorp.com/lib/"
    own_base = 0

  ensure_dir("build")
  cap:int = 262144
  out:*char = (*char)malloc(cap)
  if out == 0:
    ret 0 - 1

  w:int = 0
  line_n:int = 0
  i:int = 0
  line:int = 0
  while 1:
    c:int = mod[i] as int
    if c == 0 || c == 10:
      end:int = i
      s:int = line
      while s < end && (mod[s] == 32 || mod[s] == 9):
        s = s + 1
      if starts_with_at(mod, s, "dep.") != 0:
        s = s + 4
        ns:int = s
        while s < end && mod[s] != 32 && mod[s] != 9 && mod[s] != 61:
          s = s + 1
        ne:int = s
        while s < end && mod[s] != 61:
          s = s + 1
        if s < end && mod[s] == 61:
          s = s + 1
          while s < end && (mod[s] == 32 || mod[s] == 9):
            s = s + 1
          vs:int = s
          ve:int = end
          while ve > vs && (mod[ve-1] == 32 || mod[ve-1] == 9 || mod[ve-1] == 13):
            ve = ve - 1
          name:str = substr_dup(mod, ns, ne)
          ver:str = substr_dup(mod, vs, ve)
          dep_path:str = dep_module_path(root, name)
          crc:int = crc32_source_file(dep_path)
          crc_hex:str = hex8(crc)
          base2:str = base
          own_base2:int = 0
          bl:int = len(base)
          if bl > 0 && base[bl-1] != 47:
            base2 = str_join2(base, "/")
            own_base2 = 1
          url1:str = str_join2(base2, name)
          url2:str = str_join2(url1, ".tn")

          w = append_buf_str(out, w, name)
          out[w] = 64 as char
          w = w + 1
          w = append_buf_str(out, w, ver)
          out[w] = 32 as char
          w = w + 1
          w = append_buf_str(out, w, url2)
          out[w] = 32 as char
          w = w + 1
          w = append_buf_str(out, w, crc_hex)
          out[w] = 10 as char
          w = w + 1
          line_n = line_n + 1

          free(name)
          free(ver)
          free(dep_path)
          free(crc_hex)
          free(url1)
          free(url2)
          if own_base2 != 0:
            free(base2)
      if c == 0:
        break
      line = i + 1
    i = i + 1
  out[w] = 0 as char

  meta:str = provenance_meta_line("registry-meta", out, line_n)
  full:str = str_join3(meta, "\n", out)
  io.write_all(out_path, full)
  free(full)
  free(meta)
  free(out)
  if own_base != 0 && base != 0:
    free(base)
  if reglib != 0:
    free(reglib)
  if reg != 0:
    free(reg)
  if root != 0:
    free(root)
  free(mod)
  ret 0

fn cmd_registry() -> int:
  out_path:str = "build/registry.tnx"
  if user_args_count() >= 2:
    out_path = arg(1)
  ret write_registry(out_path)

fn cmd_publish() -> int:
  if path_exists("tezz.mod") == 0:
    say "publish: missing tezz.mod"
    ret 0 - 1
  if path_exists("tezz.lock") == 0:
    say "publish: missing tezz.lock (run: tezz lock)"
    ret 0 - 1

  publish_out:str = "build/registry.tnx"
  publish_out_owned:int = 0
  if user_args_count() >= 2:
    publish_out = str_join2("", arg(1))
    publish_out_owned = 1
  registry_rc:int = write_registry_for_publish(publish_out)
  if registry_rc != 0:
    if path_exists(publish_out) == 0:
      if publish_out_owned != 0:
        free(publish_out)
      say "publish: registry metadata generation failed"
      ret 0 - 1
  if publish_out_owned != 0:
    free(publish_out)
  say "publish: registry metadata ready"
  ret 0

fn cmd_verify() -> int:
  strict:int = 0
  ai:int = 1
  ucnt:int = user_args_count()
  while ai < ucnt:
    a0:str = arg(ai)
    if streq(a0, "--strict"):
      strict = 1
      ai = ai + 1
      continue
    if streq(a0, "--help") || streq(a0, "-h"):
      print_usage_verify()
      ret 0
    if starts_with(a0, "--") != 0:
      p0:str = str_join2("verify: unknown option: ", a0)
      say p0
      free(p0)
      print_usage_verify()
      ret 0 - 1
    ai = ai + 1

  lock:str = io.read_all("tezz.lock")
  if lock == 0:
    say "missing tezz.lock"
    ret 0 - 1

  mod:str = io.read_all("tezz.mod")
  root:str = project_module_root(mod)
  bad:int = 0

  dep_names:[str;128]
  dep_vers:[str;128]
  dep_n:int = 0
  if mod != 0:
    i2:int = 0
    line2:int = 0
    while 1:
      c2:int = mod[i2] as int
      if c2 == 0 || c2 == 10:
        end2:int = i2
        s2:int = line2
        while s2 < end2 && (mod[s2] == 32 || mod[s2] == 9):
          s2 = s2 + 1
        if starts_with_at(mod, s2, "dep.") != 0:
          s2 = s2 + 4
          ns2:int = s2
          while s2 < end2 && mod[s2] != 32 && mod[s2] != 9 && mod[s2] != 61:
            s2 = s2 + 1
          ne2:int = s2
          while s2 < end2 && mod[s2] != 61:
            s2 = s2 + 1
          if s2 < end2 && mod[s2] == 61:
            s2 = s2 + 1
            while s2 < end2 && (mod[s2] == 32 || mod[s2] == 9):
              s2 = s2 + 1
            vs2:int = s2
            ve2:int = end2
            while ve2 > vs2 && (mod[ve2-1] == 32 || mod[ve2-1] == 9 || mod[ve2-1] == 13):
              ve2 = ve2 - 1
            if dep_n < 128:
              dep_names[dep_n] = substr_dup(mod, ns2, ne2)
              dep_vers[dep_n] = substr_dup(mod, vs2, ve2)
              dep_n = dep_n + 1
        if c2 == 0:
          break
        line2 = i2 + 1
      i2 = i2 + 1

  prov_base:str = 0 as str
  prov_base_norm:str = 0 as str
  prov_base_owned:int = 0
  prov_base_norm_owned:int = 0
  if strict != 0 && mod != 0:
    reglib0:str = mod_get_value(mod, "registry_lib")
    reglib_ok:int = 0
    if reglib0 != 0:
      if reglib0[0] != 0:
        reglib_ok = 1
    if reglib_ok != 0:
      prov_base = str_join2(reglib0, "")
      prov_base_owned = 1
    else:
      reg0:str = mod_get_value(mod, "registry")
      reg_ok:int = 0
      if reg0 != 0:
        if reg0[0] != 0:
          reg_ok = 1
      if reg_ok != 0:
        prov_base = url_dir(reg0)
        prov_base_owned = 1
      if reg0 != 0:
        free(reg0)
    if reglib0 != 0:
      free(reglib0)
    if prov_base == 0:
      prov_base = str_join2("https://tn.tezzcorp.com/lib/", "")
      prov_base_owned = 1
    prov_base_norm = prov_base
    if prov_base_norm != 0:
      bl:int = len(prov_base_norm)
      if bl > 0 && prov_base_norm[bl - 1] != 47:
        prov_base_norm = str_join2(prov_base_norm, "/")
        prov_base_norm_owned = 1

  lock_nv:[str;256]
  lock_n:int = 0
  prev_line:str = 0 as str
  payload:str = str_join2("", "")
  payload_n:int = 0
  meta_seen:int = 0
  meta_lines:int = 0 - 1
  meta_payload:str = 0 as str
  meta_key:str = 0 as str
  meta_sig:str = 0 as str

  i:int = 0
  line_start:int = 0
  while 1:
    c:int = lock[i] as int
    if c == 0 || c == 10:
      line_end:int = i
      if line_end > line_start:
        if lock[line_end - 1] == (13 as char):
          line_end = line_end - 1

      s:int = line_start
      while s < line_end && is_space(lock[s] as int) != 0:
        s = s + 1

      if s < line_end:
        line:str = substr_dup(lock, s, line_end)
        if line != 0 && line[0] != 0:
          if (line[0] as int) == 35:
            if strict != 0 && starts_with_at(line, 0, "# lock-meta v1 ") != 0:
              if meta_seen != 0:
                say "duplicate lock metadata line"
                bad = bad + 1
              else:
                mv_lines:str = meta_find_value(line, "lines=")
                mv_payload:str = meta_find_value(line, "payload=")
                mv_key:str = meta_find_value(line, "key=")
                mv_sig:str = meta_find_value(line, "sig=")
                if mv_key == 0:
                  mv_key = dup_lit("none")
                if mv_sig == 0:
                  mv_sig = dup_lit("none")
                if mv_lines == 0 || mv_payload == 0:
                  say "malformed lock metadata line"
                  bad = bad + 1
                  if mv_lines != 0:
                    free(mv_lines)
                  if mv_payload != 0:
                    free(mv_payload)
                  if mv_key != 0:
                    free(mv_key)
                  if mv_sig != 0:
                    free(mv_sig)
                else:
                  meta_seen = 1
                  meta_lines = parse_i64(mv_lines)
                  meta_payload = mv_payload
                  meta_key = mv_key
                  meta_sig = mv_sig
                  free(mv_lines)
          else:
            if strict != 0:
              cur_line:str = str_join2(line, "")
              if prev_line != 0 && strcmp(prev_line, cur_line) > 0:
                say "lock order violation:"
                say cur_line
                bad = bad + 1
              if prev_line != 0:
                free(prev_line)
              prev_line = cur_line

            a:int = 0
            while line[a] != 0 && is_space(line[a] as int) == 0:
              a = a + 1
            namever:str = substr_dup(line, 0, a)
            while line[a] != 0 && is_space(line[a] as int) != 0:
              a = a + 1
            b:int = a
            while line[b] != 0 && is_space(line[b] as int) == 0:
              b = b + 1
            checksum:str = substr_dup(line, a, b)
            while line[b] != 0 && is_space(line[b] as int) != 0:
              b = b + 1
            u:int = b
            while line[u] != 0 && is_space(line[u] as int) == 0:
              u = u + 1
            url:str = substr_dup(line, b, u)
            while line[u] != 0 && is_space(line[u] as int) != 0:
              u = u + 1

            malformed:int = 0
            if len(namever) == 0:
              malformed = 1
            if len(checksum) == 0:
              malformed = 1
            if len(url) == 0:
              malformed = 1
            if line[u] != 0:
              malformed = 1
            if malformed != 0:
              say "malformed lock entry:"
              say line
              bad = bad + 1
            else:
              namebuf:[char;128]
              verbuf:[char;64]
              at_i:int = 0
              has_at:int = 0
              while namever[at_i] != 0:
                if (namever[at_i] as int) == 64:
                  has_at = 1
                  break
                at_i = at_i + 1
              if has_at == 0 || at_i <= 0:
                say "invalid lock package token:"
                say namever
                bad = bad + 1
              else:
                ni:int = 0
                while ni < at_i && ni < 127:
                  namebuf[ni] = namever[ni]
                  ni = ni + 1
                namebuf[ni] = 0 as char
                vi:int = 0
                si:int = at_i + 1
                while namever[si] != 0 && vi < 63:
                  verbuf[vi] = namever[si]
                  vi = vi + 1
                  si = si + 1
                verbuf[vi] = 0 as char
                if verbuf[0] == 0:
                  say "invalid lock package token:"
                  say namever
                  bad = bad + 1
                else:
                  if strict != 0:
                    can1:str = str_join2(namever, " ")
                    can2:str = str_join2(can1, checksum)
                    can3:str = str_join2(can2, " ")
                    can4:str = str_join2(can3, url)
                    payload2:str = str_join3(payload, can4, "\n")
                    free(payload)
                    payload = payload2
                    payload_n = payload_n + 1
                    free(can1)
                    free(can2)
                    free(can3)
                    free(can4)

                    nvcopy:str = str_join2(namever, "")
                    dup:int = 0
                    k0:int = 0
                    while k0 < lock_n:
                      if streq(lock_nv[k0], nvcopy) != 0:
                        dup = 1
                        break
                      k0 = k0 + 1
                    if dup != 0:
                      say "duplicate lock entry:"
                      say namever
                      bad = bad + 1
                      free(nvcopy)
                    else:
                      if lock_n < 256:
                        lock_nv[lock_n] = nvcopy
                        lock_n = lock_n + 1
                      else:
                        say "lock entry limit exceeded (256)"
                        bad = bad + 1
                        free(nvcopy)

                    prov_ok:int = 0
                    if prov_base_norm != 0:
                      if prov_base_norm[0] != 0:
                        prov_ok = 1
                    if prov_ok != 0:
                      if starts_with(url, prov_base_norm) == 0:
                        say "lock provenance URL mismatch:"
                        say namever
                        bad = bad + 1

                  if is_hex8(checksum) == 0:
                    say "invalid checksum format (expected 8 hex chars):"
                    say namever
                    bad = bad + 1
                  else:
                    lib_path:str = dep_module_path(root, namebuf)
                    legacy_path:str = str_join3("lib/", namebuf, ".tn")
                    cache1:str = str_join3(".tezz/cache/", namebuf, "-")
                    cache2:str = str_join2(cache1, verbuf)
                    cache:str = str_join2(cache2, ".tn")

                    use_path:str = 0 as str
                    if path_exists(lib_path) != 0:
                      use_path = lib_path
                    else:
                      if path_exists(legacy_path) != 0:
                        use_path = legacy_path
                      else:
                        if path_exists(cache) != 0:
                          use_path = cache

                    if use_path == 0:
                      say "missing dependency file:"
                      say namever
                      bad = bad + 1
                    else:
                      want:int = parse_hex(checksum)
                      have:int = crc32_source_file(use_path)
                      if have != want:
                        say "checksum mismatch:"
                        say namever
                        bad = bad + 1

                    free(lib_path)
                    free(legacy_path)
                    free(cache1)
                    free(cache2)
                    free(cache)

            free(namever)
            free(checksum)
            free(url)
        if line != 0:
          free(line)

      if c == 0:
        break
      line_start = i + 1
    i = i + 1

  if prev_line != 0:
    free(prev_line)

  if strict != 0:
    i = 0
    while i < dep_n:
      found_dep:int = 0
      j:int = 0
      while j < lock_n:
        if line_is_dep(lock_nv[j], dep_names[i], dep_vers[i]) != 0:
          found_dep = 1
          break
        j = j + 1
      if found_dep == 0:
        nv0:str = str_join3(dep_names[i], "@", dep_vers[i])
        say "missing lock entry for dep:"
        say nv0
        free(nv0)
        bad = bad + 1
      i = i + 1

    i = 0
    while i < lock_n:
      found_lock:int = 0
      j:int = 0
      while j < dep_n:
        if line_is_dep(lock_nv[i], dep_names[j], dep_vers[j]) != 0:
          found_lock = 1
          break
        j = j + 1
      if found_lock == 0:
        say "stale lock entry (not in tezz.mod deps):"
        say lock_nv[i]
        bad = bad + 1
      i = i + 1

    if meta_seen == 0:
      if starts_with_at(lock, 0, "# lock-meta v1 ") != 0:
        meta_seen = 1
        if meta_lines < 0:
          meta_lines = payload_n
        if meta_payload == 0:
          meta_payload = hex8(crc32_str(payload))
        if meta_key == 0:
          meta_key = dup_lit("none")
        if meta_sig == 0:
          meta_sig = dup_lit("none")
    if meta_seen == 0:
      say "missing lock provenance metadata (run: tezz lock)"
      bad = bad + 1
    else:
      if meta_lines < 0:
        meta_lines = payload_n
      else:
        if meta_lines == 0 && payload_n > 0:
          meta_lines = payload_n
      if meta_lines != payload_n:
        say "lock metadata line count mismatch"
        bad = bad + 1
      payload_ok:int = 0
      if meta_payload != 0:
        if is_hex8(meta_payload) != 0:
          payload_ok = 1
      if payload_ok == 0:
        say "invalid lock metadata payload checksum"
        bad = bad + 1
      if meta_key == 0 || meta_sig == 0:
        say "invalid lock metadata signature fields"
        bad = bad + 1
      else:
        key_none:int = streq(meta_key, "none")
        sig_none:int = streq(meta_sig, "none")
        if meta_key[0] == 0 as char:
          key_none = 1
        if meta_sig[0] == 0 as char:
          sig_none = 1
        if (key_none != 0 && sig_none == 0) || (key_none == 0 && sig_none != 0):
          say "invalid lock metadata signature mode"
          bad = bad + 1
        if sig_none == 0:
          khex_ok:int = is_hex8(meta_key)
          shex_ok:int = is_hex8(meta_sig)
          if khex_ok == 0 || shex_ok == 0:
            say "invalid lock metadata signature hex"
            bad = bad + 1
          else:
            sign_key2:str = env_value("TEZZ_SIGN_KEY")
            sk_ok:int = 0
            if sign_key2 != 0:
              if sign_key2[0] != 0:
                sk_ok = 1
            if sk_ok == 0:
              say "missing TEZZ_SIGN_KEY for signed lock verification"
              bad = bad + 1
            else:
              key_id2:str = hex8(crc32_str(sign_key2))
              if streq(meta_key, key_id2) == 0:
                say "lock signature key_id mismatch"
                bad = bad + 1
              sig2:str = meta_signature_hex(meta_payload, payload_n, sign_key2)
              if streq(meta_sig, sig2) == 0:
                say "lock signature mismatch"
                bad = bad + 1
              free(key_id2)
              free(sig2)
            if sign_key2 != 0:
              free(sign_key2)
      if meta_payload != 0 && is_hex8(meta_payload) != 0:
        payload_hex2:str = hex8(crc32_str(payload))
        if streq(meta_payload, payload_hex2) == 0:
          say "lock payload checksum mismatch"
          bad = bad + 1
        free(payload_hex2)

  i = 0
  while i < lock_n:
    free(lock_nv[i])
    i = i + 1
  i = 0
  while i < dep_n:
    free(dep_names[i])
    free(dep_vers[i])
    i = i + 1
  if meta_payload != 0:
    free(meta_payload)
  if meta_key != 0:
    free(meta_key)
  if meta_sig != 0:
    free(meta_sig)
  if payload != 0:
    free(payload)
  if prov_base_norm_owned != 0 && prov_base_norm != 0:
    free(prov_base_norm)
  if prov_base_owned != 0 && prov_base != 0:
    free(prov_base)

  free(lock)
  if root != 0:
    free(root)
  if mod != 0:
    free(mod)

  if bad != 0:
    say "verify: FAILED"
    ret 0 - 1
  say "verify: OK"
  ret 0

fn default_platform() -> str:
  osn:str = os_name()
  if streq(osn, "windows"):
    ret "x86_64"
  if streq(osn, "linux"):
    ret "linux"
  if streq(osn, "macos"):
    ret "macos"
  ret "x86_64"

fn map_platform_arg(p:str) -> str:
  if p == 0:
    ret 0 as str
  if streq(p, "native"):
    ret default_platform()
  if streq(p, "windows") || streq(p, "win") || streq(p, "win64"):
    ret "x86_64"
  if streq(p, "linux") || streq(p, "gnu-linux"):
    ret "linux"
  if streq(p, "macos") || streq(p, "mac") || streq(p, "darwin") || streq(p, "osx"):
    ret "macos"
  if streq(p, "android"):
    ret "linux-arm64"
  if streq(p, "x64"):
    ret "x86_64"
  ret p

fn platform_supported(p:str) -> int:
  if p == 0 || p[0] == 0:
    ret 0
  if streq(p, "x86_64") || streq(p, "x86") || streq(p, "arm64"):
    ret 1
  if streq(p, "linux") || streq(p, "linux-arm64") || streq(p, "macos"):
    ret 1
  ret 0

fn startup_profile_emit() -> int:
  path:str = g_startup_profile_path
  lane:str = g_startup_profile_lane
  src_path:str = g_startup_profile_source
  platform:str = g_startup_profile_platform
  vectorize:int = g_startup_profile_vectorize
  pre_ms:int = g_startup_profile_pre_ms
  exec_ms:int = g_startup_profile_exec_ms
  total_ms:int = g_startup_profile_total_ms
  rc:int = g_startup_profile_rc
  if path == 0 || path[0] == 0:
    path = "build/startup_profile.tnx"
  ensure_dir("build")
  if path_exists(path) == 0:
    io.write_all(path, "ts_ms,lane,source,platform,vectorize,pre_ms,exec_ms,total_ms,rc\n")
  ts:str = int_to_str(time.now_ms())
  vz:str = int_to_str(vectorize)
  p0:str = int_to_str(pre_ms)
  p1:str = int_to_str(exec_ms)
  p2:str = int_to_str(total_ms)
  rc_s:str = int_to_str(rc)
  c0:str = str_join3(ts, ",", lane)
  c1:str = str_join3(c0, ",", src_path)
  c2:str = str_join3(c1, ",", platform)
  c3:str = str_join3(c2, ",", vz)
  c4:str = str_join3(c3, ",", p0)
  c5:str = str_join3(c4, ",", p1)
  c6:str = str_join3(c5, ",", p2)
  c7:str = str_join3(c6, ",", rc_s)
  append_line_file(path, c7)

  say "startup-profile:"
  m0:str = str_join3("  lane: ", lane, "")
  m1:str = str_join3("  source: ", src_path, "")
  m2:str = str_join3("  platform: ", platform, "")
  m3a:str = str_join3("  preflight_ms: ", p0, "")
  m3b:str = str_join3("  exec_ms: ", p1, "")
  m3c:str = str_join3("  total_ms: ", p2, "")
  m3d:str = str_join3("  rc: ", rc_s, "")
  m4:str = str_join3("  saved: ", path, "")
  say m0
  say m1
  say m2
  say m3a
  say m3b
  say m3c
  say m3d
  say m4

  free(ts)
  free(vz)
  free(p0)
  free(p1)
  free(p2)
  free(rc_s)
  free(c0)
  free(c1)
  free(c2)
  free(c3)
  free(c4)
  free(c5)
  free(c6)
  free(c7)
  free(m0)
  free(m1)
  free(m2)
  free(m3a)
  free(m3b)
  free(m3c)
  free(m3d)
  free(m4)
  ret 0

fn repl_has_assign_op(s:str) -> int:
  if s == 0:
    ret 0
  n:int = len(s)
  i:int = 0
  while i < n:
    c:int = s[i] as int
    if c == 61:
      prev:int = 0
      next:int = 0
      if i > 0:
        prev = s[i - 1] as int
      if (i + 1) < n:
        next = s[i + 1] as int
      if prev != 61 && prev != 33 && prev != 60 && prev != 62 && next != 61:
        ret 1
    if (i + 1) < n:
      c2:int = s[i + 1] as int
      if (c == 43 && c2 == 43) || (c == 45 && c2 == 45):
        ret 1
      if c2 == 61:
        if c == 43 || c == 45 || c == 42 || c == 47 || c == 37 || c == 38 || c == 124 || c == 94:
          ret 1
      if (i + 2) < n:
        c3:int = s[i + 2] as int
        if c == 60 && c2 == 60 && c3 == 61:
          ret 1
        if c == 62 && c2 == 62 && c3 == 61:
          ret 1
    i = i + 1
  ret 0

fn repl_trim(s:str) -> str:
  if s == 0:
    ret 0 as str
  // Keep REPL input byte-stable; read_line already strips trailing newline.
  ret str_join2("", s)

fn repl_is_expr(src:str) -> int:
  t:str = repl_trim(src)
  if t == 0:
    ret 0
  if len(t) == 0:
    free(t)
    ret 0
  if starts_with(t, "let ") || streq(t, "let"):
    free(t)
    ret 0
  if starts_with(t, "const let ") || streq(t, "const let"):
    free(t)
    ret 0
  if starts_with(t, "fn ") || starts_with(t, "struct ") || starts_with(t, "enum ") || starts_with(t, "typedef ") || starts_with(t, "import "):
    free(t)
    ret 0
  if starts_with(t, "if ") || starts_with(t, "while ") || starts_with(t, "for ") || starts_with(t, "switch ") || starts_with(t, "unsafe"):
    free(t)
    ret 0
  if starts_with(t, "extern ") || starts_with(t, "static ") || starts_with(t, "kernel "):
    free(t)
    ret 0
  if starts_with(t, "@"):
    free(t)
    ret 0
  if repl_has_assign_op(t) != 0:
    free(t)
    ret 0
  n:int = len(t)
  i:int = n - 1
  while i >= 0 && is_space(t[i] as int) != 0:
    i = i - 1
  if i >= 0 && t[i] == 58 as char:
    free(t)
    ret 0
  free(t)
  ret 1

fn repl_is_persistent(src:str, is_expr:int) -> int:
  if src == 0:
    ret 0
  if is_expr != 0:
    ret 0
  t:str = repl_trim(src)
  if t == 0:
    ret 0
  if starts_with(t, "import "):
    free(t)
    ret 1
  if starts_with(t, "let ") || starts_with(t, "const let "):
    free(t)
    ret 1
  if starts_with(t, "fn ") || starts_with(t, "struct ") || starts_with(t, "enum ") || starts_with(t, "typedef "):
    free(t)
    ret 1
  if repl_has_assign_op(t) != 0:
    free(t)
    ret 1
  free(t)
  ret 0

fn repl_needs_more(src:str) -> int:
  t:str = repl_trim(src)
  if t == 0:
    ret 0
  n:int = len(t)
  i:int = n - 1
  while i >= 0 && is_space(t[i] as int) != 0:
    i = i - 1
  if i >= 0 && t[i] == 58 as char:
    free(t)
    ret 1
  free(t)
  ret 0

fn repl_read_prompt(prompt:str, in_h:*char, out_h:*char) -> str:
  out:*char = out_h
  if out == 0:
    out = stdout()
  if out != 0:
    fwrite(prompt, 1, len(prompt), out)
    fflush(out)
  src:*char = in_h
  if src == 0:
    src = stdin()
  line:str = read_line(src)
  if line == 0:
    ret 0 as str
  // read_line may yield "" at EOF on non-interactive stdin.
  if streq(line, "") && io_eof(src) != 0:
    ret 0 as str
  ret line

fn cmd_repl() -> int:
  lang_mode:str = "systems"
  if user_args_count() >= 2:
    ai_mode:int = 1
    while ai_mode < user_args_count():
      a0:str = arg(ai_mode)
      if streq(a0, "--help") || streq(a0, "-h"):
        ret print_usage_repl()
      if streq(a0, "--mode") && (ai_mode + 1) < user_args_count():
        lang_mode = arg(ai_mode + 1)
        ai_mode = ai_mode + 2
        continue
      if starts_with(a0, "--mode=") != 0:
        lang_mode = a0 + 7
        ai_mode = ai_mode + 1
        continue
      if starts_with(a0, "--") != 0:
        p_bad_repl:str = str_join2("repl: unknown option: ", a0)
        say p_bad_repl
        free(p_bad_repl)
        ret 0 - 1
      ai_mode = ai_mode + 1
  if streq(lang_mode, "simple") == 0 && streq(lang_mode, "systems") == 0:
    say "repl: --mode must be simple or systems"
    ret 0 - 1

  tezzc:str = tezzc_path()
  if tezzc == 0:
    say "repl: compiler not found"
    ret 0 - 1
  unlock_empty_lock_file()
  relax_stale_std_lock()
  if ensure_std_module_available() == 0:
    say "tezz: failed to resolve std module (sdk/cache/registry fallback)"
    say "hint: run `tezz get std@0.1.0` or `tezz doctor --fix`"
    ret 0 - 1
  ensure_dir("build")
  tmp_path:str = "build/tezz_repl_eval.tn"
  qtmp:str = quote_cmd_path(tmp_path)
  ensure_dir(".tezz")
  ensure_dir(".tezz/cache")
  ensure_dir(".tezz/cache/repl")
  repl_platform:str = default_platform()
  repl_os:str = os_name()
  repl_exe_suffix:str = ""
  if streq(repl_os, "windows"):
    repl_exe_suffix = ".exe"
  tezzc_fs_path:str = strip_outer_quotes(tezzc)
  repl_tool_crc:int = crc32_file(tezzc_fs_path)
  repl_tool_hex:str = hex8(repl_tool_crc)
  if tezzc_fs_path != 0:
    free(tezzc_fs_path)
  in_h:*char = stdin()
  out_h:*char = stdout()
  own_in:int = 0
  own_out:int = 0
  osn:str = os_name()
  if streq(osn, "windows") == 0:
    tty_in:*char = fopen("/dev/tty", "r")
    if tty_in != 0:
      in_h = tty_in
      own_in = 1
    tty_out:*char = fopen("/dev/tty", "w")
    if tty_out != 0:
      out_h = tty_out
      own_out = 1

  state:str = str_join2("", "")
  say "TezzNative REPL"
  mode_msg0:str = str_join3("mode: ", lang_mode, "")
  say mode_msg0
  free(mode_msg0)
  say "type .help for commands"

  while 1:
    line:str = repl_read_prompt("tezz> ", in_h, out_h)
    if line == 0:
      break
    trim:str = repl_trim(line)
    if trim == 0 || len(trim) == 0:
      if trim != 0:
        free(trim)
      free(line)
      continue
    if strcmp(trim, ".quit") == 0 || strcmp(trim, ".exit") == 0:
      free(trim)
      free(line)
      break
    if strcmp(trim, ".help") == 0:
      say ".help  show commands"
      say ".reset reset REPL state"
      say ".state show persisted state size"
      say ".quit  exit REPL"
      free(trim)
      free(line)
      continue
    if strcmp(trim, ".reset") == 0:
      free(state)
      state = str_join2("", "")
      say "state reset"
      free(trim)
      free(line)
      continue
    if strcmp(trim, ".state") == 0:
      nstate:str = int_to_str(len(state))
      msg_state:str = str_join3("state_bytes=", nstate, "")
      say msg_state
      free(nstate)
      free(msg_state)
      free(trim)
      free(line)
      continue

    chunk:str = line
    if repl_needs_more(trim) != 0:
      while 1:
        next_line:str = repl_read_prompt("... ", in_h, out_h)
        if next_line == 0:
          break
        if len(next_line) == 0:
          free(next_line)
          break
        p0:str = str_join2(chunk, "\n")
        p1:str = str_join2(p0, next_line)
        free(p0)
        free(chunk)
        free(next_line)
        chunk = p1
      free(trim)
      trim = repl_trim(chunk)
      if trim == 0 || len(trim) == 0:
        if trim != 0:
          free(trim)
        free(chunk)
        continue
    if streq(lang_mode, "simple") != 0:
      reason_repl:str = simple_mode_disallow_reason(chunk)
      if reason_repl != 0:
        p_simple_err0:str = str_join3("simple-mode error: ", reason_repl, "")
        say p_simple_err0
        free(reason_repl)
        free(p_simple_err0)
        free(chunk)
        free(trim)
        continue

    is_expr:int = repl_is_expr(chunk)
    eval_src:str = 0 as str
    if is_expr != 0:
      e0:str = str_join3("say(", chunk, ")")
      eval_src = str_join2(e0, "\n")
      free(e0)
    else:
      eval_src = str_join2(chunk, "\n")

    block0:str = str_join2("  ", eval_src)
    body:str = str_join2(state, block0)
    main0:str = str_join2("fn main() -> int:\n", body)
    main1:str = str_join2(main0, "  ret 0\n")
    candidate:str = str_join2("import \"std\"\n", main1)
    io.write_all(tmp_path, candidate)

    use_bc_repl:int = 0
    if str_contains(candidate, "input(") != 0:
      use_bc_repl = 1
    if use_bc_repl == 0 && str_contains(candidate, "ws_") != 0:
      use_bc_repl = 1
    if use_bc_repl == 0 && str_contains(candidate, "_sha1_bytes(") != 0:
      use_bc_repl = 1
    if use_bc_repl == 0 && str_contains(candidate, "_base64_encode(") != 0:
      use_bc_repl = 1
    if use_bc_repl == 0 && str_contains(candidate, "import \"net\"") != 0:
      use_bc_repl = 1
    if use_bc_repl == 0 && str_contains(candidate, "import \"io\"") != 0:
      use_bc_repl = 1
    if use_bc_repl == 0 && str_contains(candidate, "net.") != 0:
      use_bc_repl = 1
    if use_bc_repl == 0 && str_contains(candidate, "io.") != 0:
      use_bc_repl = 1
    if use_bc_repl == 0 && str_contains(candidate, "args_count(") != 0:
      use_bc_repl = 1
    if use_bc_repl == 0 && str_contains(candidate, "arg(") != 0:
      use_bc_repl = 1

    rc:int = 0
    if use_bc_repl == 0:
      repl_src_hex:str = hex8(crc32_str(candidate))
      rk0:str = str_join3("repl-", lang_mode, "-")
      rk1:str = str_join3(rk0, repl_platform, "-")
      rk2:str = str_join3(rk1, repl_src_hex, "-")
      rk3:str = str_join2(rk2, repl_tool_hex)
      rk4:str = str_join2(rk3, repl_exe_suffix)
      repl_cache_exe:str = path_join(".tezz/cache/repl", rk4)
      q_repl_cache_exe:str = quote_cmd_path(repl_cache_exe)
      run_native_repl:int = 1
      if path_exists(repl_cache_exe) == 0:
        rb0:str = str_join3(tezzc, " buildexe ", qtmp)
        rb1:str = str_join3(rb0, " ", q_repl_cache_exe)
        rb2:str = str_join3(rb1, " --target ", repl_platform)
        rb3:str = str_join2(rb2, " --vectorize")
        if run_to_file(rb3, "build/repl_cache_build.log") != 0:
          run_native_repl = 0
        free(rb0)
        free(rb1)
        free(rb2)
        free(rb3)
      if run_native_repl != 0:
        rc = proc_run(q_repl_cache_exe)
      else:
        cmd0:str = str_join3(tezzc, " run --bc ", qtmp)
        rc = proc_run(cmd0)
        free(cmd0)
      free(repl_src_hex)
      free(rk0)
      free(rk1)
      free(rk2)
      free(rk3)
      free(rk4)
      free(repl_cache_exe)
      free(q_repl_cache_exe)
    else:
      cmd0:str = str_join3(tezzc, " run --bc ", qtmp)
      rc = proc_run(cmd0)
      free(cmd0)
    if rc == 0:
      if repl_is_persistent(chunk, is_expr) != 0:
        p0:str = str_join2("  ", chunk)
        p1:str = str_join2(p0, "\n")
        s1:str = str_join2(state, p1)
        free(p0)
        free(p1)
        free(state)
        state = s1

    free(block0)
    free(body)
    free(main0)
    free(main1)
    free(candidate)
    free(eval_src)
    free(chunk)
    free(trim)
  if own_in != 0 && in_h != 0:
    fclose(in_h)
  if own_out != 0 && out_h != 0:
    fclose(out_h)
  free(state)
  free(repl_tool_hex)
  free(qtmp)
  ret 0

fn cmd_run_path(path:str) -> int:
  if path == 0:
    ret 0 - 1
  tezzc:str = tezzc_path()
  if tezzc == 0:
    ret 0 - 1
  ensure_dir("build")
  run_start_ms:int = time.now_ms()
  unlock_empty_lock_file()
  relax_stale_std_lock()
  if ensure_std_module_available() == 0:
    say "tezz: failed to resolve std module (sdk/cache/registry fallback)"
    say "hint: run `tezz get std@0.1.0` or `tezz doctor --fix`"
    ret 0 - 1
  // Parse run options + passthrough app args.
  vectorize:int = 1
  platform:str = 0 as str
  startup_profile:int = 0
  startup_profile_out:str = 0 as str
  lang_mode:str = "systems"
  passthrough:str = 0 as str
  pass_all:int = 0
  ai:int = 1
  if args_count() > 0 && streq(arg(0), "run"):
    ai = 2
  while ai < args_count():
    a:str = arg(ai)
    if pass_all != 0:
      qarg_pa:str = quote_cmd_path(a)
      if passthrough == 0:
        passthrough = str_join2(" ", qarg_pa)
      else:
        p0_pa:str = str_join2(passthrough, " ")
        p1_pa:str = str_join2(p0_pa, qarg_pa)
        free(passthrough)
        free(p0_pa)
        passthrough = p1_pa
      free(qarg_pa)
      ai = ai + 1
      continue
    if streq(a, "--"):
      pass_all = 1
      ai = ai + 1
      continue
    if streq(a, "--target") && (ai + 1) < args_count():
      platform = arg(ai + 1)
      ai = ai + 2
      continue
    if starts_with(a, "--target=") != 0:
      platform = a + 9
      ai = ai + 1
      continue
    if streq(a, "--platform") && (ai + 1) < args_count():
      platform = arg(ai + 1)
      ai = ai + 2
      continue
    if starts_with(a, "--platform=") != 0:
      platform = a + 11
      ai = ai + 1
      continue
    if streq(a, "--startup-profile") || streq(a, "--profile-startup"):
      startup_profile = 1
      ai = ai + 1
      continue
    if streq(a, "--mode") && (ai + 1) < args_count():
      lang_mode = arg(ai + 1)
      ai = ai + 2
      continue
    if starts_with(a, "--mode=") != 0:
      lang_mode = a + 7
      ai = ai + 1
      continue
    if streq(a, "--startup-profile-out"):
      if (ai + 1) >= args_count():
        say "tezz run: --startup-profile-out requires <path>"
        if passthrough != 0:
          free(passthrough)
        ret 0 - 1
      startup_profile = 1
      startup_profile_out = arg(ai + 1)
      ai = ai + 2
      continue
    if starts_with(a, "--startup-profile-out=") != 0:
      startup_profile = 1
      startup_profile_out = a + 22
      ai = ai + 1
      continue
    if streq(a, "--no-vectorize"):
      vectorize = 0
      ai = ai + 1
      continue
    if streq(a, "--vectorize"):
      vectorize = 1
      ai = ai + 1
      continue
    // Unknown arg: pass through to program.
    qarg:str = quote_cmd_path(a)
    if passthrough == 0:
      passthrough = str_join2(" ", qarg)
    else:
      p0:str = str_join2(passthrough, " ")
      p1:str = str_join2(p0, qarg)
      free(passthrough)
      free(p0)
      passthrough = p1
    free(qarg)
    ai = ai + 1

  if streq(lang_mode, "simple") == 0 && streq(lang_mode, "systems") == 0:
    say "tezz run: --mode must be simple or systems"
    if passthrough != 0:
      free(passthrough)
    ret 0 - 1

  run_path:str = path
  compat_path:str = compat_rewrite_input_mode(path)
  simple_path:str = 0 as str
  if compat_path != 0:
    run_path = compat_path
  if path_exists(run_path) == 0:
    p_nf0:str = str_join2("tezz: file not found: ", run_path)
    say p_nf0
    free(p_nf0)
    if compat_path != 0:
      remove(compat_path)
      free(compat_path)
    ret 0 - 1
  src_in:str = io.read_all(run_path)
  if src_in != 0:
    if streq(lang_mode, "simple") != 0:
      reason_simple:str = simple_mode_disallow_reason(src_in)
      if reason_simple != 0:
        p_simple0:str = str_join3("simple-mode error: ", reason_simple, "")
        say p_simple0
        say "hint: remove unsafe/pointer APIs or run with --mode systems"
        free(reason_simple)
        free(p_simple0)
        free(src_in)
        if passthrough != 0:
          free(passthrough)
        if compat_path != 0:
          remove(compat_path)
          free(compat_path)
        ret 0 - 1
      src_simple:str = simple_mode_transform(src_in)
      if src_simple == 0:
        say "simple-mode error: failed to rewrite source"
        free(src_in)
        if passthrough != 0:
          free(passthrough)
        if compat_path != 0:
          remove(compat_path)
          free(compat_path)
        ret 0 - 1
      simple_path = str_join2(run_path, ".simple.tn")
      if io.write_all(simple_path, src_simple) < 0:
        say "simple-mode error: failed to write rewritten source"
        free(src_simple)
        free(src_in)
        free(simple_path)
        if passthrough != 0:
          free(passthrough)
        if compat_path != 0:
          remove(compat_path)
          free(compat_path)
        ret 0 - 1
      free(src_simple)
      free(src_in)
      run_path = simple_path
      src_in = io.read_all(run_path)
      if src_in == 0:
        say "simple-mode error: failed to reload rewritten source"
        if passthrough != 0:
          free(passthrough)
        if compat_path != 0:
          remove(compat_path)
          free(compat_path)
        if simple_path != 0:
          remove(simple_path)
          free(simple_path)
        ret 0 - 1
    need_bc:int = 0
    if str_contains(src_in, "input(") != 0:
      need_bc = 1
    // Temporary correctness gate:
    // WebSocket/SHA1-heavy flows run via VM path until native backend parity catches up.
    if need_bc == 0 && str_contains(src_in, "ws_") != 0:
      need_bc = 1
    if need_bc == 0 && str_contains(src_in, "_sha1_bytes(") != 0:
      need_bc = 1
    if need_bc == 0 && str_contains(src_in, "_base64_encode(") != 0:
      need_bc = 1
    // Networking correctness gate:
    // Net/http parser-heavy flows still use VM path until native parity is fully stable.
    if need_bc == 0 && str_contains(src_in, "import \"net\"") != 0:
      need_bc = 1
    if need_bc == 0 && str_contains(src_in, "import \"io\"") != 0:
      need_bc = 1
    if need_bc == 0 && str_contains(src_in, "net.") != 0:
      need_bc = 1
    if need_bc == 0 && str_contains(src_in, "io.") != 0:
      need_bc = 1
    if need_bc == 0 && str_contains(src_in, "http_") != 0 && str_contains(src_in, "import \"std\"") != 0:
      need_bc = 1
    // GUI host-window lane currently runs through BC runtime backend.
    if need_bc == 0 && str_contains(src_in, "import \"gui\"") != 0:
      need_bc = 1
    if need_bc == 0 && str_contains(src_in, "import \"tzgui\"") != 0:
      need_bc = 1
    if need_bc == 0 && str_contains(src_in, "import \"tzui\"") != 0:
      need_bc = 1
    if need_bc == 0 && str_contains(src_in, "import \"wm\"") != 0:
      need_bc = 1
    if need_bc == 0 && str_contains(src_in, "import \"tnui\"") != 0:
      need_bc = 1
    if need_bc == 0 && str_contains(src_in, "import \"os\"") != 0:
      need_bc = 1
    // CLI args parity gate:
    // args_count/arg are VM-stable across platforms; force bytecode lane until
    // native argv parity is fully stable on non-Windows hosts.
    if need_bc == 0 && str_contains(src_in, "args_count(") != 0:
      need_bc = 1
    if need_bc == 0 && str_contains(src_in, "arg(") != 0:
      need_bc = 1
    if need_bc != 0:
      free(src_in)
      cmd_bc0:str = str_join3(tezzc, " run --bc ", run_path)
      cmd_bc_run:str = cmd_bc0
      cmd_bc1:str = 0 as str
      cmd_bc2:str = 0 as str
      if passthrough != 0 && len(passthrough) > 0:
        cmd_bc1 = str_join2(cmd_bc0, " --")
        cmd_bc2 = str_join2(cmd_bc1, passthrough)
        cmd_bc_run = cmd_bc2
      exec_start_ms:int = time.now_ms()
      rb0:int = proc_run(cmd_bc_run)
      done_ms:int = time.now_ms()
      pre_ms:int = exec_start_ms - run_start_ms
      exec_ms:int = done_ms - exec_start_ms
      total_ms:int = done_ms - run_start_ms
      if startup_profile != 0:
        g_startup_profile_path = startup_profile_out
        g_startup_profile_lane = "bc"
        g_startup_profile_source = run_path
        g_startup_profile_platform = "bytecode"
        g_startup_profile_vectorize = 0
        g_startup_profile_pre_ms = pre_ms
        g_startup_profile_exec_ms = exec_ms
        g_startup_profile_total_ms = total_ms
        g_startup_profile_rc = rb0
        startup_profile_emit()
      if cmd_bc1 != 0:
        free(cmd_bc1)
      if cmd_bc2 != 0:
        free(cmd_bc2)
      free(cmd_bc0)
      if passthrough != 0:
        free(passthrough)
      if compat_path != 0:
        remove(compat_path)
        free(compat_path)
      if simple_path != 0:
        remove(simple_path)
        free(simple_path)
      ret rb0
    free(src_in)
  // Default to native + vectorize for production speed; --bc still available explicitly.
  if platform == 0:
    platform = default_platform()
  platform = map_platform_arg(platform)
  if platform_supported(platform) == 0:
    say "run: unsupported platform target"
    say "supported targets: linux|windows|macos|android|native"
    if passthrough != 0:
      free(passthrough)
    if compat_path != 0:
      remove(compat_path)
      free(compat_path)
    if simple_path != 0:
      remove(simple_path)
      free(simple_path)
    ret 0 - 1
  // Native cache key: source + toolchain + mode + target + vectorize.
  osn_native:str = os_name()
  exe_suffix_native:str = ""
  if streq(osn_native, "windows"):
    exe_suffix_native = ".exe"
  ensure_dir(".tezz")
  ensure_dir(".tezz/cache")
  ensure_dir(".tezz/cache/run")
  src_crc:int = crc32_file(run_path)
  tezzc_fs_path2:str = strip_outer_quotes(tezzc)
  tool_crc:int = crc32_file(tezzc_fs_path2)
  if tezzc_fs_path2 != 0:
    free(tezzc_fs_path2)
  src_hex:str = hex8(src_crc)
  tool_hex:str = hex8(tool_crc)
  vec_s:str = int_to_str(vectorize)
  base_name:str = path_basename_no_ext(run_path)
  if base_name == 0 || base_name[0] == 0:
    if base_name != 0:
      free(base_name)
    base_name = str_join2("script", "")
  ck0:str = str_join3(base_name, "-", lang_mode)
  ck1:str = str_join3(ck0, "-", platform)
  ck2:str = str_join3(ck1, "-v", vec_s)
  ck3:str = str_join3(ck2, "-", src_hex)
  ck4:str = str_join3(ck3, "-", tool_hex)
  cache_file:str = str_join2(ck4, exe_suffix_native)
  cache_exe:str = path_join(".tezz/cache/run", cache_file)
  q_cache_exe:str = quote_cmd_path(cache_exe)
  cache_hit:int = 0
  use_fallback_native:int = 0
  if path_exists(cache_exe) != 0:
    cache_hit = 1
  else:
    q_run_path:str = quote_cmd_path(run_path)
    b0:str = str_join3(tezzc, " buildexe ", q_run_path)
    b1:str = str_join3(b0, " ", q_cache_exe)
    b2:str = str_join3(b1, " --target ", platform)
    b3:str = 0 as str
    if vectorize != 0:
      b3 = str_join2(b2, " --vectorize")
    else:
      b3 = str_join2(b2, " --no-vectorize")
    if run_to_file(b3, "build/native_cache_build.log") != 0:
      use_fallback_native = 1
    free(q_run_path)
    free(b0)
    free(b1)
    free(b2)
    free(b3)
  lane_native:str = "native-cache-hit"
  if cache_hit == 0:
    lane_native = "native-cache-miss"
  exec_start_ms_native:int = time.now_ms()
  r:int = 0
  if use_fallback_native == 0:
    cmd_run_native:str = q_cache_exe
    cmd_cache_args:str = 0 as str
    if passthrough != 0 && len(passthrough) > 0:
      cmd_cache_args = str_join2(q_cache_exe, passthrough)
      cmd_run_native = cmd_cache_args
    if streq(osn_native, "windows"):
      fixed_cmd:str = win_fix_cmd_slash(cmd_run_native)
      r = proc_run(fixed_cmd)
      free(fixed_cmd)
    else:
      r = proc_run(cmd_run_native)
    if cmd_cache_args != 0:
      free(cmd_cache_args)
  else:
    lane_native = "native"
    cmd0:str = str_join3(tezzc, " run --native --target ", platform)
    cmd0b:str = 0 as str
    cmd1:str = 0 as str
    if vectorize != 0:
      cmd0b = str_join2(cmd0, " --vectorize ")
    else:
      cmd0b = str_join2(cmd0, " --no-vectorize ")
    cmd1 = str_join2(cmd0b, run_path)
    cmd_run:str = cmd1
    cmd2:str = 0 as str
    cmd3:str = 0 as str
    if passthrough != 0 && len(passthrough) > 0:
      cmd2 = str_join2(cmd1, " --")
      cmd3 = str_join2(cmd2, passthrough)
      cmd_run = cmd3
    r = proc_run(cmd_run)
    free(cmd0)
    free(cmd0b)
    free(cmd1)
    if cmd2 != 0:
      free(cmd2)
    if cmd3 != 0:
      free(cmd3)
  done_ms_native:int = time.now_ms()
  pre_ms_native:int = exec_start_ms_native - run_start_ms
  exec_ms_native:int = done_ms_native - exec_start_ms_native
  total_ms_native:int = done_ms_native - run_start_ms
  if startup_profile != 0:
    g_startup_profile_path = startup_profile_out
    g_startup_profile_lane = lane_native
    g_startup_profile_source = run_path
    g_startup_profile_platform = platform
    g_startup_profile_vectorize = vectorize
    g_startup_profile_pre_ms = pre_ms_native
    g_startup_profile_exec_ms = exec_ms_native
    g_startup_profile_total_ms = total_ms_native
    g_startup_profile_rc = r
    startup_profile_emit()
  free(src_hex)
  free(tool_hex)
  free(vec_s)
  free(base_name)
  free(ck0)
  free(ck1)
  free(ck2)
  free(ck3)
  free(ck4)
  free(cache_file)
  free(cache_exe)
  free(q_cache_exe)
  if passthrough != 0:
    free(passthrough)
  if compat_path != 0:
    remove(compat_path)
    free(compat_path)
  if simple_path != 0:
    remove(simple_path)
    free(simple_path)
  ret r

fn cmd_build_path(path:str) -> int:
  if path == 0:
    ret 0 - 1
  ensure_dir("build")
  unlock_empty_lock_file()
  relax_stale_std_lock()
  if ensure_std_module_available() == 0:
    say "tezz: failed to resolve std module (sdk/cache/registry fallback)"
    say "hint: run `tezz get std@0.1.0` or `tezz doctor --fix`"
    ret 0 - 1
  build_path:str = path
  compat_path:str = compat_rewrite_input_mode(path)
  if compat_path != 0:
    build_path = compat_path
  if path_exists(build_path) == 0:
    p_bnf0:str = str_join2("tezz: file not found: ", build_path)
    say p_bnf0
    free(p_bnf0)
    if compat_path != 0:
      remove(compat_path)
      free(compat_path)
    ret 0 - 1
  // optional platform override
  platform:str = 0 as str
  vectorize:int = 1
  release_mode:int = 0
  dxil:int = 0
  dxil_entry:str = 0 as str
  dxc_path:str = 0 as str
  dxc_set:int = 0
  ai:int = 1
  while ai < args_count():
    a:str = arg(ai)
    if streq(a, "--platform") && (ai + 1) < args_count():
      platform = arg(ai + 1)
      ai = ai + 2
      continue
    if starts_with(a, "--platform=") != 0:
      platform = a + 11
      ai = ai + 1
      continue
    if streq(a, "--dxil"):
      dxil = 1
      ai = ai + 1
      continue
    if streq(a, "--vectorize"):
      vectorize = 1
      ai = ai + 1
      continue
    if streq(a, "--no-vectorize"):
      vectorize = 0
      ai = ai + 1
      continue
    if streq(a, "--release"):
      release_mode = 1
      vectorize = 1
      ai = ai + 1
      continue
    if streq(a, "--dxil-entry") && (ai + 1) < args_count():
      dxil_entry = arg(ai + 1)
      ai = ai + 2
      continue
    if starts_with(a, "--dxil-entry=") != 0:
      dxil_entry = a + 13
      ai = ai + 1
      continue
    if streq(a, "--dxc") && (ai + 1) < args_count():
      dxc_path = arg(ai + 1)
      dxc_set = 1
      ai = ai + 2
      continue
    if starts_with(a, "--dxc=") != 0:
      dxc_path = a + 6
      dxc_set = 1
      ai = ai + 1
      continue
    ai = ai + 1
  if platform == 0:
    platform = default_platform()
  platform = map_platform_arg(platform)
  if platform_supported(platform) == 0:
    say "build: unsupported platform target"
    say "supported targets: linux|windows|macos|android|native"
    if compat_path != 0:
      remove(compat_path)
      free(compat_path)
    ret 0 - 1
  base:str = path_basename_no_ext(build_path)
  if base == 0:
    if compat_path != 0:
      remove(compat_path)
      free(compat_path)
    ret 0 - 1
  osn:str = os_name()
  exe_suffix:str = ""
  out_dir:str = "build/"
  if streq(osn, "windows"):
    out_dir = ".\\build\\"
  if streq(platform, "x86_64") || streq(platform, "x86") || streq(platform, "arm64"):
    exe_suffix = ".exe"

  out1:str = str_join2(out_dir, base)
  out2:str = str_join2(out1, exe_suffix)
  tezzc:str = tezzc_path()
  if tezzc == 0:
    free(base)
    free(out1)
    free(out2)
    if compat_path != 0:
      remove(compat_path)
      free(compat_path)
    ret 0 - 1
  cmd1:str = str_join3(tezzc, " buildexe ", build_path)
  cmd2:str = str_join3(cmd1, " ", out2)
  cmd3a:str = str_join3(cmd2, " --target ", platform)
  cmd3:str = 0 as str
  if vectorize != 0:
    cmd3 = str_join2(cmd3a, " --verify --vectorize")
  else:
    cmd3 = str_join2(cmd3a, " --verify --no-vectorize")
  r:int = proc_run(cmd3)
  if release_mode != 0 && r == 0:
    if path_exists("tezz.mod") != 0:
      if cmd_lock() != 0:
        say "build --release: lock generation failed"
        r = 0 - 1

  // Optional DXIL build for HLSL kernels (auto if kernel fn detected)
  do_dxil:int = dxil
  if do_dxil == 0:
    if has_kernel_fn(build_path) != 0:
      do_dxil = 1
  if do_dxil != 0:
    if dxc_path == 0:
      dxc_path = "dxc"
    has_dxc:int = 1
    if dxc_set == 0 && dxc_available() == 0:
      has_dxc = 0
    if has_dxc == 0:
      if dxil != 0:
        say "dxc not found"
        r = 0 - 1
      else:
        do_dxil = 0
    if do_dxil != 0:
      hlsl_out1:str = str_join2(out_dir, base)
      hlsl_out:str = str_join2(hlsl_out1, ".hlsl")
      cmd_h1:str = str_join3(tezzc, " buildir ", build_path)
      cmd_h2:str = str_join3(cmd_h1, " ", hlsl_out)
      cmd_h3:str = str_join2(cmd_h2, " --target hlsl")
      rh:int = proc_run(cmd_h3)
      if rh != 0:
        r = 0 - 1
      else:
        entries:str = 0 as str
        if dxil_entry != 0:
          entries = str_join2(dxil_entry, "\n")
        else:
          entries = hlsl_collect_entries(hlsl_out)
        if entries == 0:
          say "dxil entry not found"
          r = 0 - 1
        else:
          // count entries
          cnt:int = 0
          idxe:int = 0
          map:str = str_join2("{\"schema\":\"dxil_map\",\"version\":1}\n", "")
          while 1:
            ent0:str = next_manifest_line(entries, &idxe)
            if ent0 == 0:
              break
            cnt = cnt + 1
            free(ent0)
          idxe = 0
          first:int = 1
          while 1:
            ent:str = next_manifest_line(entries, &idxe)
            if ent == 0:
              break
            out_name:str = 0 as str
            if cnt <= 1:
              dxil_out1:str = str_join2(out_dir, base)
              out_name = str_join2(dxil_out1, ".dxil")
              free(dxil_out1)
            else:
              if first != 0:
                dxil_out1a:str = str_join2(out_dir, base)
                out_name = str_join2(dxil_out1a, ".dxil")
                free(dxil_out1a)
              else:
                safe:str = sanitize_name(ent)
                dxil_out1b:str = str_join2(out_dir, base)
                dxil_out2b:str = str_join3(dxil_out1b, "_", safe)
                out_name = str_join2(dxil_out2b, ".dxil")
                free(dxil_out1b)
                free(dxil_out2b)
                free(safe)
            cmd_d1:str = str_join3(dxc_path, " -T cs_6_6 -HV 2021 -E ", ent)
            cmd_d2:str = str_join3(cmd_d1, " -Fo ", out_name)
            cmd_d3:str = str_join3(cmd_d2, " ", hlsl_out)
            if streq(osn, "windows") != 0:
              tmpd:str = win_fix_cmd_slash(cmd_d3)
              free(cmd_d3)
              cmd_d3 = tmpd
            if proc_run(cmd_d3) != 0:
              r = 0 - 1
            // update map
            line1:str = str_join3("{\"kernel\":\"", ent, "\",\"dxil\":\"")
            line2:str = str_join3(line1, out_name, "\",\"threads\":[1,1,1],\"kind\":\"kernel\"}")
            line3:str = str_join2(line2, "\n")
            tmpm:str = str_join2(map, line3)
            free(map)
            map = tmpm
            free(line1)
            free(line2)
            free(line3)
            free(cmd_d1)
            free(cmd_d2)
            free(cmd_d3)
            free(out_name)
            free(ent)
            first = 0
          // write map
          if map != 0:
            map1:str = str_join2(out_dir, base)
            map2:str = str_join2(map1, "_dxil_map.tnx")
            io.write_all(map2, map)
            free(map1)
            free(map2)
            free(map)
          free(entries)
      free(hlsl_out1)
      free(hlsl_out)
      free(cmd_h1)
      free(cmd_h2)
      free(cmd_h3)

  free(base)
  free(out1)
  free(out2)
  free(cmd1)
  free(cmd2)
  free(cmd3a)
  free(cmd3)
  if compat_path != 0:
    remove(compat_path)
    free(compat_path)
  ret r

fn boot_iso_path(mode:str) -> str:
  if mode != 0:
    free(mode)
  ret ""

fn cmd_boot_verify(mode:str) -> int:
  if mode != 0:
    free(mode)
  say "boot verify is not available in tezz core CLI"
  ret 0 - 1

fn boot_native_check(mode:str, iso:int) -> int:
  if mode != 0:
    free(mode)
  if iso != 0:
    ret 0 - 1
  ret 0 - 1

fn cmd_boot_native(mode:str, kpath:str, iso:int, verify:int, boot_vbe:int) -> int:
  if mode != 0:
    free(mode)
  if kpath != 0:
    free(kpath)
  if iso != 0:
    verify = verify + 0
  if boot_vbe != 0:
    verify = verify + 0
  say "boot native is not available in tezz core CLI"
  ret 0 - 1

fn cmd_boot() -> int:
  say "tezz boot is not available in tezz core CLI"
  ret 0 - 1

fn resolve_run_path_arg() -> str:
  ucnt:int = user_args_count()
  ai:int = 1
  while ai < ucnt:
    a:str = arg(ai)
    if streq(a, "--"):
      if (ai + 1) < ucnt:
        ret arg(ai + 1)
      ret 0 as str
    if streq(a, "--platform") || streq(a, "--target") || streq(a, "--startup-profile-out") || streq(a, "--mode"):
      ai = ai + 2
      continue
    if starts_with(a, "--platform=") != 0 || starts_with(a, "--target=") != 0 || starts_with(a, "--startup-profile-out=") != 0 || starts_with(a, "--mode=") != 0:
      ai = ai + 1
      continue
    if streq(a, "--vectorize") || streq(a, "--no-vectorize") || streq(a, "--startup-profile") || streq(a, "--profile-startup"):
      ai = ai + 1
      continue
    if starts_with(a, "--") != 0:
      ai = ai + 1
      continue
    ret a
  ret 0 as str

fn resolve_build_path_arg() -> str:
  ucnt:int = user_args_count()
  ai:int = 1
  while ai < ucnt:
    a:str = arg(ai)
    if streq(a, "--"):
      if (ai + 1) < ucnt:
        ret arg(ai + 1)
      ret 0 as str
    if streq(a, "--platform") || streq(a, "--target") || streq(a, "--dxil-entry") || streq(a, "--dxc"):
      ai = ai + 2
      continue
    if starts_with(a, "--platform=") != 0 || starts_with(a, "--target=") != 0 || starts_with(a, "--dxil-entry=") != 0 || starts_with(a, "--dxc=") != 0:
      ai = ai + 1
      continue
    if streq(a, "--release") || streq(a, "--vectorize") || streq(a, "--no-vectorize") || streq(a, "--dxil"):
      ai = ai + 1
      continue
    if starts_with(a, "--") != 0:
      ai = ai + 1
      continue
    ret a
  ret 0 as str

fn main() -> int:
  ucnt:int = user_args_count()
  if ucnt == 0:
    print_usage()
    ret 0

  cmd:str = arg(0)
  if streq(cmd, "--version") || streq(cmd, "-V") || streq(cmd, "version"):
    ret cmd_version()
  if streq(cmd, "--help") || streq(cmd, "-h") || streq(cmd, "help"):
    print_usage()
    ret 0
  if ucnt >= 2:
    a1:str = arg(1)
    if streq(a1, "--help") || streq(a1, "-h"):
      if streq(cmd, "init"):
        ret print_usage_init()
      if streq(cmd, "add"):
        say "tezz add <name@ver> [url] [checksum]"
        ret 0
      if streq(cmd, "remove"):
        say "tezz remove <name>"
        ret 0
      if streq(cmd, "run"):
        ret print_usage_run()
      if streq(cmd, "repl"):
        ret print_usage_repl()
      if streq(cmd, "build"):
        ret print_usage_build()
      if streq(cmd, "test"):
        ret print_usage_test()
      if streq(cmd, "doctor"):
        ret print_usage_doctor()
      if streq(cmd, "update"):
        ret print_usage_update()
      if streq(cmd, "fmt"):
        ret print_usage_fmt()
      if streq(cmd, "lint"):
        ret print_usage_lint()
      if streq(cmd, "verify"):
        ret print_usage_verify()
      if streq(cmd, "lsp"):
        ret print_usage_lsp()
      if streq(cmd, "ai"):
        ret print_usage_ai()
      if streq(cmd, "tsm"):
        ret print_usage_tsm()
      if streq(cmd, "release-artifacts"):
        ret print_usage_release_artifacts()
      if streq(cmd, "reprocheck"):
        ret print_usage_reprocheck()
      if streq(cmd, "release-policy-check"):
        ret print_usage_release_policy_check()
  if streq(cmd, "init"):
    ret cmd_init()
  if ends_with_tn(cmd) != 0:
    ret cmd_run_path(cmd)
  if streq(cmd, "run"):
    run_path_arg:str = resolve_run_path_arg()
    if run_path_arg == 0:
      if path_exists("src/main.tn") != 0:
        say "run: defaulting to src/main.tn"
        ret cmd_run_path("src/main.tn")
      if path_exists("main.tn") != 0:
        say "run: defaulting to main.tn"
        ret cmd_run_path("main.tn")
      print_usage_run()
      ret 0 - 1
    ret cmd_run_path(run_path_arg)
  if streq(cmd, "repl"):
    ret cmd_repl()
  if streq(cmd, "build"):
    build_path_arg:str = resolve_build_path_arg()
    if build_path_arg == 0:
      if path_exists("src/main.tn") != 0:
        say "build: defaulting to src/main.tn"
        ret cmd_build_path("src/main.tn")
      if path_exists("main.tn") != 0:
        say "build: defaulting to main.tn"
        ret cmd_build_path("main.tn")
      print_usage_build()
      ret 0 - 1
    ret cmd_build_path(build_path_arg)
  if streq(cmd, "get"):
    ret cmd_get()
  if streq(cmd, "install"):
    ret cmd_get()
  if streq(cmd, "add"):
    ret cmd_add()
  if streq(cmd, "remove"):
    ret cmd_remove()
  if streq(cmd, "lock"):
    ret cmd_lock()
  if streq(cmd, "publish"):
    ret cmd_publish()
  if streq(cmd, "registry"):
    ret cmd_registry()
  if streq(cmd, "manifest"):
    ret cmd_manifest()
  if streq(cmd, "verify"):
    ret cmd_verify()
  if streq(cmd, "release-artifacts"):
    ret cmd_release_artifacts()
  if streq(cmd, "reprocheck"):
    ret cmd_reprocheck()
  if streq(cmd, "release-policy-check"):
    ret cmd_release_policy_check()
  if streq(cmd, "test"):
    ret cmd_test()
  if streq(cmd, "bench"):
    ret cmd_bench()
  if streq(cmd, "benchext"):
    ret cmd_bench_ext()
  if streq(cmd, "boot"):
    say "tezz boot is not available in tezz core CLI"
    ret 0 - 1
  if streq(cmd, "doctor"):
    ret cmd_doctor()
  if streq(cmd, "lsp"):
    ret cmd_lsp()
  if streq(cmd, "ai"):
    say "tezz ai is not available in tezz core CLI"
    ret 0 - 1
  if streq(cmd, "tsm"):
    say "tezz tsm is not available in tezz core CLI"
    ret 0 - 1
  if streq(cmd, "update"):
    ret cmd_update()
  if streq(cmd, "clean"):
    ret cmd_clean()
  if streq(cmd, "fmt"):
    ret cmd_fmt()
  if streq(cmd, "lint"):
    ret cmd_lint()
  if streq(cmd, "release"):
    ret cmd_release()

  print_usage()
  ret 0
