{
  "creator": "Lars Rocha",
  "license": "MIT",
  "adapter": "rust-labs-1",
  "build": "Rust 1.88.0, wasm32-unknown-unknown; locked offline build. Place the seven original engine crates under reference/engine-labs/crates, plus source traffic.rs and synth.rs at reference/engine-labs. Source manifests pin their exact bytes. The reviewed source archives contain these files.",
  "files": {
    "experiments/engine-labs/src/lib.rs": "//! Bounded, data-only inspector adapter. Original engine work: Lars Rocha.\n//! No engine source or numerical fixture is changed by this adapter.\nuse serde_json::{json, Value};\n#[allow(dead_code)]\n#[path = \"../../../reference/engine-labs/traffic.rs\"]\nmod traffic;\n#[allow(dead_code)]\n#[path=\"../../../reference/engine-labs/synth.rs\"]\nmod synth;\nfn num(p: &Value, k: &str, d: f64, lo: f64, hi: f64) -> f64 {\n    p.get(k)\n        .and_then(Value::as_f64)\n        .filter(|n| n.is_finite())\n        .unwrap_or(d)\n        .clamp(lo, hi)\n}\nfn word(p: &Value) -> &str {\n    p.get(\"word\")\n        .and_then(Value::as_str)\n        .filter(|s| s.len() <= 128)\n        .unwrap_or(\"lars\")\n}\nfn number(p: &Value) -> i64 {\n    num(p, \"address\", 127., -1_000_000., 1_099_511_627_775.) as i64\n}\nfn kind(p: &Value) -> &'static str {\n    match p[\"kind\"].as_str().unwrap_or(\"rail\") {\n        \"silo\" => \"silo\",\n        \"scatter\" => \"scatter\",\n        \"mast\" => \"mast\",\n        _ => \"rail\",\n    }\n}\nfn car(p: &Value) -> Value {\n    let recipe = wmodel::body::Recipe::new(\n        number(p),\n        num(p, \"paint\", 0., -1e6, 1e12) as i64,\n        num(p, \"trim\", 0., -1e6, 1e12) as i64,\n    );\n    let c = wmodel::body::resolve(&recipe);\n    let s = &c.shell;\n    let sections: Vec<_> = s\n        .sections\n        .iter()\n        .map(|t| json!([t.x, t.floor, t.top, t.half]))\n        .collect();\n    json!({\"kind\":\"car\",\"class\":c.class,\"rank\":c.rank,\"body\":c.recipe.body,\"paint\":c.recipe.paint,\"trimAddress\":c.recipe.trim,\"colour\":c.colour,\"trim\":c.trim,\"length\":s.length,\"wheelbase\":s.wheelbase,\"axles\":[s.axle_r(),s.axle_f()],\"track\":s.track,\"tyre\":s.tyre_r,\"sections\":sections,\"plate\":wmodel::body::car_code(&recipe),\"why\":c.why.iter().map(|w|json!({\"field\":w.field,\"value\":w.value,\"because\":w.because})).collect::<Vec<_>>()})\n}\nfn terrain(p: &Value, id: u64) -> Value {\n    let n = num(p, \"size\", 32., 8., 64.) as usize;\n    let step = num(p, \"step\", 32., 1., 128.) as i64;\n    let x = num(p, \"x\", 2200., -32768., 32768.) as i64;\n    let z = num(p, \"z\", 0., -32768., 32768.) as i64;\n    let mut w = if id == 89 {\n        wfield::wilds::from_word(word(p))\n    } else {\n        wfield::World::great_range()\n    };\n    if id == 90 {\n        w.ridges.truncate(num(p, \"ridges\", 3., 1., 3.) as usize);\n        for r in &mut w.ridges {\n            r.z += num(p, \"offset\", 0., -2000., 2000.);\n        }\n    }\n    if id == 91 {\n        let mut f = wfield::rift::Fissures::default();\n        f.v = num(p, \"exponent\", 5., 2., 10.);\n        f.depth = num(p, \"depth\", 22., 0., 100.);\n        f.amp = 0.;\n        w.fissures = Some(f);\n    }\n    let stature = num(p, \"stature\", 1., 0.1, 3.);\n    w.water = if id == 89 {\n        w.water + num(p, \"water\", 0., -300., 300.)\n    } else {\n        num(p, \"water\", w.water, 0., 300.)\n    };\n    let f = wfield::sample(&w, wfield::Region::new(x, z, n, n, step));\n    let mut points = Vec::new();\n    let mut land_sum = 0.;\n    let mut land = 0;\n    for j in 0..n {\n        for i in 0..n {\n            let c = f.cell(i, j);\n            let height = wfield::scale_height(c.height, w.water, stature, 1.);\n            let col = wfield::palette(w.pal, height, c.colour, w.water, w.top)[0];\n            if !c.wet {\n                land_sum += height;\n                land += 1;\n            }\n            points.push(json!([\n                x + i as i64 * step,\n                z + j as i64 * step,\n                height,\n                col[0],\n                col[1],\n                col[2],\n                c.wet,\n                c.ground,\n                c.colour,\n                c.height\n            ]));\n        }\n    }\n    let ridges:Vec<_>=w.ridges.iter().map(|r|json!({\"z\":r.z,\"amplitude\":r.a,\"rank\":r.v_ref,\"width\":r.w,\"offset\":r.g,\"massif\":r.massif})).collect();\n    json!({\"kind\":\"terrain\",\"points\":points,\"size\":n,\"step\":step,\"x\":x,\"z\":z,\"seed\":w.seed,\"g0\":w.g0,\"water\":w.water,\"top\":w.top,\"ridges\":ridges,\"palette\":format!(\"{:?}\",w.pal),\"stature\":stature,\"family\":if id==89 {match wlaw::hash::at(w.seed,0,0,0)%8 {5|6=>\"archipelago\",7=>\"rift\",_=>\"alpine\"}}else{\"great-range\"},\"landSamples\":land,\"landMean\":if land>0 {Some(land_sum/land as f64)}else{None},\"samples\":n*n,\"numericBytes\":n*n*10*8})\n}\npub fn report(id: u64, p: &Value) -> Value {\n    if id == 85 {\n        if let Some(op) = p[\"fixture\"].as_str() {\n            let a = &p[\"args\"];\n            let u = |i: usize| a[i].as_u64().unwrap_or(0) as u32;\n            let actual = match op {\n                \"streamOf\" => json!(wlaw::hash::stream_of(a[0].as_str().unwrap_or(\"\"))),\n                \"mix\" => json!(wlaw::hash::mix(u(0))),\n                \"at\" => json!(wlaw::hash::at(\n                    u(0),\n                    a[1].as_i64().unwrap_or(0) as i32,\n                    a[2].as_i64().unwrap_or(0) as i32,\n                    u(3)\n                )),\n                \"unit\" => json!(format!(\"{:016x}\", wlaw::hash::unit(u(0)).to_bits())),\n                \"v2\" => json!(wlaw::v2(a[0].as_i64().unwrap_or(0))),\n                _ => Value::Null,\n            };\n            return json!({\"actual\":actual});\n        }\n    }\n\n    match id {\n        85 | 110 | 118 => {\n            let seed = wlaw::hash::stream_of(word(p));\n            let x = number(p) as i32;\n            let stream = wlaw::hash::stream_of(p[\"stream\"].as_str().unwrap_or(\"car.length\"));\n            let h = wlaw::hash::at(seed, x, 0, stream);\n            let u = wlaw::hash::unit(h);\n            json!({\"kind\":\"hash\",\"seed\":seed,\"stream\":stream,\"address\":x,\"hash\":h,\"unit\":u,\"bits\":format!(\"{:016x}\",u.to_bits()),\"bars\":(0..64).map(|i|wlaw::hash::unit(wlaw::hash::at(seed,x.wrapping_add(i),0,stream))).collect::<Vec<_>>()})\n        }\n        86 | 88 | 120 => {\n            let mut c = car(p);\n            if let Some(code) = p[\"code\"].as_str() {\n                c[\"decoded\"]=wmodel::body::car_decode(code).map(|r|json!({\"body\":r.body,\"paint\":r.paint,\"trim\":r.trim,\"version\":r.version})).unwrap_or(Value::Null);\n            }\n            c\n        }\n        87 => {\n            let mut c = car(p);\n            let raw = wlaw::ridge::epic_ridge(\n                number(p),\n                128,\n                num(p, \"rank\", 6., 2., 12.) as u32,\n                num(p, \"massif\", 0.4, 0., 1.),\n            );\n            let max = raw.iter().copied().fold(0f64, f64::max).max(1e-9);\n            let clearance = num(p, \"clearance\", 1., 0.6, 1.8);\n            let amp = num(p, \"amplitude\", 0.5, 0., 1.);\n            let length = c[\"length\"].as_f64().unwrap();\n            let pts: Vec<_> = raw\n                .iter()\n                .enumerate()\n                .map(|(i, h)| {\n                    json!([\n                        i as f64 / 127. * length - length / 2.,\n                        clearance + amp * h / max,\n                        *h\n                    ])\n                })\n                .collect();\n            c[\"roof\"] = json!(pts);\n            c[\"clearance\"] = json!(clearance);\n            c[\"experimental\"] = json!(true);\n            c\n        }\n        89 | 90 | 91 | 104 | 106 | 116 | 119 => terrain(p, id),\n        92 => {\n            let k = num(p, \"order\", 5., 1., 8.) as u32;\n            let seed = wlaw::hash::stream_of(word(p));\n            let n = wfield::river::network(seed, k, num(p, \"meander\", 0.3, 0., 1.));\n            json!({\"kind\":\"river\",\"segments\":n.segs,\"truncated\":n.truncated,\"order\":k,\"seed\":seed})\n        }\n        93 | 112 => {\n            let a = num(p, \"address\", 0., 0., 1e9) as i64;\n            let width = num(p, \"span\", 512., 16., 4096.) as i64;\n            let k = num(p, \"rank\", 7., 1., 18.) as u32;\n            let rows: Vec<_> = (a..a + width)\n                .map(|g| {\n                    let r = wlaw::v2(g + 1);\n                    json!([\n                        g,\n                        r,\n                        wbuild::city::rank_of(g, 18),\n                        ([\n                            \"saloon\", \"coupe\", \"estate\", \"pickup\", \"van\", \"muscle\", \"fastback\",\n                            \"wedge\"\n                        ][(r as usize).min(7)]),\n                        wlaw::CUM[(r as usize).min(wlaw::VMAX)]\n                    ])\n                })\n                .collect();\n            json!({\"kind\":\"ranks\",\"rows\":rows,\"next\":wbuild::city::next_settlement(a,k),\"biggest\":wbuild::city::biggest_between(a,a+width-1),\"rank\":k})\n        }\n        94 => {\n            let city = wbuild::city::City::new(word(p), \"city\");\n            let cx = num(p, \"x\", 0., -128., 128.) as i64;\n            let cz = num(p, \"z\", 0., -128., 128.) as i64;\n            let r = num(p, \"radius\", 4., 1., 8.) as i64;\n            let mut rows = Vec::new();\n            let mut coords: Vec<_> = (cz - r..=cz + r)\n                .flat_map(|z| (cx - r..=cx + r).map(move |x| (x, z)))\n                .collect();\n            if p[\"reverse\"].as_bool() == Some(true) {\n                coords.reverse();\n            }\n            for (x, z) in coords {\n                let t = city.plot(x, z);\n                let area = t.side_x * t.side_z;\n                let a = area - city.whiten(x, z, 131, 17) % (area / 3).max(1);\n                rows.push(json!({\"x\":x,\"z\":z,\"level\":t.level,\"width\":t.w,\"squareArea\":a,\"squareRoot\":wlaw::isqrt(a),\"remainder\":t.rem,\"storeys\":t.storeys,\"lot\":format!(\"{:?}\",t.lot),\"streets\":[t.street_x,t.street_z],\"key\":city.edge_key(x,z,true)}));\n            }\n            json!({\"kind\":\"city\",\"plots\":rows,\"radius\":r})\n        }\n        96 => {\n            let r = wtd::road::Road::lay(number(p));\n            let law = wtd::road::law();\n            let rows: Vec<_> = (0..=128)\n                .map(|i| {\n                    let s = r.len * i as f64 / 128.;\n                    let (x, z) = r.at(s);\n                    json!([x, z, s, r.off(x, z)])\n                })\n                .collect();\n            json!({\"kind\":\"path\",\"points\":rows,\"length\":r.len,\"vertices\":r.pts,\"decisions\":(0..=11).map(|i|{let a=number(p)+i*7;json!({\"address\":a,\"wide\":law.contains(a),\"far\":law.contains(a+1)})}).collect::<Vec<_>>()})\n        }\n        97 => {\n            let path = num(p, \"path\", 318., 100., 800.);\n            let at = num(p, \"position\", 100., 0., 800.).min(path);\n            let level = num(p, \"level\", 0., 0., 4.) as i64;\n            let mut rows = Vec::new();\n            for (i, k) in [\"silo\", \"rail\", \"scatter\", \"mast\"].iter().enumerate() {\n                let pos = (at + i as f64 * 40.).min(path);\n                let t = wtd::Tower::new(k, pos, level);\n                let (a, b) = wtd::covers(&t, path);\n                let spec = wtd::tower_at(k, level);\n                rows.push(json!({\"kind\":k,\"at\":pos,\"a\":a,\"b\":b,\"reach\":spec.reach,\"dps\":spec.dps,\"cost\":wtd::tower_cost(k,level)}));\n            }\n            json!({\"kind\":\"intervals\",\"path\":path,\"towers\":rows,\"level\":level})\n        }\n        98 => {\n            let mut r = wtd::Recipe::default();\n            r.path = num(p, \"path\", 318., 100., 500.);\n            r.waves = wtd::default_waves(num(p, \"waves\", 5., 1., 8.) as usize);\n            if p[\"opening\"].as_str() != Some(\"empty\") {\n                r.towers = vec![wtd::Tower::new(kind(p), r.path / 2., 0)];\n            }\n            let mut results = Vec::new();\n            for policy in [None, Some(wtd::Policy::Upgrade), Some(wtd::Policy::Build)] {\n                r.policy = policy;\n                let o = wtd::simulate(&r);\n                results.push(match o{Ok(o)=>json!({\"policy\":format!(\"{:?}\",policy),\"won\":o.won,\"lives\":o.lives,\"money\":o.money,\"ticks\":o.ticks,\"log\":o.log.iter().map(|v|json!([v.wave,v.money,v.lives,v.stopped,v.leaked])).collect::<Vec<_>>()}),Err(e)=>json!({\"error\":format!(\"{:?}\",e)})});\n            }\n            json!({\"kind\":\"economy\",\"results\":results})\n        }\n        100 => {\n            let c = wcraft::course::Course::new(\n                wlaw::hash::stream_of(word(p)),\n                wcraft::course::Circuit {\n                    radius: num(p, \"radius\", 300., 100., 1200.),\n                    squash: num(p, \"squash\", 0.62, 0.2, 1.),\n                    ..Default::default()\n                },\n            );\n            let points: Vec<_> = (0..=256)\n                .map(|i| {\n                    let a = c.at(c.l * i as f64 / 256.);\n                    json!([a.x, a.z, a.s, a.th])\n                })\n                .collect();\n            json!({\"kind\":\"path\",\"points\":points,\"length\":c.l,\"gates\":c.gates(num(p,\"gates\",12.,4.,24.) as usize).iter().map(|a|json!([a.x,a.z,a.s,a.th])).collect::<Vec<_>>()})\n        }\n        101 | 108 => {\n            let mut v = wcraft::Vehicle::new(wcraft::PODS[0], 0., 0., 0.);\n            v.y = num(p, \"height\", 50., 0., 500.);\n            v.speed = num(p, \"speed\", 20., 0., 100.);\n            let mut rows = vec![json!([0., v.y, v.speed, v.x, v.z, false])];\n            let ticks = num(p, \"ticks\", 360., 1., 1200.) as usize;\n            let dt = 1. / 120.;\n            let lift = wcraft::air::Lift {\n                climb: p[\"lift\"].as_str() != Some(\"dive\"),\n                dive: p[\"lift\"].as_str() == Some(\"dive\"),\n            };\n            let fps = p[\"fps\"]\n                .as_str()\n                .and_then(|s| s.parse::<f64>().ok())\n                .unwrap_or(60.)\n                .clamp(30., 144.);\n            let mut clock = wcraft::Clock::default();\n            let mut schedule = Vec::new();\n            let mut earned = 0;\n            while earned < ticks {\n                let n = clock.advance(1. / fps) as usize;\n                earned += n;\n                schedule.push(n);\n            }\n            for i in 0..ticks {\n                let f = wcraft::air::step_plane(\n                    &mut v,\n                    wcraft::Input {\n                        throttle: num(p, \"throttle\", 0., 0., 1.),\n                        steer: num(p, \"steer\", 0., -1., 1.),\n                        ..Default::default()\n                    },\n                    lift,\n                    wcraft::air::Wing::default(),\n                    dt,\n                    0.,\n                    200.,\n                );\n                rows.push(json!([\n                    (i + 1) as f64 * dt,\n                    v.y,\n                    v.speed,\n                    v.x,\n                    v.z,\n                    f.stalled\n                ]));\n            }\n            json!({\"kind\":\"flight\",\"points\":rows,\"schedule\":schedule,\"earnedTicks\":earned,\"displayFps\":fps,\"finalBlend\":clock.blend(),\"ticks\":ticks,\"dt\":dt,\"ceiling\":wcraft::air::sky_ceiling(0.,600.,200.),\"stall\":wcraft::air::STALL})\n        }\n        102 => {\n            let mut b = wcraft::arena::Ball::new(0., num(p, \"z\", 0., -20., 20.), 0., 1.);\n            b.y = num(p, \"height\", 12., 1., 40.);\n            b.vx = num(p, \"speed\", 20., 0., 100.);\n            let mut strike = None;\n            if p[\"mode\"].as_str() == Some(\"strike\") {\n                let mut c = wcraft::Vehicle::new(wcraft::PODS[0], -2., b.z, 0.);\n                c.vx = b.vx;\n                b.vx = 0.;\n                strike = b.struck_by(&c, p[\"boost\"].as_str() == Some(\"yes\"));\n            }\n            let pitch = wcraft::arena::Pitch::default();\n            let mut pts = Vec::new();\n            for i in 0..=600 {\n                pts.push(json!([\n                    i as f64 / 120.,\n                    b.y,\n                    b.x,\n                    b.z,\n                    b.vx,\n                    b.vy,\n                    format!(\"{:?}\", b.scored(&pitch))\n                ]));\n                b.step(1. / 120., &pitch);\n            }\n            json!({\"kind\":\"ball\",\"points\":pts,\"strike\":strike,\"gravity\":wcraft::arena::BALL_G,\"wall\":pitch.hx,\"mouth\":pitch.mouth,\"bar\":pitch.bar})\n        }\n        103 => {\n            let speed = num(p, \"speed\", 60., 10., 150.);\n            let d = num(p, \"distance\", 100., 1., 1000.);\n            let h = num(p, \"height\", 0., -30., 100.);\n            let g = wcraft::gun::Gun {\n                shell: speed,\n                elev: 0.5,\n                reload: 1.,\n                traverse: 1.,\n                scale: 1.,\n            };\n            let elev = wcraft::gun::elevation_for(&g, d, p[\"arc\"].as_str() == Some(\"high\"), h);\n            let mut sh = wcraft::gun::fire(\n                wcraft::gun::At {\n                    x: 0.,\n                    y: 0.,\n                    z: 0.,\n                },\n                0.,\n                &g,\n                wcraft::gun::Aim::Elev(elev),\n                0,\n                1.,\n            );\n            let mut pts = Vec::new();\n            for i in 0..1200 {\n                pts.push(json!([sh.x, sh.y, sh.z, i as f64 / 120.]));\n                if matches!(\n                    wcraft::gun::step_shell(&mut sh, 1. / 120., -30.),\n                    wcraft::gun::Flight::Ground | wcraft::gun::Flight::Gone\n                ) {\n                    break;\n                }\n            }\n            json!({\"kind\":\"trajectory\",\"points\":pts,\"elevation\":elev,\"distance\":d,\"height\":h,\"reachable\":speed.powi(4)-24.*(24.*d*d+2.*h*speed*speed)>=0.,\"gravity\":24.})\n        }\n        107 => {\n            let c = wmodel::body::resolve(&wmodel::body::Recipe::new(number(p), 0, 0));\n            let model = c.model();\n            let far = num(p, \"distance\", 30., 0., 500.);\n            let hd = wmodel::hd::level_for(far, true, true);\n            let count = num(p, \"count\", 3., 1., 30.) as usize;\n            let mut out = wmodel::hd::Build::default();\n            let mut triangles=0;let mut bytes=0;\n            for _ in 0..count {\n                out.v.clear();out.i.clear();\n                wmodel::hd::draw(&mut out, &model, &wmodel::Pose::default(), hd);\n                triangles+=out.tris();bytes+=out.v.len()*4+out.i.len()*4;\n            }\n            let mut value = car(p);\n            value[\"copies\"] = json!(count);\n            value[\"triangles\"] = json!(triangles);\n            value[\"residentMeshBytes\"]=json!(out.v.len()*4+out.i.len()*4);\n            value[\"wire\"]=json!(out.i.chunks(3).step_by((out.tris()/600).max(1)).map(|t|t.iter().map(|i|out.v[*i as usize*10..*i as usize*10+3].to_vec()).collect::<Vec<_>>()).collect::<Vec<_>>());\n            value[\"meshBytes\"] = json!(bytes);\n            value[\"parts\"] = json!(model.len());\n            value[\"distance\"] = json!(far);\n            value\n        }\n        111 => {\n            let stride = num(p, \"stride\", 3., 1., 32.) as i64;\n            let origin = num(p, \"origin\", 0., -64., 64.) as i64;\n            let xor = num(p, \"xor\", 5., 0., 63.) as i64;\n            let law =\n                wlaw::sieve::Law::new(0, 256, stride, origin, 1, 1, 0, xor, 4, vec![1]).unwrap();\n            let rows: Vec<_> = (0..256)\n                .map(|a| {\n                    json!([\n                        a,\n                        law.contains(a),\n                        (a - origin).rem_euclid(stride),\n                        (a ^ xor).rem_euclid(4)\n                    ])\n                })\n                .collect();\n            json!({\"kind\":\"selection\",\"rows\":rows,\"stride\":stride,\"origin\":origin,\"xor\":xor})\n        }\n        115 => {\n            use wbuild::walk::*;\n            let h = num(p, \"obstacle\", 0.3, 0., 3.);\n            let s = Solid {\n                x: 2.,\n                y: 0.,\n                z: -1.,\n                w: 1.,\n                h,\n                d: 2.,\n            };\n            let body = Body {\n                r: num(p, \"radius\", 0.3, 0.1, 1.5),\n                h: 1.7,\n                step: num(p, \"step\", 0.35, 0., 1.),\n            };\n            let mut w = Walker::at(0., 0., 0.);\n            let mut pts = Vec::new();\n            for i in 0..120 {\n                let m = walk_report(&[s], body, &mut w, 0.04, 0., |_, _| 0.);\n                pts.push(json!([i, w.y, w.x, m.hit]));\n            }\n            json!({\"kind\":\"walk\",\"points\":pts,\"obstacle\":h,\"radius\":body.r,\"step\":body.step})\n        }\n        117 => {\n            if p[\"voice\"].as_str()==Some(\"vehicle\") {let mut e=synth::Engine::default();let mut pcm=Vec::new();for i in 0..48000 {if i%400==0 {e.aim(num(p,\"speed\",30.,0.,100.),80.,false,false,1./120.);}pcm.push(e.next());}return json!({\"kind\":\"voice\",\"pcm\":pcm,\"sampleRate\":48000,\"pitch\":e.base(),\"gain\":e.gain(),\"duration\":1.});}\n            let a = number(p);\n            json!({\"kind\":\"notes\",\"notes\":(a..a+256).filter_map(|g|wlaw::song::note_at(g).map(|n|json!({\"address\":g,\"rank\":wlaw::v2(g+1),\"frequency\":n.freq,\"volume\":n.vol,\"duration\":n.secs,\"bright\":n.bright}))).collect::<Vec<_>>()})\n        }\n        95 => {\n            let city = wbuild::city::City::new(word(p), \"city\");\n            let grid = traffic::Grid::new((0., 0.), 1.6);\n            let mut ground = |_: f64, _: f64| 0.;\n            let mut fleet = traffic::Fleet::on_streets(\n                &city,\n                grid,\n                (0., 0.),\n                8,\n                num(p, \"cars\", 4., 1., 8.) as usize,\n                wcraft::drive::Driver::default(),\n                wbuild::walk::Body {\n                    r: 2.2,\n                    h: 1.5,\n                    step: 0.3,\n                },\n                &mut ground,\n            );\n            let mut frames = Vec::new();\n            let ticks = num(p, \"ticks\", 600., 1., 1200.) as usize;\n            for i in 0..ticks {\n                if i % 4 == 0 {\n                    frames.push(json!(fleet\n                        .cars\n                        .iter()\n                        .map(|c| [c.v.x, c.v.z, c.v.yaw, c.v.speed, c.lane])\n                        .collect::<Vec<_>>()));\n                }\n                fleet.drive(&city, 1. / 60., &mut ground, &traffic::Solids::new());\n            }\n            json!({\"kind\":\"traffic\",\"frames\":frames,\"cars\":fleet.cars.len(),\"seconds\":ticks as f64/60.,\"streets\":city.avenues(-8,8,3,true).iter().map(|s|grid.run(*s,1.).centre()).collect::<Vec<_>>()})\n        }\n        113 => {\n            let k = num(p, \"detail\", 48., 16., 128.);\n            let cam = num(p, \"camera\", 40., -128., 512.);\n            let opts = wmesh::Opts {\n                k,\n                ..Default::default()\n            };\n            let mut tiles = Vec::new();\n            for x in [0, 32] {\n                let t = wmesh::refine_tris(x, 0, 5, cam, 16., &opts);\n                tiles.push(json!({\"x\":x,\"step\":t.step,\"np\":t.np,\"indices\":t.tris}));\n            }\n            json!({\"kind\":\"mesh\",\"tiles\":tiles,\"detail\":k,\"camera\":cam})\n        }\n        114 => {\n            let height = num(p, \"height\", 80., 0., 200.);\n            let origin = num(p, \"x\", 0., -64., 64.);\n            let terrain = |x: f64, z: f64| height * (1. - (-(x * x + z * z) / 800.).exp());\n            let top = height;\n            let hz = wmesh::horizon::bake(origin, 0., 1, 1, 1., top, 1., 512., &terrain);\n            let full = wmesh::horizon::bearings()\n                .iter()\n                .map(|dir| {\n                    let h0 = terrain(origin, 0.);\n                    let mut best = 0f64;\n                    for d in wmesh::horizon::RINGS {\n                        best = best.max((terrain(origin + dir[0] * d, dir[1] * d) - h0) / d);\n                    }\n                    best.atan() as f32\n                })\n                .collect::<Vec<_>>();\n            json!({\"kind\":\"horizon\",\"angles\":hz.p[0].ang,\"full\":full,\"sky\":hz.p[0].sky,\"top\":top,\"height\":terrain(origin,0.),\"points\":(-64..=64).map(|x|[x as f64,terrain(x as f64,0.)]).collect::<Vec<_>>()})\n        }\n        _ => {\n            json!({\"error\":\"Unsupported Rust adapter; this page uses the declared browser adapter\"})\n        }\n    }\n}\n// One synchronous request per instance. JS writes at most 8192 bytes to input_ptr,\n// calls run, then copies output before issuing the next request. No shared memory.\nthread_local! {static BUFFERS:std::cell::RefCell<(Box<[u8;8192]>,Vec<u8>)>=std::cell::RefCell::new((Box::new([0;8192]),Vec::new()));}\n#[no_mangle]\npub extern \"C\" fn input_ptr() -> *mut u8 {\n    BUFFERS.with(|b| b.borrow_mut().0.as_mut_ptr())\n}\n#[no_mangle]\npub extern \"C\" fn run(len: usize) -> *const u8 {\n    BUFFERS.with(|b| {\n        let mut b = b.borrow_mut();\n        let result = if len > 8192 {\n            json!({\"error\":\"Input exceeds 8192 bytes\"})\n        } else {\n            match serde_json::from_slice::<Value>(&b.0[..len]) {\n                Ok(v) => report(v[\"id\"].as_u64().unwrap_or(0), &v[\"params\"]),\n                Err(_) => json!({\"error\":\"Invalid JSON\"}),\n            }\n        };\n        b.1 = serde_json::to_vec(&result).unwrap();\n        b.1.as_ptr()\n    })\n}\n#[no_mangle]\npub extern \"C\" fn output_len() -> usize {\n    BUFFERS.with(|b| b.borrow().1.len())\n}\n",
    "experiments/engine-labs/Cargo.toml": "[package]\nname = \"indexin-labs\"\nversion = \"1.0.0\"\nedition = \"2021\"\nlicense = \"MIT\"\ndescription = \"Bounded browser adapters for Lars Rocha's Indexin engine laws\"\n[lib]\ncrate-type = [\"cdylib\", \"rlib\"]\n[dependencies]\nserde_json = \"=1.0.154\"\nwlaw = { path = \"../../reference/engine-labs/crates/wlaw\" }\nwfield = { path = \"../../reference/engine-labs/crates/wfield\" }\nwmodel = { path = \"../../reference/engine-labs/crates/wmodel\" }\nwcraft = { path = \"../../reference/engine-labs/crates/wcraft\" }\nwbuild = { path = \"../../reference/engine-labs/crates/wbuild\" }\nwmesh = { path = \"../../reference/engine-labs/crates/wmesh\" }\nwtd = { path = \"../../reference/engine-labs/crates/wtd\" }\n[profile.release]\nopt-level = 2\nlto = true\npanic = \"abort\"\nstrip = true\n",
    "experiments/engine-labs/Cargo.lock": "# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 4\n\n[[package]]\nname = \"indexin-labs\"\nversion = \"1.0.0\"\ndependencies = [\n \"serde_json\",\n \"wbuild\",\n \"wcraft\",\n \"wfield\",\n \"wlaw\",\n \"wmesh\",\n \"wmodel\",\n \"wtd\",\n]\n\n[[package]]\nname = \"itoa\"\nversion = \"1.0.18\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682\"\n\n[[package]]\nname = \"memchr\"\nversion = \"2.8.3\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98\"\n\n[[package]]\nname = \"proc-macro2\"\nversion = \"1.0.107\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9\"\ndependencies = [\n \"unicode-ident\",\n]\n\n[[package]]\nname = \"quote\"\nversion = \"1.0.47\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001\"\ndependencies = [\n \"proc-macro2\",\n]\n\n[[package]]\nname = \"serde\"\nversion = \"1.0.229\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba\"\ndependencies = [\n \"serde_core\",\n]\n\n[[package]]\nname = \"serde_core\"\nversion = \"1.0.229\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48\"\ndependencies = [\n \"serde_derive\",\n]\n\n[[package]]\nname = \"serde_derive\"\nversion = \"1.0.229\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348\"\ndependencies = [\n \"proc-macro2\",\n \"quote\",\n \"syn\",\n]\n\n[[package]]\nname = \"serde_json\"\nversion = \"1.0.154\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6\"\ndependencies = [\n \"itoa\",\n \"memchr\",\n \"serde\",\n \"serde_core\",\n \"zmij\",\n]\n\n[[package]]\nname = \"syn\"\nversion = \"3.0.9\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b\"\ndependencies = [\n \"proc-macro2\",\n \"quote\",\n \"unicode-ident\",\n]\n\n[[package]]\nname = \"unicode-ident\"\nversion = \"1.0.27\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563\"\n\n[[package]]\nname = \"wbuild\"\nversion = \"0.1.0\"\ndependencies = [\n \"wlaw\",\n]\n\n[[package]]\nname = \"wcraft\"\nversion = \"0.1.0\"\ndependencies = [\n \"wlaw\",\n]\n\n[[package]]\nname = \"wfield\"\nversion = \"0.1.0\"\ndependencies = [\n \"wlaw\",\n]\n\n[[package]]\nname = \"wlaw\"\nversion = \"0.1.0\"\n\n[[package]]\nname = \"wmesh\"\nversion = \"0.1.0\"\ndependencies = [\n \"wlaw\",\n]\n\n[[package]]\nname = \"wmodel\"\nversion = \"0.1.0\"\ndependencies = [\n \"wlaw\",\n]\n\n[[package]]\nname = \"wtd\"\nversion = \"0.1.0\"\ndependencies = [\n \"wlaw\",\n]\n\n[[package]]\nname = \"zmij\"\nversion = \"1.0.23\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b\"\n",
    "tools/build-engine-labs.cjs": "// Compile a bounded, pinned engine adapter. Original work: Lars Rocha.\nconst fs=require('node:fs'),path=require('node:path'),crypto=require('node:crypto'),{execFileSync}=require('node:child_process');\nconst root=path.resolve(__dirname,'..'),ref=path.join(root,'reference/engine-labs'),hash=b=>crypto.createHash('sha256').update(b).digest('hex');\nconst manifest=JSON.parse(fs.readFileSync(path.join(ref,'manifest.json')));\nfor(const row of manifest.files)if(hash(fs.readFileSync(path.join(ref,row.path)))!==row.sha256)throw Error('Pinned source changed: '+row.path);\nexecFileSync('cargo',['+1.88.0','build','--manifest-path','experiments/engine-labs/Cargo.toml','--locked','--offline','--release','--target','wasm32-unknown-unknown'],{cwd:root,stdio:'inherit',env:{...process.env,RUSTFLAGS:`--remap-path-prefix=${process.env.HOME}=build-source --remap-path-prefix=${root}=indexin-source -C link-arg=--max-memory=134217728`}});\nconst data=fs.readFileSync(path.join(root,'experiments/engine-labs/target/wasm32-unknown-unknown/release/indexin_labs.wasm'));\nif(data.includes(Buffer.from('/Users/'))||data.includes(Buffer.from('/home/')))throw Error('Machine path in wasm');\nfs.writeFileSync(path.join(root,'inspector/engine/laws.wasm'),data);\nfs.writeFileSync(path.join(root,'inspector/engine/provenance.json'),JSON.stringify({format:'indexin-engine-adapter',version:1,creator:'Lars Rocha',adapter:'rust-labs-1',wasmSha256:hash(data),fixturesSha256:hash(fs.readFileSync(path.join(root,'reference/engine-survey/fixtures.json'))),wasmBytes:data.length,source:manifest,adapterSha256:hash(fs.readFileSync(path.join(root,'experiments/engine-labs/src/lib.rs'))),limits:{memoryBytes:134217728,maxGrid:64,maxTicks:1200,maxInputBytes:8192},notes:'Source snapshot from the reviewed MIT source release. Same compiled Rust kernels; adapter experiments and browser scheduling are labeled separately.'},null,2)+'\\n');\n// Dependency licenses accompany the shipped binary, independently of project licensing.\nconst deps=['serde_json','serde_core','itoa','memchr','zmij'];let notices='# Engine adapter notices\\n\\nOriginal engine laws, tools and visual work: Lars Rocha. The engine source release is MIT licensed.\\n\\n';\nnotices+=fs.readFileSync(path.join(ref,'LICENSE'),'utf8')+'\\n';\nconst registry=path.join(process.env.HOME,'.cargo/registry/src');\nfor(const d of fs.readdirSync(registry))for(const folder of fs.readdirSync(path.join(registry,d))){if(!deps.some(n=>folder.startsWith(n+'-')))continue;const dir=path.join(registry,d,folder);for(const name of ['LICENSE-MIT','LICENSE-APACHE'])if(fs.existsSync(path.join(dir,name)))notices+='\\n## '+folder+' / '+name+'\\n\\n'+fs.readFileSync(path.join(dir,name),'utf8');}\n// Plain text in JSON avoids treating license examples as website links.\nfs.writeFileSync(path.join(root,'inspector/engine/licenses.json'),JSON.stringify({notices},null,2)+'\\n');\nfs.copyFileSync(path.join(root,'reference/engine-survey/fixtures.json'),path.join(root,'inspector/engine/fixtures.json'));\nfs.writeFileSync(path.join(root,'inspector/engine/adapter-source.json'),JSON.stringify({creator:'Lars Rocha',license:'MIT',adapter:'rust-labs-1',build:'Rust 1.88.0, wasm32-unknown-unknown; locked offline build. Place the seven original engine crates under reference/engine-labs/crates, plus source traffic.rs and synth.rs at reference/engine-labs. Source manifests pin their exact bytes. The reviewed source archives contain these files.',files:Object.fromEntries(['experiments/engine-labs/src/lib.rs','experiments/engine-labs/Cargo.toml','experiments/engine-labs/Cargo.lock','tools/build-engine-labs.cjs'].map(name=>[name,fs.readFileSync(path.join(root,name),'utf8')]))},null,2)+'\\n');\nconsole.log(`Pinned ${manifest.files.length} inputs; built ${data.length} byte adapter.`);\n"
  }
}
