File size: 13,205 Bytes
3d46076
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
730a23d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3d46076
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
730a23d
 
 
 
3d46076
 
 
 
730a23d
 
 
 
3d46076
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
730a23d
 
3d46076
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
#!/usr/bin/env python3
"""

FlyBrain - Autonomous Biological Connectome Framework Entrypoint.

Supports rich subcommands: run, lab, experiment (run, verify, compare),

acceptance-matrix, docs-verify, diagnostics, test, validate-vulkan, benchmark, evolve.

"""

import os
import sys
import argparse
import json
import numpy as np

# Ensure project root in sys.path
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if PROJECT_ROOT not in sys.path:
    sys.path.insert(0, PROJECT_ROOT)

from src.connectome.types import GraphMode
from src.connectome.loader import get_or_create_circuit, load_raw_neurons
from src.brain.runtime import BrainRuntime
from src.brain.simulation_engine import SimulationEngine
from src.memory.persistence import PersistentMemoryManager
from src.trainer.curriculum import CurriculumTrainer
from src.evolution.scheduler import EvolutionScheduler
from src.dream.engine import DreamEngine
from src.experiment.manager import ExperimentManager
from src.compute.validator import run_cpu_gpu_validation

def run_diagnostics():
    from scripts.detect_env import main as detect_main
    from scripts.generate_manifests import main as manifest_main
    from scripts.validate_malecns_data import main as malecns_main
    
    print("Collecting system environment diagnostics...")
    detect_main()
    print("Validating biological malecns connectome source...")
    malecns_main()
    print("Generating dependency and reproducibility manifests...")
    manifest_main()
    print("Running Vulkan GPU vs CPU reference validation...")
    run_cpu_gpu_validation()
    print("\nAll diagnostics and validation manifests generated.")

def run_app(host="127.0.0.1", port=8080):
    import uvicorn
    from src.ui.server import app
    print(f"Starting FlyBrain Lab Scientific Workstation at http://{host}:{port}")
    uvicorn.run(app, host=host, port=port)


# First-run presets (V5 phase_29): real configurations, never unusable.
# Each maps to the FLYBRAIN_* env contract consumed by src/ui/server.py.
PRESETS = {
    "QUICK_DEMO": {"FLYBRAIN_CIRCUIT_SIZE": "128",
                   "FLYBRAIN_GRAPH_MODE": "SYNTHETIC_TEST",
                   "FLYBRAIN_USE_GPU": "0", "FLYBRAIN_AUTOSTART": "1"},
    "BIOLOGICAL_SUBGRAPH": {"FLYBRAIN_CIRCUIT_SIZE": "512",
                            "FLYBRAIN_GRAPH_MODE": "REAL_SUBGRAPH",
                            "FLYBRAIN_USE_GPU": "1", "FLYBRAIN_AUTOSTART": "0"},
    "GPU_PERFORMANCE": {"FLYBRAIN_CIRCUIT_SIZE": "1024",
                        "FLYBRAIN_GRAPH_MODE": "REAL_SUBGRAPH",
                        "FLYBRAIN_USE_GPU": "1", "FLYBRAIN_AUTOSTART": "1"},
    "CPU_SAFE": {"FLYBRAIN_CIRCUIT_SIZE": "256",
                 "FLYBRAIN_GRAPH_MODE": "REAL_SUBGRAPH",
                 "FLYBRAIN_USE_GPU": "0", "FLYBRAIN_AUTOSTART": "0"},
    "ALIFE_COLONY": {"FLYBRAIN_CIRCUIT_SIZE": "256",
                     "FLYBRAIN_GRAPH_MODE": "SYNTHETIC_TEST",
                     "FLYBRAIN_USE_GPU": "0", "FLYBRAIN_AUTOSTART": "0"},
    "RESEARCH": {"FLYBRAIN_CIRCUIT_SIZE": "512",
                 "FLYBRAIN_GRAPH_MODE": "REAL_SUBGRAPH",
                 "FLYBRAIN_USE_GPU": "1", "FLYBRAIN_AUTOSTART": "0"},
    "24_7_STREAM": {"FLYBRAIN_CIRCUIT_SIZE": "512",
                    "FLYBRAIN_GRAPH_MODE": "REAL_SUBGRAPH",
                    "FLYBRAIN_USE_GPU": "1", "FLYBRAIN_AUTOSTART": "1",
                    "FLYBRAIN_WATCHDOG": "1"},
}


def apply_preset(name: str) -> None:
    if name not in PRESETS:
        raise ValueError(f"unknown preset {name!r}; choices: {sorted(PRESETS)}")
    for k, v in PRESETS[name].items():
        os.environ.setdefault(k, v)
    print(f"[flybrain] preset {name}: " +
          ", ".join(f"{k}={v}" for k, v in PRESETS[name].items()))

def run_acceptance_matrix():
    from scripts.run_acceptance_matrix import evaluate_acceptance_matrix
    rep = evaluate_acceptance_matrix()
    if rep["failed"] > 0:
        sys.exit(1)

def run_docs_verify():
    from scripts.verify_docs_consistency import verify_docs_consistency
    ok = verify_docs_consistency()
    if not ok:
        sys.exit(1)

def main():
    parser = argparse.ArgumentParser(
        description="FlyBrain - Autonomous Biological Connectome Research Framework",
        formatter_class=argparse.RawDescriptionHelpFormatter
    )
    
    # Optional backward compatibility flag
    parser.add_argument("--mode", choices=["run", "lab", "diagnostics", "validate-vulkan", "benchmark", "evolve", "test", "acceptance-matrix", "docs-verify"], default=None,
                        help="Legacy execution mode selector")
    parser.add_argument("--host", default="127.0.0.1", help="Host address for UI server")
    parser.add_argument("--port", type=int, default=8080, help="Port for UI server")
    parser.add_argument("--circuit-size", type=int, default=512, help="Number of neurons in connectome circuit")
    parser.add_argument("--generations", type=int, default=3, help="Evolution generations")
    parser.add_argument("--seed", type=int, default=42, help="Deterministic PRNG seed")

    subparsers = parser.add_subparsers(dest="subcommand", help="FlyBrain Subcommands")

    # flybrain run / lab
    sub_run = subparsers.add_parser("run", help="Start FlyBrain Lab interactive server")
    sub_run.add_argument("--host", default="127.0.0.1")
    sub_run.add_argument("--port", type=int, default=8080)
    sub_run.add_argument("--preset", default=None,
                         choices=["QUICK_DEMO", "BIOLOGICAL_SUBGRAPH", "GPU_PERFORMANCE",
                                  "CPU_SAFE", "ALIFE_COLONY", "RESEARCH", "24_7_STREAM"],
                         help="First-run configuration preset (real configs)")

    sub_lab = subparsers.add_parser("lab", help="Launch FlyBrain Lab scientific workstation")
    sub_lab.add_argument("--host", default="127.0.0.1")
    sub_lab.add_argument("--port", type=int, default=8080)
    sub_lab.add_argument("--preset", default=None,
                         choices=["QUICK_DEMO", "BIOLOGICAL_SUBGRAPH", "GPU_PERFORMANCE",
                                  "CPU_SAFE", "ALIFE_COLONY", "RESEARCH", "24_7_STREAM"],
                         help="First-run configuration preset (real configs)")

    # flybrain experiment (run, verify, compare)
    sub_exp = subparsers.add_parser("experiment", help="Manage deterministic research experiments")
    exp_subs = sub_exp.add_subparsers(dest="exp_command", help="Experiment subcommands")

    exp_run = exp_subs.add_parser("run", help="Execute an experiment")
    exp_run.add_argument("--spec", default=None, help="Path to experiment JSON spec file")
    exp_run.add_argument("--id", default=None, help="Custom experiment identifier")
    exp_run.add_argument("--seed", type=int, default=42, help="PRNG seed")
    exp_run.add_argument("--mode", choices=["REAL", "REAL_SUBGRAPH", "SPATIAL_SURROGATE", "SYNTHETIC_TEST"], default="REAL", help="Connectome graph mode (REAL = REAL_SUBGRAPH sampled)")
    exp_run.add_argument("--scale", type=int, default=256, help="Number of neurons")
    exp_run.add_argument("--steps", type=int, default=50, help="Number of simulation steps")
    exp_run.add_argument("--no-gpu", action="store_true", help="Force CPU reference backend")

    exp_verify = exp_subs.add_parser("verify", help="Verify bitwise replication of an experiment")
    exp_verify.add_argument("--result", required=True, help="Experiment ID or path to experiment manifest JSON")

    exp_compare = exp_subs.add_parser("compare", help="Compare two experiment results")
    exp_compare.add_argument("--a", required=True, help="First experiment ID or manifest path")
    exp_compare.add_argument("--b", required=True, help="Second experiment ID or manifest path")

    # flybrain acceptance-matrix
    subparsers.add_parser("acceptance-matrix", help="Run canonical release acceptance matrix (verification/acceptance_schema.json)")

    # flybrain docs-verify
    subparsers.add_parser("docs-verify", help="Verify consistency between code, shaders, and documentation")

    # flybrain diagnostics
    subparsers.add_parser("diagnostics", help="Run full environment & hardware diagnostic suite")

    # flybrain validate-vulkan
    subparsers.add_parser("validate-vulkan", help="Run CPU vs Vulkan GPU compute parity validation suite")

    # flybrain test
    subparsers.add_parser("test", help="Run full test suite")

    # flybrain doctor
    subparsers.add_parser("doctor", help="Verify real environment: dataset, shaders, GPU, LLM, runtime")

    # flybrain version
    subparsers.add_parser("version", help="Print FlyBrain version")

    # flybrain benchmark
    subparsers.add_parser("benchmark", help="Run curriculum performance benchmarks")

    # flybrain evolve
    sub_evolve = subparsers.add_parser("evolve", help="Run genetic evolution loop on connectome")
    sub_evolve.add_argument("--circuit-size", type=int, default=512)
    sub_evolve.add_argument("--generations", type=int, default=3)
    sub_evolve.add_argument("--seed", type=int, default=42)

    args = parser.parse_args()

    # Determine execution target
    target = args.subcommand or args.mode or "run"

    if target in ("run", "lab"):
        h = getattr(args, "host", "127.0.0.1")
        p = getattr(args, "port", 8080)
        if getattr(args, "preset", None):
            apply_preset(args.preset)
        run_app(host=h, port=p)
    elif target == "experiment":
        exp_mgr = ExperimentManager()
        if args.exp_command == "run":
            if args.spec and os.path.exists(args.spec):
                with open(args.spec, "r", encoding="utf-8") as f:
                    spec_data = json.load(f)
                from src.connectome.types import coerce_graph_mode as _coerce
                seed = spec_data.get("seed", 42)
                mode = _coerce(spec_data.get("graph_mode", "REAL"))
                scale = spec_data.get("neuron_scale", 256)
                steps = spec_data.get("duration_steps", 50)
                use_gpu = spec_data.get("use_gpu", True)
                exp_id = spec_data.get("experiment_id", None)
            else:
                from src.connectome.types import coerce_graph_mode
                seed = args.seed
                mode = coerce_graph_mode(args.mode)
                scale = args.scale
                steps = args.steps
                use_gpu = not args.no_gpu
                exp_id = args.id

            manifest = exp_mgr.run_experiment(
                experiment_id=exp_id,
                seed=seed,
                graph_mode=mode,
                neuron_scale=scale,
                duration_steps=steps,
                use_gpu=use_gpu
            )
            print(f"Experiment completed successfully: {manifest.experiment_id}")
            print(f"Final State Hash: {manifest.final_state_hash}")
            print(f"Mean Latency: {manifest.metrics['mean_step_latency_ms']} ms ({manifest.metrics['throughput_steps_per_sec']} steps/sec)")
        elif args.exp_command == "verify":
            exp_id = args.result
            if exp_id.endswith(".json"):
                exp_id = os.path.splitext(os.path.basename(exp_id))[0]
            res = exp_mgr.verify_experiment(exp_id)
            print(json.dumps(res, indent=2))
            if res["status"] != "PASS":
                sys.exit(1)
        elif args.exp_command == "compare":
            id_a = os.path.splitext(os.path.basename(args.a))[0] if args.a.endswith(".json") else args.a
            id_b = os.path.splitext(os.path.basename(args.b))[0] if args.b.endswith(".json") else args.b
            comp = exp_mgr.compare_experiments(id_a, id_b)
            print(json.dumps(comp, indent=2))
        else:
            sub_exp.print_help()
    elif target == "acceptance-matrix":
        run_acceptance_matrix()
    elif target == "docs-verify":
        run_docs_verify()
    elif target == "diagnostics":
        run_diagnostics()
    elif target == "validate-vulkan":
        run_cpu_gpu_validation()
    elif target == "benchmark":
        import scripts.run_curriculum_benchmark as bm
        bm.run_benchmarks()
    elif target == "evolve":
        circuit = get_or_create_circuit(args.circuit_size)
        evo = EvolutionScheduler(circuit)
        for g in range(args.generations):
            evo.run_generation(num_candidates=4, seed=args.seed + g*10)
    elif target == "test":
        import unittest
        loader = unittest.TestLoader()
        suite = loader.discover("tests", pattern="test_*.py")
        runner = unittest.TextTestRunner(verbosity=2)
        res = runner.run(suite)
        if not res.wasSuccessful():
            sys.exit(1)
    elif target == "doctor":
        from src.diagnostics.doctor import main as doctor_main
        sys.exit(doctor_main())
    elif target == "version":
        from src.version import VERSION
        print(f"FlyBrain {VERSION}")
    else:
        parser.print_help()

if __name__ == "__main__":
    main()