Back to GRAV / RIFT
SOURCE / PINNED RELEASE

Made of little things.

GRAV / RIFT

Release
288aa261ce07…
Author-recorded commit
c549b5a4e17e…
License
LICENSE
Author’s source reference
nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-8a7361981e8

Archive hash verified: e52a01aff70810b3…. The source-to-build association is the author’s claim; it has not been independently rebuilt.

tests/surgical.mjs
// Mouse-first end-to-end proof in the real soyLI iframe; no game-state mutation.
import assert from 'node:assert/strict';import {createRequire} from 'node:module';import {realpathSync,mkdirSync} from 'node:fs';
const require=createRequire(realpathSync(new URL('../node_modules/@napplet/conformance-cli/package.json',import.meta.url))),{chromium}=require('playwright');
const url=process.argv.slice(2).find(a=>/^https?:/.test(a));if(!url)throw new Error('Pass soyli dev URL');
const browser=await chromium.launch(),errors=[];mkdirSync('.napplet-space/promotion',{recursive:true});let page;
const style='#stage{position:fixed!important;inset:0!important;z-index:100!important}#stage iframe{width:100vw!important;height:100dvh!important;min-height:0!important}body{overflow:hidden!important}';
try{
 page=await browser.newPage({viewport:{width:1200,height:750}});page.on('pageerror',e=>errors.push(e.message));await page.goto(url);await page.locator('iframe').waitFor();const f=page.frames().find(f=>f!==page.mainFrame());await f.locator('#deploy').waitFor();await page.addStyleTag({content:style});await page.clock.install({time:new Date('2026-09-27T12:00:00Z')});await page.clock.pauseAt(new Date('2026-09-27T12:01:00Z'));await page.clock.runFor(100);
 const state=()=>f.locator('#game').evaluate(n=>({...n.dataset}));
 const aim=async(x,y)=>{const {d,r}=await f.locator('#game').evaluate(n=>({d:{...n.dataset},r:n.getBoundingClientRect().toJSON()}));await page.mouse.move(r.left+(x-Number(d.camera))*Number(d.viewScale),r.top+(y-Number(d.cameraY))*Number(d.viewScale));};
 const rig=async(id)=>JSON.parse((await state()).rigs).find(r=>id?r.id===id:r.kind==='walker');
 const run=ms=>page.clock.runFor(ms);
 await f.locator('#practice').click();await aim(640,820);await page.mouse.down({button:'right'});await run(1100);assert.ok(Number((await state()).payload)>10);
 // Independent field and discharge choices; physical left mouse while right stays down.
 await page.keyboard.press('KeyR');let d=await state();await aim(Number(d.shipX)+400,Number(d.shipY)-200);await run(300);
 let shots=Number((await state()).shots);await page.mouse.down({button:'left'});await run(240);await page.mouse.up({button:'left'});await run(120);d=await state();console.log('STREAM',d.shots,d.payload);
 assert.ok(Number(d.shots)>=shots+2);assert.ok(Number(d.payload)>0);shots=Number(d.shots);await run(150);assert.equal(Number((await state()).shots),shots);
 await page.keyboard.press('KeyR');await page.mouse.down({button:'left'});await run(600);await page.mouse.up({button:'left'});console.log('CLUSTERS',(await state()).shots,(await state()).payload);assert.ok(Number((await state()).shots)>=shots+2);
 await page.screenshot({path:'.napplet-space/promotion/cluster-fire.png'});
 // Right release drops cargo; it must never become another firing trigger.
 await run(120);shots=Number((await state()).shots);await page.mouse.up({button:'right'});await run(200);
 assert.equal((await state()).payload,'0');assert.equal(Number((await state()).shots),shots);
 // Reverse press order: fire can already be held when collection starts.
 await page.mouse.down({button:'left'});await run(120);assert.equal(Number((await state()).shots),shots);
 d=await state();await aim(Number(d.shipX)+220,820);await page.mouse.down({button:'right'});await run(450);
 assert.ok(Number((await state()).shots)>shots,'already-held fire consumes newly collected debris');
 await page.mouse.up({button:'right'});await run(120);shots=Number((await state()).shots);await run(200);
 assert.equal((await state()).payload,'0');assert.equal(Number((await state()).shots),shots,'right release drops instead of auto-draining');
 await page.mouse.up({button:'left'});
 // Tab should preserve combat state and slow simulation, while selection stays responsive.
 await page.keyboard.down('Tab');assert.equal(await f.locator('#radial').isVisible(),true);const before=Number((await state()).simTime),beforeShots=Number((await state()).shots);
 await run(2000);const delta=Number((await state()).simTime)-before;assert.ok(delta>.06&&delta<.2,`slow motion delta ${delta}`);assert.equal(Number((await state()).shots),beforeShots);
 await f.locator('[data-select-release="1"]').click();await f.locator('[data-select-mode="3"]').hover();await page.screenshot({path:'.napplet-space/promotion/surgical-radial.png'});await page.keyboard.up('Tab');await page.mouse.up({button:'right'});await run(120);
 assert.equal((await state()).fieldMode,'3');assert.equal((await state()).releaseMode,'1');assert.equal((await state()).timeScale,'1');assert.equal(Number((await state()).shots),beforeShots);
 await f.locator('#pause').click();await f.locator('#retry').click();await page.keyboard.press('Digit4');
 await page.keyboard.down('KeyD');await page.keyboard.down('KeyW');await run(650);await page.keyboard.up('KeyW');
 for(let i=0;i<15&&Number((await state()).shipX)<940;i++)await run(100);await page.keyboard.up('KeyD');await run(120);
 let r=await rig(),id=r.id;
 const select=async(key,label)=>{
  for(let i=0;i<20;i++){
   const target=await rig(id),part=key?target?.parts.find(p=>p.key===key):target;assert.ok(part,`target ${key??'root'} still alive`);
   await aim(part.x,part.y);await run(110);
   if((await state()).focusLabel.includes(label)){
    const current=await rig(id),point=key?current.parts.find(p=>p.key===key):current;await aim(point.x,point.y);
    await page.mouse.down({button:'right'});await run(110);
    const locked=await state();if(locked.focus&&locked.focusLabel.includes(label))return;
    await page.mouse.up({button:'right'});await run(110);
   }
  }
  throw new Error(`Could not point at ${label}: ${(await state()).focusLabel}`);
 };
 await select('shield-cell','SHIELD CELL');await run(950);
 d=await state();console.log('EXTRACT',d.focusLabel,d.cellsExtracted,d.payload);assert.equal(Number(d.cellsExtracted),1);assert.equal(Number(d.payload),1);assert.equal((await rig(id)).shielded,false);
 await page.screenshot({path:'.napplet-space/promotion/shield-extracted.png'});
 // Throw the extracted explosive away from the living target.
 await aim(Number(d.shipX)-140,190);await run(700);await page.mouse.down({button:'left'});await run(60);await page.mouse.up({button:'left'});await page.mouse.up({button:'right'});await run(100);
 r=await rig(id);assert.ok(r,'Strider survives cell extraction');await select(null,'STRIDER');await run(120);
 d=await state();assert.equal(d.payload,'1');assert.match(d.focusLabel,/STRIDER|WALKER/);const oldY=(await rig(id)).y;
 await aim(Number(d.shipX)+130,340);await page.mouse.wheel(0,160);await run(750);r=await rig(id);assert.ok(r.y<oldY-70,'whole living rig follows the cursor upward');
 await page.screenshot({path:'.napplet-space/promotion/living-strider.png'});
 await aim(Number((await state()).shipX)+470,350);await page.mouse.down({button:'left'});await run(80);await page.mouse.up({button:'left'});await page.mouse.up({button:'right'});await run(220);
 d=await state();console.log('LIVE THROW',d.liveThrows,d.focusLabel);assert.equal(d.liveThrows,'1');await page.screenshot({path:'.napplet-space/promotion/living-strider-thrown.png'});
 // A fresh encounter keeps the leg test independent from the volatile shield-cell shot.
 await f.locator('#pause').click();await f.locator('#retry').click();await page.keyboard.press('Digit4');
 await page.keyboard.down('KeyD');await page.keyboard.down('KeyW');await run(650);await page.keyboard.up('KeyW');
 for(let i=0;i<15&&Number((await state()).shipX)<940;i++)await run(100);await page.keyboard.up('KeyD');await run(120);
 r=await rig();id=r.id;await select('leg-0-upper','LEG JOINT');
 for(let i=0;i<30&&Number((await state()).limbsTorn)===0;i++)await run(25);
 d=await state();console.log('LEG',d.focusLabel,d.limbsTorn);assert.ok(Number(d.limbsTorn)>=1);assert.equal((await rig(id)).legs,3);assert.equal(d.payload,'1');
 await page.screenshot({path:'.napplet-space/promotion/leg-extracted.png'});await page.mouse.up({button:'right'});
 // Selector lifecycle and compact layout.
 await page.keyboard.down('Tab');await page.keyboard.press('Escape');await page.keyboard.up('Tab');assert.equal(await f.locator('#radial').isVisible(),false);await run(150);assert.equal((await state()).timeScale,'1');
 for(const [w,h] of [[320,560],[900,600],[1440,900],[844,390]]){
  await page.setViewportSize({width:w,height:h});await run(100);await f.locator('#selector').click();await run(100);
  const layout=await f.locator('.radial-choice').evaluateAll(bs=>bs.map(b=>{const r=b.getBoundingClientRect();return {x:r.x,y:r.y,w:r.width,h:r.height,vw:innerWidth,vh:innerHeight};}));
  assert.ok(layout.every(r=>r.x>=0&&r.y>=0&&r.x+r.w<=r.vw&&r.y+r.h<=r.vh&&r.w>=44&&r.h>=44),`${w} selector reachable`);
  await page.screenshot({path:`.napplet-space/promotion/radial-${w}x${h}.png`});await f.locator('[data-close]').click();
 }
 for(const [w,h] of [[390,844],[844,390]]){
  const context=await browser.newContext({viewport:{width:w,height:h},isMobile:true,hasTouch:true}),phone=await context.newPage();phone.on('pageerror',e=>errors.push(e.message));
  await phone.goto(url);await phone.locator('iframe').waitFor();const f=phone.frames().find(f=>f!==phone.mainFrame());await f.locator('#deploy').waitFor();await phone.addStyleTag({content:style});await phone.clock.install({time:new Date('2026-09-27T12:00:00Z')});await phone.clock.pauseAt(new Date('2026-09-27T12:01:00Z'));await phone.clock.runFor(100);await f.locator('#practice').tap();
  await f.locator('#selector').tap();await f.locator('[data-select-release="1"]').tap();await f.locator('[data-close]').tap();
  const field=await f.locator('#fieldButton').boundingBox(),fire=await f.locator('#fireButton').boundingBox(),cdp=await context.newCDPSession(phone);
  const touch=(id,r)=>({id,x:r.x+r.width/2,y:r.y+r.height/2,radiusX:4,radiusY:4,force:1});
  await cdp.send('Input.dispatchTouchEvent',{type:'touchStart',touchPoints:[touch(1,field)]});await phone.clock.runFor(1100);
  await cdp.send('Input.dispatchTouchEvent',{type:'touchStart',touchPoints:[touch(1,field),touch(2,fire)]});await phone.clock.runFor(400);
  assert.ok(Number(await f.locator('#game').getAttribute('data-shots'))>=3,`${w}: touch streams while gathering`);
  await phone.screenshot({path:`.napplet-space/promotion/stream-touch-${w}x${h}.png`});await cdp.send('Input.dispatchTouchEvent',{type:'touchEnd',touchPoints:[]});await context.close();
 }
 assert.deepEqual(errors,[]);console.log('SURGICAL: stream, clusters, both mouse buttons, 5% Tab selector, cell/leg extraction, live rig drag/rotation/throw and responsive selector passed.');
}catch(error){if(page)await page.screenshot({path:'.napplet-space/promotion/surgical-failure.png'});throw error;}finally{await browser.close();}