Brain-5D-Space / tests /test_dashboard_completion.py
github-actions[bot]
Sync: publish Space API fix
5e0b58b
Raw History Blame Contribute Delete
21.5 kB
"""Tests for the Alpha.5 dashboard completion (observability + truthfulness).
Covers the requirements from the Alpha.5 Dashboard Completion mission:
- Tick-0 dashboard shows real network size.
- null metrics serialize as unavailable, not measured zero.
- disabled config component is reported disabled, not failed.
- canonical command contract works.
- structural controls disabled when config disabled.
- snapshot info uses real .b5d.
- integration status reads test_baseline.json and detects staleness.
- network inspector pagination.
- neuron inspector returns real 5D coordinates.
- synapse inspector returns real weights/delays.
- projection endpoint contains real 5D coordinates.
"""
from __future__ import annotations
import json
from pathlib import Path
from typing import Any, cast
from src.controller.runtime import RuntimeController
from src.core import Brain5DConfig, NeuralNetwork
from src.dashboard.integration_status import IntegrationStatusBuilder
from src.dashboard.models import (
DashboardSnapshot,
HomeostasisMetrics,
StorageMetrics,
SystemMetrics,
)
from src.dashboard.network_inspector import NetworkInspector
from src.dashboard.operator_bridge import OperatorBridge
from src.dashboard.state import DashboardStateStore
from src.dashboard.verification import (
EVIDENCE_SCOPES,
artifact_digest_matches,
compute_scope_digest,
)
def test_evidence_scope_digest_ignores_unrelated_dashboard_file(tmp_path: Path) -> None:
(tmp_path / "src" / "core").mkdir(parents=True)
(tmp_path / "src" / "dashboard").mkdir(parents=True)
(tmp_path / "src" / "core" / "state.py").write_text("state", encoding="utf-8")
(tmp_path / "src" / "dashboard" / "ui.js").write_text("one", encoding="utf-8")
first = compute_scope_digest(tmp_path, "restore_determinism")
(tmp_path / "src" / "dashboard" / "ui.js").write_text("two", encoding="utf-8")
assert compute_scope_digest(tmp_path, "restore_determinism") == first
def test_scoped_artifact_digest_is_preferred_and_legacy_fallback_remains(
tmp_path: Path,
) -> None:
assert "dashboard" in EVIDENCE_SCOPES
(tmp_path / "src" / "dashboard").mkdir(parents=True)
(tmp_path / "src" / "dashboard" / "state.py").write_text("state", encoding="utf-8")
digest = compute_scope_digest(tmp_path, "dashboard")
assert digest is not None
assert artifact_digest_matches(
tmp_path, {"scope": "dashboard", "scope_digest": digest}
)
# ============================================================
# Helpers
# ============================================================
def _build_real_network(n: int = 200) -> NeuralNetwork:
"""Build a small real network for inspector tests."""
config = Brain5DConfig.from_dict(
{
"dimensions": [10, 10, 10, 10, 10],
"network": {"initial_connections_per_neuron": 5, "neighbour_radius": 2.0},
}
)
import random
rng = random.Random(42)
network = NeuralNetwork(config, rng)
from src.core.spatial_index import linear_to_5d
dims = config.dimensions
for i in range(n):
network.add_neuron(linear_to_5d(i, dims))
network.initialize_random_connections(5, 2.0)
return network
def _bridge_with_network(network: NeuralNetwork) -> OperatorBridge:
controller = RuntimeController(network)
return OperatorBridge(controller=controller)
# ============================================================
# Phase 2: Tick-0 dashboard shows real network size
# ============================================================
def test_tick0_dashboard_shows_real_network_size() -> None:
"""At tick 0 the dashboard snapshot must show real neuron/synapse counts,
not zeros from missing tick history."""
network = _build_real_network(n=200)
expected_neurons = len(network.neurons)
expected_synapses = network.synapse_count
snapshot = DashboardSnapshot(
status="idle",
version="0.5.0-alpha.5",
system=SystemMetrics(
tick=0,
neurons=expected_neurons,
synapses=expected_synapses,
spikes_total=0,
spikes_last_tick=0,
),
)
payload = cast(dict[str, Any], snapshot.to_json())
assert payload["system"]["neurons"] == expected_neurons
assert payload["system"]["synapses"] == expected_synapses
assert payload["system"]["tick"] == 0
assert payload["status"] == "idle"
assert expected_neurons > 0
assert expected_synapses > 0
# ============================================================
# Phase 3: null metrics serialize as unavailable, not measured zero
# ============================================================
def test_null_storage_metrics_serialize_as_none() -> None:
"""StorageMetrics with available=False must serialize None fields,
so the frontend can render '—' instead of fake 0."""
storage = StorageMetrics() # available=False, all None
payload = cast(dict[str, Any], storage.to_json())
assert payload["available"] is False
assert payload["deltas_written"] is None
assert payload["bytes_written"] is None
assert payload["write_latency_ms"] is None
assert payload["commit_latency_ms"] is None
assert payload["journal_size_bytes"] is None
def test_measured_zero_storage_serializes_as_zero() -> None:
"""A measured zero must serialize as 0, not None."""
storage = StorageMetrics(
available=True,
deltas_written=0,
bytes_written=0,
write_latency_ms=0.0,
)
payload = cast(dict[str, Any], storage.to_json())
assert payload["available"] is True
assert payload["deltas_written"] == 0
assert payload["bytes_written"] == 0
assert payload["write_latency_ms"] == 0.0
def test_disabled_homeostasis_serializes_enabled_false() -> None:
homeo = HomeostasisMetrics(enabled=False)
payload = cast(dict[str, Any], homeo.to_json())
assert payload["enabled"] is False
# ============================================================
# Phase 4 / 14: disabled config component reported disabled, not failed
# ============================================================
def test_integration_status_reports_disabled_for_structural_when_not_configured() -> (
None
):
"""When structural plasticity is disabled by config (no coordinator),
integration status must report 'disabled', not 'failed'."""
network = _build_real_network(n=50)
bridge = _bridge_with_network(network)
store = DashboardStateStore()
# Publish a snapshot with storage available=False (poc_config default)
store.publish(
DashboardSnapshot(
status="idle",
system=SystemMetrics(tick=0, neurons=50),
storage=StorageMetrics(available=False),
)
)
builder = IntegrationStatusBuilder(
store.snapshot(),
bridge=bridge,
heatmap_source=None,
research_source=None,
repo_root=Path(__file__).resolve().parents[1],
)
status = cast(dict[str, Any], builder.build())
items_by_name = {item["name"]: item for item in status["items"]}
# Structural has no coordinator => disabled by config
assert items_by_name["Structural"]["status"] == "disabled"
assert items_by_name["Structural Journal"]["status"] == "disabled"
# Delta storage available=False => disabled by config
assert items_by_name["Delta Storage"]["status"] == "disabled"
# Bridge and controller are connected => passed
assert items_by_name["Bridge"]["status"] == "passed"
assert items_by_name["Controller"]["status"] == "passed"
# ============================================================
# Phase 5: canonical command contract works
# ============================================================
def test_canonical_command_run_ticks_advances_exactly_n_ticks() -> None:
"""POST /api/control {command: run_ticks, ticks: 100} must advance
exactly 100 ticks."""
from src.dashboard.control_service import DashboardControlService
network = _build_real_network(n=50)
controller = RuntimeController(network)
service = DashboardControlService(controller)
response = service.execute({"command": "run_ticks", "ticks": 100})
assert response.ok
assert response.status == 200
assert network.current_tick == 100
def test_canonical_command_step_advances_exactly_one_tick() -> None:
from src.dashboard.control_service import DashboardControlService
network = _build_real_network(n=50)
controller = RuntimeController(network)
service = DashboardControlService(controller)
response = service.execute({"command": "step"})
assert response.ok
assert network.current_tick == 1
def test_runtime_clock_can_be_configured_through_control_service() -> None:
from src.dashboard.control_service import DashboardControlService
service = DashboardControlService(RuntimeController(_build_real_network(n=10)))
response = service.execute({"command": "configure", "target_hz": 100.0})
assert response.ok
runtime_payload = cast(dict[str, Any], response.payload["runtime"])
assert runtime_payload["target_hz"] == 100.0
max_response = service.execute({"command": "configure", "target_hz": "MAX"})
assert max_response.ok
max_runtime_payload = cast(dict[str, Any], max_response.payload["runtime"])
assert max_runtime_payload["target_hz"] is None
def test_legacy_action_still_accepted_for_compat() -> None:
from src.dashboard.control_service import DashboardControlService
network = _build_real_network(n=50)
controller = RuntimeController(network)
service = DashboardControlService(controller)
response = service.execute({"action": "step"})
assert response.ok
assert network.current_tick == 1
# ============================================================
# Phase 6: structural controls disabled when config disabled
# ============================================================
def test_structural_status_unconfigured_when_no_coordinator() -> None:
"""When self_organization is disabled by config, the bridge has no
coordinator, so structural_status must report configured=False."""
network = _build_real_network(n=50)
bridge = _bridge_with_network(network) # no coordinator/plasticity
status = bridge.structural_status()
assert status["configured"] is False
assert status["proposal_count"] == 0
assert status["history_count"] == 0
# ============================================================
# Phase 8/9: network inspector returns real 5D coordinates
# ============================================================
def test_network_summary_returns_real_counts() -> None:
network = _build_real_network(n=200)
inspector = NetworkInspector(network)
summary = inspector.summary()
payload = cast(dict[str, Any], summary.to_json())
assert payload["neuron_count"] == 200
assert payload["synapse_count"] == network.synapse_count
assert payload["dimensions"] == [10, 10, 10, 10, 10]
assert payload["source"] == "live_runtime"
assert payload["mean_energy"] is not None
def test_neuron_inspector_returns_real_5d_coordinates() -> None:
network = _build_real_network(n=100)
inspector = NetworkInspector(network)
page = inspector.neurons(limit=10, offset=0)
payload = cast(dict[str, Any], page.to_json())
assert payload["returned"] == 10
assert payload["total"] == 100
assert payload["source"] == "live_runtime"
first = payload["neurons"][0]
# Each neuron must expose all 5 coordinates
for key in ("x1", "x2", "x3", "x4", "x5"):
assert key in first
assert "neuron_id" in first
assert "v" in first
assert "u" in first
assert "energy" in first
def test_neuron_inspector_pagination_consistent() -> None:
network = _build_real_network(n=100)
inspector = NetworkInspector(network)
page1 = inspector.neurons(limit=20, offset=0)
page2 = inspector.neurons(limit=20, offset=20)
ids1 = [n["neuron_id"] for n in cast(list[dict[str, Any]], page1.neurons)]
ids2 = [n["neuron_id"] for n in cast(list[dict[str, Any]], page2.neurons)]
# Pages must not overlap
assert set(ids1).isdisjoint(set(ids2))
assert page1.total == 100
assert page2.total == 100
def test_synapse_inspector_returns_real_weights_and_delays() -> None:
network = _build_real_network(n=100)
inspector = NetworkInspector(network)
page = inspector.synapses(limit=10, offset=0)
payload = cast(dict[str, Any], page.to_json())
assert payload["returned"] == 10
assert payload["total"] == network.synapse_count
assert payload["source"] == "live_runtime"
first = payload["synapses"][0]
assert "source_id" in first
assert "target_id" in first
assert "weight" in first
assert "delay" in first
def test_projection_endpoint_contains_real_5d_coordinates() -> None:
network = _build_real_network(n=300)
inspector = NetworkInspector(network)
proj = inspector.projection(limit=200, mode="activity")
payload = cast(dict[str, Any], proj.to_json())
assert payload["sample_count"] == 200
assert payload["total_count"] == 300
assert payload["source"] == "live_runtime"
assert "Projection of 5D coordinates into 3D" in str(payload["label"])
first = payload["points"][0]
for key in ("x", "y", "z", "d4", "d5", "value", "neuron_id"):
assert key in first
# ============================================================
# Phase 14: integration status reads test_baseline.json
# ============================================================
def test_integration_status_reads_test_baseline() -> None:
"""Integration status must read tests/test_baseline.json and report the
tested_commit vs current HEAD plus the tree-digest staleness model.
A baseline whose ``tested_tree_digest`` does NOT match the current
source-tree digest must be reported as STALE.
"""
repo_root = Path(__file__).resolve().parents[1]
baseline = {
"tested_commit": "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
"recorded_in_commit": "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
"tested_tree_digest": "0" * 64, # intentionally wrong digest
"python": "3.13.14",
"verified_subset": {"passed": 216, "failed": 0, "skipped": 2},
}
# Write a temporary baseline into the real repo's tests dir, then restore.
real_baseline = repo_root / "tests" / "test_baseline.json"
original = (
real_baseline.read_text(encoding="utf-8") if real_baseline.exists() else None
)
try:
real_baseline.write_text(json.dumps(baseline), encoding="utf-8")
network = _build_real_network(n=50)
bridge = _bridge_with_network(network)
store = DashboardStateStore()
store.publish(DashboardSnapshot(status="idle", system=SystemMetrics()))
builder = IntegrationStatusBuilder(
store.snapshot(),
bridge=bridge,
heatmap_source=None,
research_source=None,
repo_root=repo_root,
)
status = cast(dict[str, Any], builder.build())
tests_item = {i["name"]: i for i in status["items"]}["Tests"]
# The fake tree digest won't match the real source tree => STALE
assert tests_item["status"] == "stale"
assert tests_item["tested_commit"] == baseline["tested_commit"]
assert "current_commit" in tests_item
assert tests_item["current_commit"] is not None
assert "current_tree_digest" in tests_item
assert tests_item["current_tree_digest"] != baseline["tested_tree_digest"]
finally:
if original is not None:
real_baseline.write_text(original, encoding="utf-8")
def test_stale_tested_commit_detection() -> None:
"""When the source tree changed since the baseline (tree digest mismatch),
status must be 'stale' — even if the commit SHA differs only by baseline
metadata. This is the scientifically correct staleness model."""
repo_root = Path(__file__).resolve().parents[1]
baseline = {
"tested_commit": "aaaa1111aaaa1111aaaa1111aaaa1111aaaa1111",
"tested_tree_digest": "f" * 64, # wrong digest => stale
"verified_subset": {"passed": 10, "failed": 0, "skipped": 0},
}
real_baseline = repo_root / "tests" / "test_baseline.json"
original = (
real_baseline.read_text(encoding="utf-8") if real_baseline.exists() else None
)
try:
real_baseline.write_text(json.dumps(baseline), encoding="utf-8")
network = _build_real_network(n=50)
bridge = _bridge_with_network(network)
store = DashboardStateStore()
store.publish(DashboardSnapshot(status="idle", system=SystemMetrics()))
builder = IntegrationStatusBuilder(
store.snapshot(),
bridge=bridge,
repo_root=repo_root,
)
status = cast(dict[str, Any], builder.build())
tests_item = {i["name"]: i for i in status["items"]}["Tests"]
# The fake tree digest cannot match the real source tree
assert tests_item["status"] == "stale"
finally:
if original is not None:
real_baseline.write_text(original, encoding="utf-8")
def test_tree_digest_match_reports_passed() -> None:
"""When the recorded tree digest matches the current source tree, the
test status must be PASSED — even though the commit SHA differs. This
proves that a pure baseline/docs change does not invalidate the tests."""
repo_root = Path(__file__).resolve().parents[1]
# First compute the real current tree digest.
network = _build_real_network(n=50)
bridge = _bridge_with_network(network)
store = DashboardStateStore()
store.publish(DashboardSnapshot(status="idle", system=SystemMetrics()))
builder = IntegrationStatusBuilder(
store.snapshot(),
bridge=bridge,
repo_root=repo_root,
)
real_digest = builder._current_tree_digest() # type: ignore[reportPrivateUsage]
assert real_digest is not None, "tree digest must be computable"
baseline = {
"tested_commit": "aaaa2222aaaa2222aaaa2222aaaa2222aaaa2222",
"tested_tree_digest": real_digest, # matches current tree
"verified_subset": {"passed": 236, "failed": 0, "skipped": 2},
}
real_baseline = repo_root / "tests" / "test_baseline.json"
original = (
real_baseline.read_text(encoding="utf-8") if real_baseline.exists() else None
)
try:
real_baseline.write_text(json.dumps(baseline), encoding="utf-8")
status = cast(dict[str, Any], builder.build())
tests_item = {i["name"]: i for i in status["items"]}["Tests"]
# Digest matches => PASSED, even though commit SHA differs
assert tests_item["status"] == "passed"
assert tests_item["passed"] == 236
finally:
if original is not None:
real_baseline.write_text(original, encoding="utf-8")
# ============================================================
# Phase 15: no unknown /api route falls through to SPA
# ============================================================
def test_unknown_api_route_returns_json_error_not_spa() -> None:
"""An unknown /api/ route must return a JSON error, never index.html."""
from http import HTTPStatus
from src.dashboard.server import DashboardRequestHandler
# We test the handler logic directly by simulating the routing decision.
# The server's do_GET explicitly returns _send_api_not_found for /api/...
# We verify the constant is used (not a static-file fallback).
assert hasattr(DashboardRequestHandler, "_send_api_not_found")
assert HTTPStatus.NOT_FOUND == 404
# ============================================================
# Phase 16: provenance — network inspector source is live_runtime
# ============================================================
def test_network_inspector_provenance_is_live() -> None:
network = _build_real_network(n=50)
inspector = NetworkInspector(network)
assert (
cast(dict[str, Any], inspector.summary().to_json())["source"] == "live_runtime"
)
assert (
cast(dict[str, Any], inspector.neurons().to_json())["source"] == "live_runtime"
)
assert (
cast(dict[str, Any], inspector.synapses().to_json())["source"] == "live_runtime"
)
assert (
cast(dict[str, Any], inspector.projection().to_json())["source"]
== "live_runtime"
)
# ============================================================
# Phase 18: no demo heatmap source in normal runtime
# ============================================================
def test_no_demo_heatmap_source_class_in_inspector_module() -> None:
"""The network inspector must not import or use a DemoHeatmapSource."""
import src.dashboard.network_inspector as mod
# No DemoHeatmapSource should be referenced in the module
source = Path(mod.__file__).read_text(encoding="utf-8")
assert "DemoHeatmapSource" not in source
def test_serve_dashboard_does_not_create_demo_heatmap() -> None:
"""serve_dashboard must not create a synthetic demo heatmap source."""
import src.dashboard.server as server_mod
source = Path(server_mod.__file__).read_text(encoding="utf-8")
# The server explicitly avoids demo data
assert "Synthetic demo data must never" in source
assert "DemoHeatmapSource" not in source