import importlib import pandas as pd def test_streamlit_app_imports(): importlib.import_module("multi_swarm.dashboard.data") def test_dashboard_data_helpers_signatures(): from multi_swarm.dashboard import data assert hasattr(data, "list_runs_df") assert hasattr(data, "generations_df") assert hasattr(data, "evaluations_df") assert hasattr(data, "genomes_df") def test_aquarium_helper_builds_html_with_click_handler(): from multi_swarm.dashboard.aquarium import build_aquarium_html fish = [ { "id": "abc123", "fitness": 0.8, "cognitive_style": "physicist", "n_trades": 30, "dsr": 0.7, "sharpe": 1.2, "max_dd": 0.1, "system_prompt": "test", "temperature": 0.9, "lookback_window": 200, "feature_access": ["close"], "model_tier": "C", "generation": 1, "parent_ids": [], "ancestors": [], } ] html = build_aquarium_html(fish, canvas_w=800, canvas_h=400) assert "canvas" in html assert "abc123" in html # fish id present in JSON payload assert "addEventListener('click'" in html assert "fish-info-panel" in html assert "showFishInfo" in html assert "Discendenza" in html assert "requestAnimationFrame" in html def test_aquarium_build_fish_dataset_legacy_path(): from multi_swarm.dashboard.aquarium import build_fish_dataset df = pd.DataFrame( [ { "genome_id": "low", "fitness": 0.1, "cognitive_style": "physicist", "n_trades": 1, "dsr": 0.0, }, { "genome_id": "high", "fitness": 0.9, "cognitive_style": "biologist", "n_trades": 10, "dsr": 0.5, }, ] ) out = build_fish_dataset(df) ids = {f["id"] for f in out} assert ids == {"low", "high"} high = next(f for f in out if f["id"] == "high") assert high["cognitive_style"] == "biologist" assert high["ancestors"] == [] def test_aquarium_build_fish_dataset_drops_nan_fitness(): from multi_swarm.dashboard.aquarium import build_fish_dataset df = pd.DataFrame( [ { "genome_id": "ok", "fitness": 0.4, "cognitive_style": "historian", "n_trades": 2, "dsr": 0.1, }, { "genome_id": "bad", "fitness": float("nan"), "cognitive_style": "ecologist", "n_trades": 0, "dsr": 0.0, }, ] ) out = build_fish_dataset(df) assert len(out) == 1 assert out[0]["id"] == "ok" def test_aquarium_empty_input_returns_empty(): from multi_swarm.dashboard.aquarium import build_aquarium_html, build_fish_dataset assert build_fish_dataset(pd.DataFrame()) == [] html = build_aquarium_html([], canvas_w=400, canvas_h=200) assert "canvas" in html assert "Acquario vuoto" in html def test_build_lineage_index_returns_dict_keyed_by_id(): from multi_swarm.dashboard.aquarium import build_lineage_index genomes = pd.DataFrame( [ { "id": "g1", "generation_idx": 0, "generation": 0, "system_prompt": "x", "feature_access": ["close"], "temperature": 0.9, "top_p": 0.95, "model_tier": "C", "lookback_window": 100, "cognitive_style": "physicist", "parent_ids": [], }, { "id": "g2", "generation_idx": 1, "generation": 1, "system_prompt": "y", "feature_access": ["close", "volume"], "temperature": 1.0, "top_p": 0.95, "model_tier": "C", "lookback_window": 200, "cognitive_style": "biologist", "parent_ids": ["g1"], }, ] ) evals = pd.DataFrame( [ { "genome_id": "g1", "fitness": 0.5, "dsr": 0.6, "sharpe": 1.2, "max_dd": 0.1, "n_trades": 30, "parse_error": None, "raw_text": "", }, { "genome_id": "g2", "fitness": 0.7, "dsr": 0.8, "sharpe": 1.5, "max_dd": 0.05, "n_trades": 40, "parse_error": None, "raw_text": "", }, ] ) idx = build_lineage_index(genomes, evals) assert "g1" in idx and "g2" in idx assert idx["g2"]["parent_ids"] == ["g1"] assert idx["g2"]["fitness"] == 0.7 assert idx["g1"]["cognitive_style"] == "physicist" assert idx["g2"]["feature_access"] == ["close", "volume"] def test_trace_ancestors_walks_levels(): from multi_swarm.dashboard.aquarium import trace_ancestors idx = { "child": { "id": "child", "parent_ids": ["p1", "p2"], "fitness": 0.8, "generation": 2, "cognitive_style": "physicist", }, "p1": { "id": "p1", "parent_ids": ["gp1"], "fitness": 0.5, "generation": 1, "cognitive_style": "biologist", }, "p2": { "id": "p2", "parent_ids": [], "fitness": 0.3, "generation": 1, "cognitive_style": "engineer", }, "gp1": { "id": "gp1", "parent_ids": [], "fitness": 0.2, "generation": 0, "cognitive_style": "historian", }, } levels = trace_ancestors("child", idx, max_levels=5) assert len(levels) == 2 assert {a["id"] for a in levels[0]} == {"p1", "p2"} assert {a["id"] for a in levels[1]} == {"gp1"} def test_trace_ancestors_handles_cycles(): from multi_swarm.dashboard.aquarium import trace_ancestors # Pathological cycle: a <-> b. Should terminate cleanly. idx = { "a": { "id": "a", "parent_ids": ["b"], "fitness": 0.1, "generation": 1, "cognitive_style": "physicist", }, "b": { "id": "b", "parent_ids": ["a"], "fitness": 0.2, "generation": 0, "cognitive_style": "biologist", }, } levels = trace_ancestors("a", idx, max_levels=5) # a -> b at level 0; b's only parent is a, already seen -> stop. assert len(levels) == 1 assert levels[0][0]["id"] == "b" def test_trace_ancestors_no_parents_returns_empty(): from multi_swarm.dashboard.aquarium import trace_ancestors idx = { "solo": { "id": "solo", "parent_ids": [], "fitness": 0.4, "generation": 0, "cognitive_style": "engineer", }, } assert trace_ancestors("solo", idx) == [] def test_build_fish_dataset_attaches_ancestors(): from multi_swarm.dashboard.aquarium import build_fish_dataset, build_lineage_index genomes = pd.DataFrame( [ { "id": "p", "generation_idx": 0, "generation": 0, "system_prompt": "p", "feature_access": ["close"], "temperature": 0.8, "top_p": 0.9, "model_tier": "C", "lookback_window": 100, "cognitive_style": "physicist", "parent_ids": [], }, { "id": "c", "generation_idx": 1, "generation": 1, "system_prompt": "c", "feature_access": ["close"], "temperature": 0.8, "top_p": 0.9, "model_tier": "C", "lookback_window": 120, "cognitive_style": "biologist", "parent_ids": ["p"], }, ] ) evals = pd.DataFrame( [ {"genome_id": "p", "fitness": 0.3, "dsr": 0.0, "sharpe": 0.0, "max_dd": 0.0, "n_trades": 0}, {"genome_id": "c", "fitness": 0.6, "dsr": 0.0, "sharpe": 0.0, "max_dd": 0.0, "n_trades": 0}, ] ) lineage = build_lineage_index(genomes, evals) active = genomes[genomes["generation_idx"] == 1].merge( evals, left_on="id", right_on="genome_id", how="left" ) fish = build_fish_dataset(active, lineage) assert len(fish) == 1 assert fish[0]["id"] == "c" assert len(fish[0]["ancestors"]) == 1 assert fish[0]["ancestors"][0][0]["id"] == "p"