// verify-admission.mjs — cross-machine, on REAL storage, NON-WRITING check that
// the base.replicate(wakeup) fix lets a member's PENDING optimistic admission
// land once the indexer is online.
//
// --mode host : open the room StateBase (indexer side) and stay online N secs,
// logging writer/indexer count so the joiner can be admitted.
// --mode watch : open the room StateBase (member side), poll `writable` for N
// secs WITHOUT writing. Reports if it flips true (= admitted).
//
// bare tools/verify-admission.mjs --storage <root> --title <room> --mode host|watch [--secs N]
import { startDaemon } from '../index.js'
const a = Bare.argv.slice(2)
const gi = (f) => { const i = a.indexOf(f); return i >= 0 ? a[i + 1] : null }
const storage = gi('--storage'); const title = gi('--title'); const mode = gi('--mode') || 'watch'
const secs = Number(gi('--secs') || 60)
if (!storage || !title) { console.log('usage: --storage <root> --title <room> --mode host|watch [--secs N]'); Bare.exit(1) }
const sleep = (ms) => new Promise(r => setTimeout(r, ms))
setTimeout(() => { console.log('VERIFY_END (timeout)'); Bare.exit(0) }, (secs + 30) * 1000)
const d = await startDaemon({ storage, socketPath: '/tmp/keet-verify.sock', pidFile: '/tmp/keet-verify.pid', debug: false })
await d.core.backendAPI.ready()
const rooms = await d.router._rooms()
const hit = rooms.find(r => r.title === title)
if (!hit) { console.log('no room titled', JSON.stringify(title)); Bare.exit(1) }
const sb = await d.router._getStateBase(hit.roomId)
const self = sb._selfKey ? sb._selfKey.toString('hex').slice(0, 8) : '?'
const wc = () => { try { return (sb.base.activeWriters && sb.base.activeWriters.size) ?? '?' } catch { return '?' } }
console.log('MODE=%s self=%s room=%s startWritable=%s writers=%s', mode, self, hit.roomId.slice(0, 12), sb.writable, wc())
const peers = () => { try { return sb.swarm ? sb.swarm.connections.size : -1 } catch { return -1 } }
let flips = false
for (let i = 0; i < secs; i += 3) {
await sb.base.update().catch(() => {})
// join mode WRITES every few seconds (like the game's per-frame set) so the
// member appends a fresh optimistic admit block for the indexer to ack.
if (mode === 'join') {
try { await sb.set('__admit_probe__:' + self, { t: i, ts: Date.now ? 0 : 0 }) } catch (e) { console.log(' set threw:', e.message) }
}
if (sb.writable && !flips) { flips = true; console.log('>>> WRITABLE FLIPPED TRUE at ~%ds (writers=%s)', i, wc()) }
if (i % 9 === 0) console.log(' t=%ds writable=%s writers=%s swarmPeers=%d', i, sb.writable, wc(), peers())
await sleep(3000)
}
console.log('VERIFY_RESULT mode=%s self=%s finalWritable=%s writers=%s flipped=%s', mode, self, sb.writable, wc(), flips)
Bare.exit(0)