feat(agentctl): federation stability and hub ingest journeys
Add runFederationStabilitySoakJourney and runFederationHubIngestJourney for Phase 650 federation mesh validation. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -29,6 +29,8 @@ Both modes use **`pearcord-ui-flow` `dispatchUiMessage`** — the same handler a
|
|||||||
|
|
||||||
**v0.8.617 (Phase 645):** `runLargeGuildMemberJourney` (seed 120+ members → partial bundle → member page request); IPC `request-member-page`. Bundle: `npm run test:phase645-large-guild-mesh`. See [LARGE_GUILD_MESH.md](../../docs/LARGE_GUILD_MESH.md).
|
**v0.8.617 (Phase 645):** `runLargeGuildMemberJourney` (seed 120+ members → partial bundle → member page request); IPC `request-member-page`. Bundle: `npm run test:phase645-large-guild-mesh`. See [LARGE_GUILD_MESH.md](../../docs/LARGE_GUILD_MESH.md).
|
||||||
|
|
||||||
|
**v0.8.622 (Phase 650):** `runFederationStabilitySoakJourney` (`PEARCORD_FEDERATION_SOAK_MS`), `runFederationHubIngestJourney`; async `exportFederationSyncDiagnostics`. Bundle: `npm run test:phase650-live-federation-mesh`.
|
||||||
|
|
||||||
**v0.8.621 (Phase 649):** `runFederationMeshSoakJourney` (multi-guild + listing refresh + federation export); `exportFederationSyncDiagnostics`. Bundle: `npm run test:phase649-federation-discovery`. See [FEDERATION_MESH.md](../../docs/FEDERATION_MESH.md).
|
**v0.8.621 (Phase 649):** `runFederationMeshSoakJourney` (multi-guild + listing refresh + federation export); `exportFederationSyncDiagnostics`. Bundle: `npm run test:phase649-federation-discovery`. See [FEDERATION_MESH.md](../../docs/FEDERATION_MESH.md).
|
||||||
|
|
||||||
**v0.8.620 (Phase 648):** `runMultiGuildMeshSoakJourney` (two guilds, switch, multi export); `exportMultiGuildSyncDiagnostics`. Bundle: `npm run test:phase648-multi-guild-mesh`. See [MULTI_GUILD_MESH.md](../../docs/MULTI_GUILD_MESH.md).
|
**v0.8.620 (Phase 648):** `runMultiGuildMeshSoakJourney` (two guilds, switch, multi export); `exportMultiGuildSyncDiagnostics`. Bundle: `npm run test:phase648-multi-guild-mesh`. See [MULTI_GUILD_MESH.md](../../docs/MULTI_GUILD_MESH.md).
|
||||||
|
|||||||
+63
-2
@@ -1147,7 +1147,7 @@ class HeadlessSession {
|
|||||||
return this.platform.exportMultiGuildSyncDiagnostics()
|
return this.platform.exportMultiGuildSyncDiagnostics()
|
||||||
}
|
}
|
||||||
|
|
||||||
exportFederationSyncDiagnostics () {
|
async exportFederationSyncDiagnostics () {
|
||||||
if (!this.platform) throw new Error('headless not started')
|
if (!this.platform) throw new Error('headless not started')
|
||||||
return this.platform.exportFederationSyncDiagnostics()
|
return this.platform.exportFederationSyncDiagnostics()
|
||||||
}
|
}
|
||||||
@@ -1187,11 +1187,72 @@ class HeadlessSession {
|
|||||||
syncMesh: false
|
syncMesh: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const federation = this.platform.exportFederationSyncDiagnostics()
|
const federation = await this.platform.exportFederationSyncDiagnostics()
|
||||||
await this.refreshView()
|
await this.refreshView()
|
||||||
return { ...multiOut, listingRefresh, federation }
|
return { ...multiOut, listingRefresh, federation }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Journey: federation stability ticks (CI-safe; use PEARCORD_FEDERATION_SOAK_MS for long soak). */
|
||||||
|
async runFederationStabilitySoakJourney (guildId) {
|
||||||
|
if (!this.platform) throw new Error('headless not started')
|
||||||
|
const gid = guildId || this.platform.guild?.guild?.id
|
||||||
|
if (!gid) throw new Error('no guild')
|
||||||
|
const soakMs = Math.max(
|
||||||
|
3000,
|
||||||
|
Number(process.env.PEARCORD_FEDERATION_SOAK_MS) || 12000
|
||||||
|
)
|
||||||
|
const deadline = Date.now() + soakMs
|
||||||
|
const ticks = []
|
||||||
|
while (Date.now() < deadline) {
|
||||||
|
const scoped = await this.platform.refreshDiscoveryExploreScoped().catch(() => null)
|
||||||
|
const health = await this.getGuildSyncHealth(gid)
|
||||||
|
ticks.push({
|
||||||
|
at: Date.now(),
|
||||||
|
scoped,
|
||||||
|
pending: !!health?.pending,
|
||||||
|
peers: Number(health?.peers) || 0
|
||||||
|
})
|
||||||
|
await new Promise((r) => setTimeout(r, 2000))
|
||||||
|
}
|
||||||
|
const federation = await this.platform.exportFederationSyncDiagnostics()
|
||||||
|
await this.refreshView()
|
||||||
|
return { guildId: gid, soakMs, tickCount: ticks.length, ticks, federation }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Journey: simulate remote hub post ingest on discovery mesh. */
|
||||||
|
async runFederationHubIngestJourney () {
|
||||||
|
if (!this.platform) throw new Error('headless not started')
|
||||||
|
const g = await this.createGuild({ name: 'Hub Src', publicListing: true })
|
||||||
|
const gid = g?.guild?.id || this.platform.guild?.guild?.id
|
||||||
|
const ch = this.platform.activeChannelId
|
||||||
|
if (!gid || !ch) throw new Error('guild/channel required')
|
||||||
|
await this.sendGuildMessage(`hub-${Date.now()}`)
|
||||||
|
const targetGuild = await this.createGuild({ name: 'Hub Sub' })
|
||||||
|
const subGid = targetGuild?.guild?.id || this.platform.guild?.guild?.id
|
||||||
|
const targetCh = this.platform.activeChannelId
|
||||||
|
if (!subGid || !targetCh) throw new Error('subscriber guild required')
|
||||||
|
await this.platform.announcementHub.subscribe({
|
||||||
|
subscriberGuildId: subGid,
|
||||||
|
sourceGuildId: gid,
|
||||||
|
sourceChannelId: ch,
|
||||||
|
targetChannelId: targetCh
|
||||||
|
})
|
||||||
|
const payload = {
|
||||||
|
sourceGuildId: gid,
|
||||||
|
sourceChannelId: ch,
|
||||||
|
sourceGuildName: 'Hub Src',
|
||||||
|
sourceChannelName: 'general',
|
||||||
|
messageId: `hub-msg-${Date.now()}`,
|
||||||
|
content: 'federation hub ingest smoke',
|
||||||
|
authorName: 'Smoke',
|
||||||
|
postedAt: Date.now()
|
||||||
|
}
|
||||||
|
const mirrored = await this.platform._ingestAnnouncementHubPost(payload)
|
||||||
|
const federation = await this.platform.exportFederationSyncDiagnostics()
|
||||||
|
await this.refreshView()
|
||||||
|
return { payload, mirrored: mirrored?.length || 0, federation }
|
||||||
|
}
|
||||||
|
|
||||||
/** Journey: mesh stability + partition heal + message + diagnostics (production soak). */
|
/** Journey: mesh stability + partition heal + message + diagnostics (production soak). */
|
||||||
async runProductionMeshSoakJourney (guildId) {
|
async runProductionMeshSoakJourney (guildId) {
|
||||||
if (!this.platform) throw new Error('headless not started')
|
if (!this.platform) throw new Error('headless not started')
|
||||||
|
|||||||
Reference in New Issue
Block a user