/** * Public contract for the Designer (Slice 3): the discovery loop that invents * novel Teams by mutating and breeding them with Strength as the fitness signal. * The single seam is `design`; this is the structure it returns. */ import type { MatchupResult, Submission, ValidationError } from '../types.js'; /** Weights for the composite fitness — the ADR-0004 lean correction lives here. */ export interface FitnessWeights { /** Weight on absolute Strength vs the Gauntlet. */ gauntlet: number; /** Weight on peer performance within the evolving population. */ peer: number; /** Weight on the worst-matchup floor (rewards robust, flat profiles). */ robustness: number; } export interface DesignBudget { /** Teams kept per generation. */ population?: number; /** Generations to run. */ generations?: number; /** Battles per pairing when evaluating a contender's fitness. */ battlesPerPairing?: number; /** Cheaper first-pass battles for the adaptive screen; only the top half of a * generation's new Teams are then re-evaluated at `battlesPerPairing`. Defaults * to half of `battlesPerPairing`. Set equal to it to disable the screen. */ screenBattlesPerPairing?: number; /** Hard ceiling on total Battles across the run; generations stop once hit. */ battleBudget?: number; /** Top Teams carried unchanged into the next generation. */ elitism?: number; weights?: FitnessWeights; } export type Origin = 'seed' | 'random' | 'mutation' | 'crossover'; /** How a Team came to be — its provenance in the search. */ export interface Lineage { origin: Origin; generation: number; /** Parent ids (mutation: one; crossover: two). */ parents: string[]; /** The operator that produced it (e.g. `swap-item`, `swap-member`, `crossover`). */ operator?: string; } /** The three components of a Team's composite fitness. */ export interface FitnessParts { gauntlet: number; peer: number; robustness: number; } /** A Team the Designer discovered. */ export interface DesignedTeam { id: string; paste: string; /** Overall Strength vs the Gauntlet, in [0, 1]. */ strength: number; /** Composite fitness the search optimised. */ fitness: number; fitnessParts: FitnessParts; /** LLM-assigned (or fallback) Archetype label. */ archetype: string; /** True if the model flagged it as a novel Archetype. */ novel: boolean; lineage: Lineage; /** Per-Gauntlet-member win-rates (Archetype-tagged). */ matchups: MatchupResult[]; } export interface DesignInput { /** Starting Team(s) as Showdown text; omit to search from scratch. */ seedTeams?: string | Array; /** Gauntlet version to measure Strength against (gauntlet mode). */ gauntletVersion?: string; budget?: DesignBudget; /** Master seed; identical seed + inputs + stub model reproduce the run. */ seed?: string; } export interface DesignResult { /** Discovered Teams, ranked by composite fitness (fittest first). */ discovered: DesignedTeam[]; /** Generations actually run (may be fewer than requested if the cap was hit). */ generations: number; seed: string; gauntletVersion: string; /** Pilot identity the fitness was measured under (ADR 0002/0004). */ pilot: string; /** The resolved budget the run used. */ budget: Required; /** Total Battles run across the whole search. */ battlesRun: number; /** Seed Teams that were illegal and excluded. */ errors: ValidationError[]; } /** * The LLM seam — stub-able so the whole search loop runs with no subscription * call. `proposeMutations` returns candidate Team pastes (legality-checked by * the caller); `nameArchetype` labels a Team. */ export interface DesignerModel { readonly name: string; proposeMutations(paste: string, critique?: string): Promise; nameArchetype(paste: string, note: string): Promise<{ archetype: string; novel: boolean; }>; }