Phase 853: guild 4-peer offline recovery + partition heal journey

Add runGuildMeshQuadOfflineHealJourney and meshQuadOfflineHealReady
matcher combining Phase 842 offline recovery with Phase 850 heal on
all four peers after quad reconnect.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Raven Scott
2026-06-04 05:52:36 -04:00
co-authored by Cursor
parent c9cc14f221
commit 20afebe827
3 changed files with 157 additions and 0 deletions
+2
View File
@@ -2,6 +2,8 @@
Agent control plane for Pearcord — send the same IPC messages the UI sends, read `view` snapshots, and run scripted journeys against a **live worker** or an in-process **headless** session.
**Phase 853 (v0.8.820):** `runGuildMeshQuadOfflineHealJourney` (4-peer offline + partition heal). Bundle: `npm run test:ci-phase853`.
**Phase 852 (v0.8.819):** `runGuildMeshQuadRecoveryHealJourney` (4-peer recovery + partition heal). Bundle: `npm run test:ci-phase852`.
**Phase 851 (v0.8.818):** `runGuildMeshQuadChurnHealJourney` (4-peer churn + partition heal). Bundle: `npm run test:ci-phase851`.
+12
View File
@@ -211,6 +211,18 @@ function matchView (view, spec) {
if (view?.meshStabilityStats?.pushHalted) return false
continue
}
if (key === 'meshQuadOfflineHealReady') {
if (!expected) return true
const peers = Number(view?.stats?.peers) || 0
if (peers < 2) return false
const gid = view?.guild?.id
const rail = gid ? view.guildSyncHealthRail?.[gid] : null
if (rail?.meshBounded) return false
if (view?.meshStabilityStats?.pushHalted) return false
if (!!view?.partitionHealInProgress) return false
if (!view?.lastPartitionHeal?.at) return false
continue
}
if (key === 'meshQuadEmojisReady') {
if (!expected) return true
const peers = Number(view?.stats?.peers) || 0
+143
View File
@@ -8814,6 +8814,149 @@ class HeadlessSession {
}
}
/** Phase 853: 4-peer mesh — offline recovery + partition heal after quad reconnect. */
async runGuildMeshQuadOfflineHealJourney () {
const {
connectGuildMeshQuad,
disconnectGuildMeshQuad
} = require('./mesh-helpers')
const token = `offline853-${Date.now()}`
const base = path.join(os.tmpdir(), `pearcord-agentctl-offline853-${Date.now()}`)
const host = new HeadlessSession({ storagePath: path.join(base, 'host') })
const guest1 = new HeadlessSession({ storagePath: path.join(base, 'guest1') })
const guest2 = new HeadlessSession({ storagePath: path.join(base, 'guest2') })
const guest3 = new HeadlessSession({ storagePath: path.join(base, 'guest3') })
await host.start()
await guest1.start()
await guest2.start()
await guest3.start()
try {
await host.registerUser({ username: 'offhost853', displayName: 'Offline Heal Host 853' })
await host.createGuild({ name: 'Offline Heal Quad 853', publicListing: false })
await host.wait({ mode: 'guild' }, 45000)
const invite = await host.platform.createInvite().catch(() => null)
const code = invite?.shareCode || invite?.code
if (!code) throw new Error('host invite missing')
await guest1.registerUser({ username: 'offguest853a', displayName: 'Offline Heal Guest 853a' })
await guest2.registerUser({ username: 'offguest853b', displayName: 'Offline Heal Guest 853b' })
await guest3.registerUser({ username: 'offguest853c', displayName: 'Offline Heal Guest 853c' })
await guest1.ipc({ type: 'join-invite', code })
await guest2.ipc({ type: 'join-invite', code })
await guest3.ipc({ type: 'join-invite', code })
await guest1.wait({ mode: 'guild' }, 45000)
await guest2.wait({ mode: 'guild' }, 45000)
await guest3.wait({ mode: 'guild' }, 45000)
const chId = (await host.refreshView()).activeChannelId
if (!chId) throw new Error('active channel missing')
for (const sess of [guest1, guest2, guest3]) {
await sess.ipc({ type: 'select-channel', channelId: chId })
await sess.wait({ activeChannelId: chId }, 30000)
}
await connectGuildMeshQuad(
host.platform,
guest1.platform,
guest2.platform,
guest3.platform,
55000
)
const quadWait = { meshQuadReady: true, membersMin: 4 }
await host.wait(quadWait, 30000)
await guest1.wait(quadWait, 30000)
await guest2.wait(quadWait, 30000)
await guest3.wait(quadWait, 30000)
await host.sendGuildMessage(token)
const msgWait = { activeChannelMessageIncludes: token }
await guest1.wait(msgWait, 90000)
await guest2.wait(msgWait, 90000)
await guest3.wait(msgWait, 90000)
await disconnectGuildMeshQuad(
host.platform,
guest1.platform,
guest2.platform,
guest3.platform,
20000
)
for (const sess of [guest1, guest2, guest3]) {
await sess.wait({ meshPeersExact: 0 }, 30000)
}
await connectGuildMeshQuad(
host.platform,
guest1.platform,
guest2.platform,
guest3.platform,
55000
)
const g3v0 = await guest3.refreshView()
const guest3UserId = g3v0.user?.id
if (!guest3UserId) throw new Error('guest3 user id missing')
const gid = host.platform.guild?.guild?.id
if (!gid) throw new Error('guild id missing')
const t0 = Date.now()
await host.platform._ingestPresenceVectorBundle(gid, [
{ userId: guest3UserId, status: 'idle', at: t0 - 5000, vectorSeq: 13 }
])
await host.platform._ingestPresenceVectorBundle(gid, [
{ userId: guest3UserId, status: 'online', at: t0, vectorSeq: 13 }
])
const healMid = await host.platform.runPartitionHealSync({
force: true,
source: 'agentctl-quad-offline853-mid'
})
if (healMid?.throttled) throw new Error('mid partition heal throttled')
for (const p of [host.platform, guest1.platform, guest2.platform, guest3.platform]) {
if (typeof p.runOfflineRecoverySync === 'function') {
await p.runOfflineRecoverySync().catch(() => null)
}
if (typeof p.requestGuildSyncFanout === 'function') {
p.requestGuildSyncFanout()
}
}
const healFinal = await host.platform.runPartitionHealSync({
force: true,
source: 'agentctl-quad-offline853-final'
})
if (healFinal?.throttled) throw new Error('final partition heal throttled')
for (const p of [host.platform, guest1.platform, guest2.platform, guest3.platform]) {
if (typeof p.requestGuildSyncFanout === 'function') {
p.requestGuildSyncFanout()
}
}
const fullWait = {
meshQuadReady: true,
membersMin: 4,
meshQuadOfflineHealReady: true,
meshQuadOfflineRecoveryReady: true,
meshReconnectReady: true,
partitionHealComplete: true,
activeChannelMessageIncludes: token,
presencePeersMin: 3
}
await host.wait(fullWait, 120000)
await guest1.wait(fullWait, 120000)
await guest2.wait(fullWait, 120000)
await guest3.wait(fullWait, 120000)
const presWait = { peerPresenceStatus: { userId: guest3UserId, status: 'online' } }
await host.wait(presWait, 90000)
await guest1.wait(presWait, 90000)
await guest2.wait(presWait, 90000)
await guest3.wait(presWait, 90000)
const g2v = await guest2.refreshView()
return {
token,
guest3UserId,
healMidMs: healMid?.durationMs,
healFinalMs: healFinal?.durationMs,
guest2Peers: g2v.stats?.peers,
guest2HealAt: g2v.lastPartitionHeal?.at
}
} finally {
await host.close()
await guest1.close()
await guest2.close()
await guest3.close()
}
}
/** Phase 852: 4-peer mesh — full quad disconnect/reconnect + partition heal + recovery burst reconcile. */
async runGuildMeshQuadRecoveryHealJourney () {
const {