SOURCE / PINNED RELEASE
Made of little things.
Napcraft
- Release
- ee47ac6a25df…
- Author-recorded commit
- 410dea87e109…
- License
- LICENSE
- Author’s source reference
- nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-52f9e22f5ce
Archive hash verified: 9e6e0cabb18d0d46…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
// Real hosted UI + provider. Delays/faults wrap the SDK only in this trusted test.
import { writeFile } from 'node:fs/promises';
export async function instrument(frame, delay = 150) {
await frame.evaluate((delay) => {
const clock = () => performance.timeOrigin + performance.now();
const wait = (ms) => new Promise(r => setTimeout(r, ms));
const registry = window.napplet.cvm.registry;
const original = registry.call.bind(registry);
window.editProbe = { delay, offline: false, loseNext: false, calls: [], inputs: [], renders: [] };
registry.call = async (family, tool, args, options) => {
const p = window.editProbe;
const call = { tool, args: structuredClone(args), start: clock() };
p.calls.push(call);
if (p.holdReads && ['readWorld','readUpdates'].includes(args.operation)) await new Promise(r => { p.releaseRead = r; });
await wait(p.delay);
if (p.offline) { call.error = 'offline'; throw Error('Test connection unavailable'); }
const reply = await original(family, tool, args, options);
call.providerAt = clock();
call.reply = structuredClone(reply);
await wait(p.delay);
if (p.loseNext && ['editBlock', 'editBlocks'].includes(args.operation) && !reply.isError) {
p.loseNext = false;
if (p.offlineAfterLoss) p.offline = true;
call.error = 'lost response';
throw Error('Test lost reply after durable commit');
}
call.end = clock();
return reply;
};
const canvas = document.querySelector('canvas');
new MutationObserver(() => {
const edits = Number(canvas.dataset.edits);
const p = window.editProbe;
if (p.renders.at(-1)?.edits !== edits) p.renders.push({ edits, at: clock() });
}).observe(canvas, { attributes: true, attributeFilter: ['data-edits'] });
const input = event => {
if (event.type === 'keydown' && !['Space', 'KeyX'].includes(event.code)) return;
if (event.type === 'pointerdown' && !['place', 'remove'].includes(event.target.closest('button')?.id)) return;
window.editProbe.inputs.push({ at: clock(), type: event.type });
};
document.addEventListener('keydown', input, true);
document.addEventListener('pointerdown', input, true);
}, delay);
}
export default async ({ players, connectIdentity, approveBackendAccount, check, diagnostics }) => {
const [a, b] = players;
const cpuRate = Number(process.env.NAPCRAFT_CPU_RATE || 1);
if (cpuRate !== 1) {
const cdp = await b.page.context().newCDPSession(b.page);
await cdp.send('Emulation.setCPUThrottlingRate',{rate:cpuRate});
}
await connectIdentity(a);
await a.frame.locator('#create').click();
await a.frame.locator('#name').fill('Responsiveness lab');
await a.frame.locator('#confirmCreate').click();
await approveBackendAccount(a, 'worlds');
await a.frame.locator('#share').waitFor();
await a.frame.locator('#share').click();
const code = await a.frame.locator('#shareCode').inputValue();
await a.frame.locator('#close').click();
await b.frame.locator('#join').click();
await b.frame.locator('#code').fill(code);
await b.frame.locator('#confirmJoin').click();
await b.frame.locator('#share').waitFor();
await Promise.all(players.map(p => p.frame.waitForFunction(() => Number(document.querySelector('canvas').dataset.peerCount) === 1)));
check('two independent players connected', true);
await Promise.all(players.map(p => instrument(p.frame)));
// Compare idle-network input in BOTH versions. Background-read overlap has its
// own correctness/feedback test; the old app disabled these inputs entirely.
await b.page.waitForTimeout(1000);
const samples = [];
let edits = 0;
for (const mobile of [false, true]) {
if (mobile) {
await b.page.setViewportSize({ width: 390, height: 844 });
await b.page.addStyleTag({content:'body>header,body>#status,body>#media{display:none!important}#stage{margin:0!important;padding:0!important;width:390px!important;height:844px!important}#stage iframe{width:390px!important;height:844px!important;min-height:0!important;border:0!important}'});
await b.frame.waitForFunction(() => innerWidth === 390 && innerHeight === 844);
const cdp = await b.page.context().newCDPSession(b.page);
await cdp.send('Emulation.setTouchEmulationEnabled', { enabled: true });
}
for (let i = 0; i < 4; i++) {
const remove = i % 2 === 1;
await Promise.all(players.map(p => p.frame.waitForFunction(() => window.editProbe.calls.every(c => c.end !== undefined || c.error))));
await b.frame.waitForFunction(() => !document.querySelector('#place').disabled);
await b.frame.locator('canvas').focus();
if (mobile) {
const rect = await b.frame.locator(remove ? '#remove' : '#place').boundingBox();
const cdp = await b.page.context().newCDPSession(b.page);
await cdp.send('Input.dispatchTouchEvent',{type:'touchStart',touchPoints:[{x:rect.x+rect.width/2,y:rect.y+rect.height/2}]});
await cdp.send('Input.dispatchTouchEvent',{type:'touchEnd',touchPoints:[]});
await cdp.detach();
} else await b.page.keyboard.press(remove ? 'x' : 'Space');
edits++;
await Promise.all(players.map(p => p.frame.waitForFunction(n => Number(document.querySelector('canvas').dataset.edits) === n, edits, {timeout:12000})));
const local = await b.frame.evaluate(n => {
const p = window.editProbe, input = p.inputs.at(-1).at;
const command = p.calls.findLast(c => ['editBlock', 'editBlocks'].includes(c.args.operation));
return {input, localMs:p.renders.find(r => r.edits === n).at-input, confirmedMs:command.end ? command.end-input : null,resultBytes:command.reply ? new TextEncoder().encode(JSON.stringify(command.reply.structuredContent.result)).length : null};
}, edits);
const remote = await a.frame.evaluate(n => window.editProbe.renders.find(r => r.edits === n).at, edits);
// Optimistic rendering can precede confirmation: collect final acknowledgement too.
await b.frame.waitForFunction(() => window.editProbe.calls.filter(c => ['editBlock','editBlocks'].includes(c.args.operation)).at(-1)?.end !== undefined);
local.confirmedMs = await b.frame.evaluate(start => window.editProbe.calls.filter(c => ['editBlock','editBlocks'].includes(c.args.operation)).at(-1).end-start, local.input);
samples.push({mobile,action:remove?'erase':'build',localMs:local.localMs,confirmedMs:local.confirmedMs,remoteMs:remote-local.input,resultBytes:local.resultBytes});
console.log(JSON.stringify(samples.at(-1)));
await b.page.waitForTimeout(900);
}
}
const label = process.env.NAPCRAFT_BASELINE ? 'before' : `after${cpuRate === 1 ? '' : '-cpu'+cpuRate}`;
await writeFile(`.napplet-space/edit-latency-${label}.json`, JSON.stringify({delayPerCvmLegMs:150,cpuRate,samples,diagnostics:await diagnostics()},null,2));
check('local block feedback under 80 ms', samples.every(s => s.localMs < 80));
check('remote committed blocks under 1300 ms', samples.every(s => s.remoteMs < 1300));
};
