import re, sys

stage2 = open('/tmp/opencode/stage2.lua').read()
rhex = re.search(r'__RHEX__\t([0-9a-f]+)', open('/tmp/opencode/cap4.txt').read()).group(1)
rbytes = bytes.fromhex(rhex)

# embed R as a Luau string literal (\xNN escapes, chunked)
esc = ''.join('\\x%02x' % b for b in rbytes)
rlit = '"' + esc + '"'

# call profile instrumentation
assert stage2.startswith('local R=')
assert stage2.rstrip().endswith(':A();')
stage2 = stage2.replace('return({', 'local __T={', 1)
stage2 = stage2.rstrip()[:-len('}):A();')] + '};__WRAP(__T);return __T:A();'
# instrument: dump state table immediately before the interpreter call
needle = 'y,A,m,P,e=W:KS(e,P,A,G,y);'
assert stage2.count(needle) == 1
stage2 = stage2.replace(needle, needle, 1)

# make R come from the embedded literal instead of ...
assert stage2.startswith('local R=...;')
stage2 = 'local R=buffer.fromstring(' + rlit + ');' + stage2[len('local R=...;'):]

shim = r'''
-- permissive Roblox environment
__GAME = 0
local __realsetfenv = setfenv
setfenv = function(f, env)
  if type(env) == "table" then
    local mt = getmetatable(env)
    if type(mt) ~= "table" then mt = {} end
    if mt.__index == nil then mt.__index = _G; setmetatable(env, mt) end
  end
  return __realsetfenv(f, env)
end
local __realprint = print
local function __proxy(name)
  local t = {}
  return setmetatable(t, {
    __index = function(self, k)
      if k == "ClassName" then return "Proxy" end
      if tostring(k) == "GetService" then __GAME = __GAME + 1 if __GAME <= 5 then __realprint("GETSERVICE") end end
      if k == "Name" then return name end
      local v = __proxy(name .. "." .. tostring(k))
      rawset(self, k, v)
      return v
    end,
    __newindex = function(self, k, v) rawset(self, k, v) end,
    __call = function(self, ...) return __proxy(name .. "()") end,
    __tostring = function() return "<" .. name .. ">" end,
    __len = function() return 0 end,
    __add = function() return 0 end, __sub = function() return 0 end,
    __mul = function() return 0 end, __div = function() return 0 end,
    __mod = function() return 0 end, __pow = function() return 0 end,
    __unm = function() return 0 end,
    __eq = function() return false end,
    __lt = function() return false end, __le = function() return false end,
    __concat = function() return "" end,
    __iter = function() return function() return nil end end,
  })
end
game = __proxy("game")
workspace = __proxy("workspace")
script = __proxy("script")
local __inst = 0
Instance = { new = function(c, ...) __inst = __inst + 1 if __inst <= 12 then __realprint("INST", tostring(c)) end return __proxy("Instance:" .. tostring(c)) end }
Enum = setmetatable({}, { __index = function(t, k) local v = __proxy("Enum." .. k); rawset(t, k, v); return v end })
local __waits = 0
task = { wait = function() __waits = __waits + 1 if __waits > 3 then error("__LUAD_STOP__") end end, spawn = function() end, delay = function() end, defer = function() end }
typeof = function(v) return type(v) end
tick = function() return 0 end
time = function() return 0 end
wait = function() __waits = __waits + 1 if __waits > 3 then error("__LUAD_STOP__") end end
warn = function() end
Vector2 = __proxy("Vector2")
Vector3 = __proxy("Vector3")
CFrame = __proxy("CFrame")
Color3 = __proxy("Color3")
UDim = __proxy("UDim")
UDim2 = __proxy("UDim2")
Rect = __proxy("Rect")
Ray = __proxy("Ray")
Region3 = __proxy("Region3")
NumberRange = __proxy("NumberRange")
NumberSequence = __proxy("NumberSequence")
ColorSequence = __proxy("ColorSequence")
TweenInfo = __proxy("TweenInfo")
Random = __proxy("Random")
Font = __proxy("Font")
Drawing = __proxy("Drawing")
Path2DControlPoint = __proxy("Path2DControlPoint")
gethui = function() return __proxy("gethui") end
getgenv = function() return _G end
getrenv = function() return _G end
getreg = function() return __proxy("getreg") end
identifyexecutor = function() return "luau-cli", "1.0" end
hookfunction = function(a, b) return a end
hookmetamethod = function() return function() end end
getconnections = function() return {} end
firetouchinterest = function() end
setclipboard = function() end
request = function() return {} end
cloneref = function(t) return t end
setfpscap = function() end
getrawmetatable = getmetatable
setreadonly = function() end
checkcaller = function() return false end
newcclosure = function(f) return f end
getnamecallmethod = function() return nil end
decompile = function() return "" end
require = function(x) return __proxy("require") end

local __MISS = {}
do
  local __type, __tostring, __rawset, __setmetatable, __getmetatable = type, tostring, rawset, setmetatable, getmetatable
  local __env = getfenv()
  local __mt = __getmetatable(__env)
  local __prev = __type(__mt) == "table" and __mt.__index or nil
  __setmetatable(__env, {
    __index = function(t, k)
      local v
      if __prev ~= nil then
        if __type(__prev) == "function" then v = __prev(t, k)
        elseif __type(__prev) == "table" then v = __prev[k] end
      end
      if v == nil then __MISS[#__MISS + 1] = __tostring(k) end
      return v
    end,
  })
end
local __seen = 0
function __FIELD(name, v, depth)
  local t = type(v)
  if t == "table" then
    local n, nnum, nstr, ntab, nfn = 0, 0, 0, 0, 0
    local sample = {}
    local i = 0
    for kk, vv in pairs(v) do
      n = n + 1
      local tt = type(vv)
      if tt == "number" then nnum = nnum + 1 elseif tt == "string" then nstr = nstr + 1 elseif tt == "table" then ntab = ntab + 1 elseif tt == "function" then nfn = nfn + 1 end
      i = i + 1
      if i <= 10 then
        local sv
        if tt == "number" then sv = string.format("%.6g", vv)
        elseif tt == "string" then sv = string.format("%q", vv:sub(1, 16))
        else sv = tt end
        sample[#sample+1] = tostring(kk) .. ":" .. sv
      end
      if i > 500000 then break end
    end
    __realprint("FIELD", name, "table", "len", #v, "count", n, "num", nnum, "str", nstr, "tab", ntab, "fn", nfn, "sample", table.concat(sample, " | "))
  elseif t == "string" then
    __realprint("FIELD", name, "string", #v, string.format("%q", v:sub(1, 60)))
  else
    __realprint("FIELD", name, t, tostring(v))
  end
end
function __VAL(v)
  local t = type(v)
  if t == "number" then return string.format("%.14g", v) end
  if t == "string" then return string.format("%q", v) end
  if t == "table" then
    local n = 0
    for _ in pairs(v) do n = n + 1 end
    return "tbl#" .. n
  end
  return t
end
local __visited = {}
local __hits = 0
local function __findwalk(t, path, depth)
  if depth <= 0 or type(t) ~= "table" or __hits > 60 then return end
  if __visited[t] then return end
  __visited[t] = true
  for k, v in pairs(t) do
    local p = path .. "[" .. tostring(k) .. "]"
    if type(v) == "string" then
      if v:find("Boulder") or v:find("Animals") or v:find("FireServer") or v:find("Path2D") or #v > 25 then
        __realprint("HIT", p, #v, string.format("%q", v:sub(1, 50)))
        __hits = __hits + 1
      end
    elseif type(v) == "number" then
      if v == -35.035717 or v == 3.5714285714 or (v > 3.5714285713999 and v < 3.5714285714001) then
        __realprint("HITNUM", p, string.format("%.10g", v))
        __hits = __hits + 1
      end
    elseif type(v) == "table" then
      __findwalk(v, p, depth - 1)
    end
    if __hits > 60 then return end
  end
end
local function __join(t, n)
  local out = {}
  for i = 1, math.min(#t, n or #t) do
    local v = t[i]
    if type(v) == "number" then out[#out+1] = string.format("%.10g", v)
    elseif type(v) == "string" then out[#out+1] = string.format("%q", v:sub(1, 24))
    else out[#out+1] = "<" .. type(v) .. ">" end
  end
  return table.concat(out, " ")
end
function __TRACE(y, G)
  __realprint("TRACE_BEGIN")
  local ids = setmetatable({}, {__mode = "k"})
  local nid = 0
  local n = 0
  local function log(proto, field, key)
    local f = debug.info(2, "f")
    local id = ids[f]
    if not id then nid = nid + 1; id = nid; ids[f] = id end
    local line = debug.info(2, "l")
    n = n + 1
    if n <= 150 then
      __realprint("RD", proto, field, tostring(key), "fn", id, "line", tostring(line))
    end
  end
  for i = 1, #y do
    local p = y[i]
    if type(p) == "table" then
      for _, f in ipairs({2,3,4,5,7,8,9,10,11}) do
        local t = p[f]
        if type(t) == "table" and not getmetatable(t) then
          setmetatable(t, {__index = function(t, k)
            log(i, f, k)
            return rawget(t, k)
          end})
        end
      end
    end
  end
  local function proxy(t, tag)
    if type(t) == "table" and not getmetatable(t) then
      setmetatable(t, {__index = function(tt, k)
        log(tag, 0, k)
        return rawget(tt, k)
      end})
    end
  end
  proxy(y, "Y")
  for _, k in ipairs({2, 10, 17, 22, 43}) do
    proxy(G and G[k], "G" .. tostring(k))
  end
  proxy(G, "G")
  __realprint("TRACE_READY", #y)
end
function __BIG(y)
  __realprint("CT_BEGIN")
  local shown = 0
  for i = 1, #y do
    local p = y[i]
    if type(p) == "table" then
      for f = 2, 11 do
        local t = p[f]
        if type(t) == "table" then
          for k, v in pairs(t) do
            if type(v) == "string" and (#v > 12 or v:find("Fire") or v:find("Boulder")) then
              __realprint("CSTR", i, f, tostring(k), #v, string.format("%q", v:sub(1, 60)))
              shown = shown + 1
              break
            end
          end
        end
        if shown > 25 then break end
      end
    end
    if shown > 25 then break end
  end
  __realprint("CT_END", shown)
end
function __BIG(y)
  local best, bl = nil, -1
  local tot = 0
  for i = 1, #y do
    local p = y[i]
    if type(p) == "table" and type(p[3]) == "table" then
      local n = #p[3]
      tot = tot + n
      if n > bl then bl, best = n, i end
    end
  end
  __realprint("BIG_TOTAL", #y, tot, "max", bl, "proto", best)
  local p = y[best]
  for f = 1, 11 do
    local v = p[f]
    if type(v) == "table" then
      __realprint("F", f, "table", "#", #v, "HEAD", __join(v, 40))
    else
      __realprint("F", f, type(v), tostring(v))
    end
  end
  __realprint("A3", __join(p[3], 400))
  __realprint("A4", __join(p[4], 400))
  __realprint("A5", __join(p[5], 400))
end
function __PROTOS(y)
  __realprint("PROTOS_BEGIN")
  local fieldstats = {}
  local total_num = 0
  for i = 1, #y do
    local p = y[i]
    if type(p) == "table" then
      local keys = {}
      for k in pairs(p) do keys[#keys+1] = k end
      table.sort(keys, function(a,b) return tostring(a) < tostring(b) end)
      for _, k in ipairs(keys) do
        local v = p[k]
        local t = type(v)
        local key = tostring(k) .. ":" .. t
        fieldstats[key] = (fieldstats[key] or 0) + 1
        if t == "table" then
          local n = 0
          for _ in pairs(v) do n = n + 1 end
          if n > 100 then
            total_num = total_num + n
            if i <= 3 then __realprint("BIGFIELD", i, k, "n", n, "#", #v, "sample", tostring(v[1]), tostring(v[2]), tostring(v[3])) end
          end
        end
      end
      if i <= 2 then
        local out = {}
        for _, k in ipairs(keys) do out[#out+1] = tostring(k) .. "=" .. type(p[k]) .. (type(p[k]) == "table" and ("#" .. tostring(#p[k])) or "") end
        __realprint("PROTO", i, table.concat(out, " "))
      end
    end
  end
  local ks = {}
  for k in pairs(fieldstats) do ks[#ks+1] = k end
  table.sort(ks)
  for _, k in ipairs(ks) do __realprint("FS", k, fieldstats[k]) end
  __realprint("PROTOS_END", total_num)
end
function __DUMPY(y, G)
  __realprint("YDUMP_BEGIN")
  if type(y) == "table" then
    local n, num, str, tab, fn = 0, 0, 0, 0, 0
    for k, v in pairs(y) do
      n = n + 1
      local t = type(v)
      if t == "number" then num = num + 1 elseif t == "string" then str = str + 1 elseif t == "table" then tab = tab + 1 elseif t == "function" then fn = fn + 1 end
    end
    __realprint("Y", "len", #y, "n", n, "num", num, "str", str, "tab", tab, "fn", fn)
    local out = {}
    for i = 1, math.min(#y, 60) do
      local v = y[i]
      out[#out+1] = type(v) == "table" and ("tbl#" .. tostring(#v)) or (type(v) == "number" and string.format("%.8g", v) or string.format("%q", tostring(v)))
    end
    __realprint("YHEAD", table.concat(out, " "))
  else
    __realprint("Y", type(y), tostring(y))
  end
  local c = G[2]
  if type(c) == "table" then
    for i = 1, math.min(9, #c) do
      local v = c[i]
      if type(v) == "table" then
        local out = {}
        for k = 1, math.min(#v, 8) do out[#out+1] = tostring(v[k]) end
        __realprint("C2", i, "tbl", #v, table.concat(out, ","))
      else
        __realprint("C2", i, type(v), tostring(v))
      end
    end
  end
  __realprint("YDUMP_END")
end
function __FIND(t, tag, depth)
  __visited = {}
  __hits = 0
  __realprint("FIND_BEGIN", tag)
  __findwalk(t, tag, depth)
  __realprint("FIND_END", __hits)
end
local __visited2 = {}
local __strings = {}
local function __walk(t, depth, tag)
  if depth <= 0 or type(t) ~= "table" then return end
  if __visited[t] then return end
  __visited[t] = true
  for k, v in pairs(t) do
    if type(v) == "string" then
      if #v >= 5 then __strings[#__strings+1] = tag .. ":" .. #v .. ":" .. v:sub(1, 40):gsub("%c", "?") end
    elseif type(v) == "table" then
      __walk(v, depth - 1, tag)
    end
    if #__strings > 400 then return end
  end
end
function __SCAN(t, depth, tag)
  __visited = {}
  __strings = {}
  __walk(t, depth, tag)
  __realprint("SCAN", tag, #__strings)
  for i = 1, math.min(#__strings, 80) do __realprint("STR", __strings[i]) end
end
function __DUMPG(G)
  __realprint("GDUMP_BEGIN")
  for k = 1, 60 do
    local v = G[k]
    if v ~= nil then
      local t = type(v)
      if t == "table" then
        local n = 0
        for _ in pairs(v) do n = n + 1 end
        local sample = {}
        local i = 0
        for kk, vv in pairs(v) do
          i = i + 1
          if i <= 12 then sample[#sample+1] = tostring(kk) .. "=" .. __VAL(vv) end
          if i > 300000 then break end
        end
        __realprint("G", k, "table", "#", #v, "n", n, table.concat(sample, " "))
      else
        __realprint("G", k, t, __VAL(v))
      end
    end
  end
  local code = G[2]
  if type(code) == "table" then
    local out = {}
    for i = 1, math.min(#code, 120) do out[#out+1] = __VAL(code[i]) end
    __realprint("G2_HEAD", table.concat(out, " "))
    __realprint("G2_LEN", #code)
  end
  __realprint("GDUMP_END")
end
function __PROBE4(m, j, T, O, u)
  __realprint("PROBE_BEGIN")
  __FIELD("m", m) __FIELD("j", j) __FIELD("T", T) __FIELD("O", O)
  for k = 1, 12 do __FIELD("u[" .. k .. "]", u[k]) end
  for k = 15, 24 do __FIELD("u[" .. k .. "]", u[k]) end
  __realprint("PROBE_END")
end
function __PROBE(u)
  __realprint("PROBE_BEGIN", tostring(u))
  local keys = {}
  for k in pairs(u) do keys[#keys+1] = k end
  table.sort(keys, function(a, b) return tostring(a) < tostring(b) end)
  for _, k in ipairs(keys) do
    local v = u[k]
    local t = type(v)
    if t == "table" then
      local n = 0
      for _ in pairs(v) do n = n + 1 end
      local sample = {}
      local i = 0
      for kk, vv in pairs(v) do
        i = i + 1
        if i <= 6 then sample[#sample+1] = tostring(kk) .. ":" .. type(vv) .. "=" .. (type(vv) == "number" and string.format("%.6g", vv) or type(vv) == "string" and ("'" .. vv:sub(1, 20) .. "'") or type(vv) == "table" and ("tbl#" .. tostring(#vv)) or type(vv))
        end
        if i > 200000 then break end
      end
      __realprint("FIELD", tostring(k), "table", "len", #v, "count", n, "sample", table.concat(sample, " | "))
    elseif t == "string" then
      __realprint("FIELD", tostring(k), "string", #v, string.format("%q", v:sub(1, 40)))
    else
      __realprint("FIELD", tostring(k), t, tostring(v))
    end
  end
  __realprint("PROBE_END")
end
'''

spy = r'''
local __realLS = loadstring
local __lsn = 0
loadstring = function(src, name)
  __lsn = __lsn + 1
  if type(src) == "string" and __lsn <= 40 then
    __realprint("LS", __lsn, #src, string.format("%q", src:sub(1, 200)))
  end
  return __realLS(src, name)
end
'''
tail = r"""
local __ok,__err = pcall(function()
""" + stage2 + r"""
end)
__realprint("EXEC1", __ok, type(__err))
if __ok then
  for lvl = 1, 3 do
    local i = debug.info(__err, "slnf")
    __realprint("FNINFO", lvl, tostring(i))
  end
  __realprint("ARITY", debug.info(__err, "a"))
  local __ok2,__err2 = pcall(__err)
  __realprint("EXEC2", __ok2, tostring(__err2))
end
"""
profile = r"""
local __CNT = {}
local __FIRST = {}
local __LAST = {}
__GAME = 0
local __realsetfenv = setfenv
setfenv = function(f, env)
  if type(env) == "table" then
    local mt = getmetatable(env)
    if type(mt) ~= "table" then mt = {} end
    if mt.__index == nil then mt.__index = _G; setmetatable(env, mt) end
  end
  return __realsetfenv(f, env)
end
local __CALLS = 0
local __FN2NAME = {}
local __ERRDONE = false
local __realerror = error
function error(msg, lvl)
  if not __ERRDONE then
    __ERRDONE = true
    __realprint("ERRMSG", tostring(msg))
    for lv = 2, 14 do
      local f = debug.info(lv, "f")
      if not f then break end
      local nm = __FN2NAME[f] or "?"
      local line = debug.info(lv, "l")
      __realprint("TRACE", lv, nm, tostring(line))
    end
  end
  return __realerror(msg, lvl)
end
function __WRAP(T)
  for k, v in pairs(T) do
    if type(v) == "function" then __FN2NAME[v] = tostring(k) end
  end
  for k, v in pairs(T) do
    if type(v) == "function" then
      __CNT[k] = 0
      __FIRST[k] = {}
      T[k] = function(...)
        __CNT[k] = __CNT[k] + 1
        __CALLS = __CALLS + 1
        if __CALLS > 40000000 then error("__LUAD_STOP__") end
        if __CALLS % 1000000 == 0 then __realprint("BEAT", __CALLS, k) end
        local a = table.pack(...)
        local ps = {}
        for i = 1, math.min(4, a.n) do
          local x = a[i]
          if type(x) == "number" then ps[#ps+1] = string.format("%.10g", x)
          elseif type(x) == "string" then ps[#ps+1] = string.format("%q", x:sub(1, 16))
          elseif type(x) == "boolean" then ps[#ps+1] = tostring(x)
          end
        end
        __LAST[#__LAST+1] = k .. "(" .. table.concat(ps, ",") .. ")"
        if #__LAST > 4000 then table.remove(__LAST, 1) end
        local n = #__FIRST[k]
        if n < 6 then
          local parts = {}
          local a = table.pack(...)
          for i = 1, math.min(4, a.n) do
            local x = a[i]
            parts[#parts+1] = type(x) == "number" and string.format("%.8g", x) or type(x) == "string" and string.format("%q", x:sub(1, 20)) or type(x)
          end
          __FIRST[k][n+1] = table.concat(parts, ",")
        end
        return v(...)
      end
    end
  end
end
local function __REPORT()
  local ks = {}
  for k, n in pairs(__CNT) do ks[#ks+1] = k end
  table.sort(ks, function(a, b) return __CNT[a] > __CNT[b] end)
  __realprint("CALLS", __CALLS, "METHODS", #ks, "GAMEHITS", __GAME)
  for i = 1, #__LAST do __realprint("T", i, __LAST[i]) end
  __realprint("MISSING", table.concat(__MISS, ","))
  for i = 1, math.min(#ks, 15) do
    local k = ks[i]
    __realprint("HOT", k, __CNT[k], table.concat(__FIRST[k], " || "))
  end
end
"""
tail = r"""
local __ok,__err = pcall(function()
""" + stage2 + r"""
end)
if not __ok then __REPORT() end
__realprint("EXEC1", __ok, type(__err))
if __ok then
  local __ok2,__err2 = pcall(__err)
  __REPORT()
  __realprint("EXEC2", __ok2, tostring(__err2))
end
"""
out = shim + spy + profile + tail
open('/tmp/opencode/run_stage2.luau', 'w').write(out)
print("wrote", len(out), "R", len(rbytes))
