// RE-ANCHOR WITH UNSIGNED LOCAL WRITES — the forward-only gate must not swallow them.
//
// When sign() finds a network head newer than its own, it re-anchors (head = the net frame). It used to
// set the diff baseline to the device's CURRENT VIEW at that moment. If the device already held a local
// write the net head does not have, that write went into the signed data root with NO op in any frame:
// the before/after diff was empty, so no #commit frame was appended at all, yet head advanced to the
// unpublished commit. An ops-only consumer (the reference bsky AppView applies ops and nothing else)
// never learns that record, and the next frame's prevData points at a root no frame ever published.
//
// The baseline after a re-anchor must be the record set the NET HEAD commits to (the firehose replay),
// so the local write is diffed as an op.
import '../lib/bare-globals.js'
import test from 'brittle'
import b4a from 'b4a'
import { SwarmDevice } from '../lib/swarm-device.js'
const DID = 'did:plc:reanchorunsigned'
const KEY = (() => { const k = b4a.alloc(32); k[31] = 7; return k })()
const post = (text) => ({ $type: 'app.bsky.feed.post', text, createdAt: '2026-10-13T00:00:00.000Z' })
class MemKV {
constructor (m) { this.m = new Map(m || []) }
async set (k, v) { this.m.set(k, v) }
async get (k) { return this.m.has(k) ? this.m.get(k) : null }
async getNow (k) { return this.get(k) }
async del (k) { this.m.delete(k) }
async list (prefix = '') { const o = {}; for (const [k, v] of this.m) if (k.startsWith(prefix)) o[k] = v; return o }
async listNow (prefix = '') { return this.list(prefix) }
}
test('re-anchor: a local write the net head lacks is published as an op, not absorbed', async (t) => {
const sb = new MemKV()
const A = new SwarmDevice(sb, { did: DID, privateKey: KEY, self: 'A', firehose: true })
const B = new SwarmDevice(sb, { did: DID, privateKey: KEY, self: 'B', firehose: true })
await A.putRecord('app.bsky.feed.post', 'r1', post('one'))
const h1 = await A.sign({ force: true })
t.ok(await B.sign() === null && B.head && B.head.rev === h1.rev, 'B anchored at the first commit')
// A moves the chain on; B is now behind it.
await A.putRecord('app.bsky.feed.post', 'r2', post('two'))
const h2 = await A.sign()
t.ok(h2 && h2.rev > h1.rev, 'A signed a newer head')
// B writes locally BEFORE its next sign, so that sign both re-anchors and has a new record.
await B.putRecord('app.bsky.feed.post', 'r3', post('three'))
const h3 = await B.sign()
t.ok(h3 && h3.rev > h2.rev, 'B signed forward from the net head')
const frames = Object.values(await sb.listNow('__commit__/'))
const published = frames.flatMap((f) => (f.ops || []).map((o) => o.path))
t.ok(published.includes('app.bsky.feed.post/r3'), 'r3 reached the firehose as an op')
const head = frames.find((f) => f.commitCid === h3.commitCid.toString())
t.ok(head, 'the commit B signed was appended as a frame (head never points at an unpublished commit)')
})