Phase 654: runMeshResilienceSoak journey with CI skip path.

3-peer live soak or single-host heal + replication lag assert when PEARCORD_SKIP_MESH_ROUNDTRIP=1.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Raven Scott
2026-06-02 17:43:31 -04:00
co-authored by Cursor
parent 06b446bca0
commit 3e04bd4336
2 changed files with 62 additions and 0 deletions
+5
View File
@@ -1942,6 +1942,11 @@ class HeadlessSession {
return runFanout(scenarioPath, opts) return runFanout(scenarioPath, opts)
} }
async runMeshResilienceSoak (scenarioPath, opts = {}) {
const { runMeshResilienceSoak: runSoak } = require('./mesh')
return runSoak(scenarioPath, opts)
}
/** Journey: simulate remote hub post ingest on discovery mesh. */ /** Journey: simulate remote hub post ingest on discovery mesh. */
async runFederationHubIngestJourney () { async runFederationHubIngestJourney () {
if (!this.platform) throw new Error('headless not started') if (!this.platform) throw new Error('headless not started')
+57
View File
@@ -315,6 +315,62 @@ async function runMeshChurnScaleSoakJourney (scenarioPath, opts = {}) {
/** /**
* Production federation live: 3-peer mesh + 8 fanout message tokens (CI-safe). * Production federation live: 3-peer mesh + 8 fanout message tokens (CI-safe).
*/ */
/**
* Phase 654: partition heal + replication diagnostics lag assert.
* Full 3-peer live mesh unless `PEARCORD_SKIP_MESH_ROUNDTRIP=1`.
*/
async function runMeshResilienceSoak (scenarioPath, opts = {}) {
const maxLagMs = Math.max(0, Number(opts.maxReplicationLagMs) || 120000)
if (process.env.PEARCORD_SKIP_MESH_ROUNDTRIP === '1') {
const base = path.join(os.tmpdir(), `pearcord-agentctl-resilience-${Date.now()}`)
const host = new HeadlessSession({ storagePath: path.join(base, 'host') })
if (opts.sessions) opts.sessions.push(host)
await host.start()
try {
if (scenarioPath && fs.existsSync(scenarioPath)) {
await host.runScenario(scenarioPath)
} else {
await host.registerUser({ username: 'resilience_host', displayName: 'Resilience' })
await host.createGuild({ name: 'Mesh Resilience' })
}
const gid = host.platform.guild?.guild?.id
if (!gid) throw new Error('mesh resilience: no guild')
const heal = await host.runPartitionHealJourney(gid)
const meshDiag = host.platform.exportMeshReplicationDiagnostics(gid)
const lag = Number(meshDiag?.maxReplicationLagMs) || 0
if (lag > maxLagMs) {
throw new Error(`mesh resilience: replication lag ${lag}ms > ${maxLagMs}ms`)
}
return {
peerCount: 1,
guildId: gid,
heal,
meshDiag,
soak: heal?.heal?.throttled ? 'heal-throttled' : 'ok',
maxReplicationLagMs: lag,
gossipLanes: meshDiag?.gossipLaneCounts || null,
ciSkipMesh: true
}
} finally {
await host.close()
}
}
const live = await runPartitionHeal3PeerLiveJourney(scenarioPath, opts)
const lag = Number(live.meshDiag?.maxReplicationLagMs) || 0
if (lag > maxLagMs) {
throw new Error(`mesh resilience: replication lag ${lag}ms > ${maxLagMs}ms`)
}
if (!live.heal?.heal && live.heal?.throttled) {
return { ...live, soak: 'heal-throttled' }
}
return {
...live,
soak: 'ok',
maxReplicationLagMs: lag,
gossipLanes: live.meshDiag?.gossipLaneCounts || null
}
}
async function runMesh8PeerFanoutJourney (scenarioPath, opts = {}) { async function runMesh8PeerFanoutJourney (scenarioPath, opts = {}) {
const triple = await connectGuildMeshTripleGroup(scenarioPath, { const triple = await connectGuildMeshTripleGroup(scenarioPath, {
...opts, ...opts,
@@ -339,5 +395,6 @@ module.exports = {
connectGuildMeshTripleGroup, connectGuildMeshTripleGroup,
runPartitionHeal3PeerLiveJourney, runPartitionHeal3PeerLiveJourney,
runMeshChurnScaleSoakJourney, runMeshChurnScaleSoakJourney,
runMeshResilienceSoak,
runMesh8PeerFanoutJourney runMesh8PeerFanoutJourney
} }