







fn get_model(pick: Int) -> String {
    if pick == 0 { return "meta/llama-3.3-70b-instruct" }
    if pick == 1 { return "google/gemma-2-27b-it" }
    if pick == 2 { return "mistralai/mixtral-8x22b-instruct-v0.1" }
    if pick == 3 { return "microsoft/phi-3-medium-128k-instruct" }
    return "mistralai/mistral-7b-instruct-v0.3"
}

fn get_topic(pick: Int) -> String {
    if pick == 0 { return "what animals do and why" }
    if pick == 1 { return "feelings and emotions" }
    if pick == 2 { return "how weather works" }
    if pick == 3 { return "food and cooking" }
    if pick == 4 { return "colors and what they mean" }
    if pick == 5 { return "family and friends" }
    if pick == 6 { return "the ocean and sea creatures" }
    if pick == 7 { return "music and sounds" }
    if pick == 8 { return "stars and the night sky" }
    if pick == 9 { return "plants and how they grow" }
    if pick == 10 { return "what makes things hot or cold" }
    if pick == 11 { return "rain and water" }
    if pick == 12 { return "being brave and trying new things" }
    if pick == 13 { return "toys and play" }
    if pick == 14 { return "morning and bedtime" }
    if pick == 15 { return "bugs and small creatures" }
    if pick == 16 { return "what different jobs people do" }
    if pick == 17 { return "seasons and why they change" }
    if pick == 18 { return "shapes and patterns" }
    return "being kind and helping others"
}

fn ask_api(system_prompt: String, last_msg: String, model_name: String) -> String {
    write_file("/tmp/scyla_auto_system.txt", system_prompt)
    write_file("/tmp/scyla_auto_user.txt", last_msg)
    write_file("/tmp/scyla_auto_model.txt", model_name)
    let result = shell_exec("timeout 60 python3 /home/kishonic/scyla/tools/auto_talk.py")
    return result
}

fn main() {
    println("============================================================")
    println("  AUTO TRAINER - Silkie learns by eavesdropping")
    println("  Two AIs talk. Silkie listens, trains, mints topos.")
    println("  GPU accelerated. Saves every epoch.")
    println("============================================================")

    let n = load_model("examples/silkie_full.safetensors")
    let ns = create_neuron_stack(1, 512, 64)
    let cs = create_cascade()
    let ts = load_tokenizer("examples/silkie_tokenizer.json")
    let tp = load_topos("examples/silkie_topos.json")
    println(tp)
    let sc = load_schemas("examples/silkie_schemas.json")
    println(sc)

    let embed_w = model_get("token_embedding.weight")
    let lr = 0.000003
    let total_steps = 0


    for epoch in 0..50 {

        let model_a_pick = epoch - ((epoch / 5) * 5)
        let model_b_pick = (epoch + 2) - (((epoch + 2) / 5) * 5)
        let topic_pick = epoch - ((epoch / 20) * 20)

        let model_a = get_model(model_a_pick)
        let model_b = get_model(model_b_pick)
        let topic = get_topic(topic_pick)

        println("")
        println("=== EPOCH " + (epoch + 1) + " ===")
        println("  A: " + model_a)
        println("  B: " + model_b)
        println("  Topic: " + topic)

        let system_prompt = "You are having a simple, friendly conversation about: " + topic + ". Use short sentences (1-2 max). Simple vocabulary like talking to a child. Be warm and curious."
        let last_said = "Tell me about " + topic + "."
        let epoch_steps = 0


        for round in 0..10 {


            let msg_a = ask_api(system_prompt, last_said, model_a)
            if str_len(msg_a) < 3 {
                println("  [A failed, skipping round]")
            }
            if str_len(msg_a) > 2 {
                println("  A: " + msg_a)

                let topos_before = topos_count()
                let generated = tokenize(msg_a)
                let input_len = tensor_len(generated)
                let seq_len = input_len
                neuron_stack_reset()
                cascade_reset()
                for step in 0..8 {
                    let flat = t_reshape(generated, seq_len)
                    let x = embedding_lookup(embed_w, flat)
                    let x = t_reshape(x, 1, seq_len, 512)
                    for layer_idx in 0..8 {
                        let prefix = "layers." + layer_idx
                        let x = transformer_block(x,
                            model_get(prefix + ".attention.in_proj_weight"),
                            model_get(prefix + ".attention.in_proj_bias"),
                            model_get(prefix + ".attention.out_proj.weight"),
                            model_get(prefix + ".attention.out_proj.bias"),
                            model_get(prefix + ".ff.0.weight"),
                            model_get(prefix + ".ff.0.bias"),
                            model_get(prefix + ".ff.3.weight"),
                            model_get(prefix + ".ff.3.bias"),
                            model_get(prefix + ".norm1.weight"),
                            model_get(prefix + ".norm1.bias"),
                            model_get(prefix + ".norm2.weight"),
                            model_get(prefix + ".norm2.bias"), 8)
                    }
                    neuron_stack_apply_noise(1.0)
                    let x = neuron_stack_forward(x)
                    let pooled = t_mean_seq(x)
                    let emotion = t_slice(pooled, -1, 0, 34)
                    topos_observe(emotion)
                    let x = layer_norm(x, model_get("layers.0.norm1.weight"), model_get("layers.0.norm1.bias"))
                    let logits = matmul(x, transpose(embed_w))
                    let logits_2d = t_reshape(logits, seq_len, 4100)
                    let last_logits = t_slice(logits_2d, 0, seq_len - 1, seq_len)
                    let last_logits = presence_penalty(last_logits, flat, 1.2)
                    let masked = topk_mask(last_logits, 50)
                    let probs = softmax(masked)
                    let next_token = t_multinomial(probs)
                    neuron_stack_suppress_repeat(0.85)
                    let generated = t_cat(generated, t_reshape(next_token, 1, 1))
                    let seq_len = seq_len + 1
                }
                let gen_flat = t_reshape(generated, seq_len)
                let new_words = detokenize_range(gen_flat, input_len, seq_len)
                println("  Silkie: [" + new_words + "]")


                gc()
                neuron_stack_reset()
                cascade_reset()
                begin_tape()
                let qkv_0 = register_param("qkv_0", model_get("layers.0.attention.in_proj_weight"))
                let qkv_1 = register_param("qkv_1", model_get("layers.1.attention.in_proj_weight"))
                let qkv_2 = register_param("qkv_2", model_get("layers.2.attention.in_proj_weight"))
                let qkv_3 = register_param("qkv_3", model_get("layers.3.attention.in_proj_weight"))
                let qkv_4 = register_param("qkv_4", model_get("layers.4.attention.in_proj_weight"))
                let qkv_5 = register_param("qkv_5", model_get("layers.5.attention.in_proj_weight"))
                let qkv_6 = register_param("qkv_6", model_get("layers.6.attention.in_proj_weight"))
                let qkv_7 = register_param("qkv_7", model_get("layers.7.attention.in_proj_weight"))
                let flat = t_reshape(generated, seq_len)
                let x = embedding_lookup(embed_w, flat)
                let x = t_reshape(x, 1, seq_len, 512)
                let x = transformer_block_train(x, qkv_0, model_get("layers.0.attention.in_proj_bias"), model_get("layers.0.attention.out_proj.weight"), model_get("layers.0.attention.out_proj.bias"), model_get("layers.0.ff.0.weight"), model_get("layers.0.ff.0.bias"), model_get("layers.0.ff.3.weight"), model_get("layers.0.ff.3.bias"), model_get("layers.0.norm1.weight"), model_get("layers.0.norm1.bias"), model_get("layers.0.norm2.weight"), model_get("layers.0.norm2.bias"), 8)
                let x = transformer_block_train(x, qkv_1, model_get("layers.1.attention.in_proj_bias"), model_get("layers.1.attention.out_proj.weight"), model_get("layers.1.attention.out_proj.bias"), model_get("layers.1.ff.0.weight"), model_get("layers.1.ff.0.bias"), model_get("layers.1.ff.3.weight"), model_get("layers.1.ff.3.bias"), model_get("layers.1.norm1.weight"), model_get("layers.1.norm1.bias"), model_get("layers.1.norm2.weight"), model_get("layers.1.norm2.bias"), 8)
                let x = transformer_block_train(x, qkv_2, model_get("layers.2.attention.in_proj_bias"), model_get("layers.2.attention.out_proj.weight"), model_get("layers.2.attention.out_proj.bias"), model_get("layers.2.ff.0.weight"), model_get("layers.2.ff.0.bias"), model_get("layers.2.ff.3.weight"), model_get("layers.2.ff.3.bias"), model_get("layers.2.norm1.weight"), model_get("layers.2.norm1.bias"), model_get("layers.2.norm2.weight"), model_get("layers.2.norm2.bias"), 8)
                let x = transformer_block_train(x, qkv_3, model_get("layers.3.attention.in_proj_bias"), model_get("layers.3.attention.out_proj.weight"), model_get("layers.3.attention.out_proj.bias"), model_get("layers.3.ff.0.weight"), model_get("layers.3.ff.0.bias"), model_get("layers.3.ff.3.weight"), model_get("layers.3.ff.3.bias"), model_get("layers.3.norm1.weight"), model_get("layers.3.norm1.bias"), model_get("layers.3.norm2.weight"), model_get("layers.3.norm2.bias"), 8)
                let x = transformer_block_train(x, qkv_4, model_get("layers.4.attention.in_proj_bias"), model_get("layers.4.attention.out_proj.weight"), model_get("layers.4.attention.out_proj.bias"), model_get("layers.4.ff.0.weight"), model_get("layers.4.ff.0.bias"), model_get("layers.4.ff.3.weight"), model_get("layers.4.ff.3.bias"), model_get("layers.4.norm1.weight"), model_get("layers.4.norm1.bias"), model_get("layers.4.norm2.weight"), model_get("layers.4.norm2.bias"), 8)
                let x = transformer_block_train(x, qkv_5, model_get("layers.5.attention.in_proj_bias"), model_get("layers.5.attention.out_proj.weight"), model_get("layers.5.attention.out_proj.bias"), model_get("layers.5.ff.0.weight"), model_get("layers.5.ff.0.bias"), model_get("layers.5.ff.3.weight"), model_get("layers.5.ff.3.bias"), model_get("layers.5.norm1.weight"), model_get("layers.5.norm1.bias"), model_get("layers.5.norm2.weight"), model_get("layers.5.norm2.bias"), 8)
                let x = transformer_block_train(x, qkv_6, model_get("layers.6.attention.in_proj_bias"), model_get("layers.6.attention.out_proj.weight"), model_get("layers.6.attention.out_proj.bias"), model_get("layers.6.ff.0.weight"), model_get("layers.6.ff.0.bias"), model_get("layers.6.ff.3.weight"), model_get("layers.6.ff.3.bias"), model_get("layers.6.norm1.weight"), model_get("layers.6.norm1.bias"), model_get("layers.6.norm2.weight"), model_get("layers.6.norm2.bias"), 8)
                let x = transformer_block_train(x, qkv_7, model_get("layers.7.attention.in_proj_bias"), model_get("layers.7.attention.out_proj.weight"), model_get("layers.7.attention.out_proj.bias"), model_get("layers.7.ff.0.weight"), model_get("layers.7.ff.0.bias"), model_get("layers.7.ff.3.weight"), model_get("layers.7.ff.3.bias"), model_get("layers.7.norm1.weight"), model_get("layers.7.norm1.bias"), model_get("layers.7.norm2.weight"), model_get("layers.7.norm2.bias"), 8)
                let logits = t_matmul(x, transpose(embed_w))
                end_tape()
                backward(logits)
                model_set("layers.0.attention.in_proj_weight", sgd_step(qkv_0, get_grad("qkv_0"), lr))
                model_set("layers.1.attention.in_proj_weight", sgd_step(qkv_1, get_grad("qkv_1"), lr))
                model_set("layers.2.attention.in_proj_weight", sgd_step(qkv_2, get_grad("qkv_2"), lr))
                model_set("layers.3.attention.in_proj_weight", sgd_step(qkv_3, get_grad("qkv_3"), lr))
                model_set("layers.4.attention.in_proj_weight", sgd_step(qkv_4, get_grad("qkv_4"), lr))
                model_set("layers.5.attention.in_proj_weight", sgd_step(qkv_5, get_grad("qkv_5"), lr))
                model_set("layers.6.attention.in_proj_weight", sgd_step(qkv_6, get_grad("qkv_6"), lr))
                model_set("layers.7.attention.in_proj_weight", sgd_step(qkv_7, get_grad("qkv_7"), lr))


                let topos_after = topos_count()
                let topos_minted_this_turn = topos_after - topos_before

                if topos_minted_this_turn > 1 {
                    neuron_stack_reset()
                    cascade_reset()
                    let df = t_reshape(generated, seq_len)
                    let dx = embedding_lookup(embed_w, df)
                    let dx = t_reshape(dx, 1, seq_len, 512)
                    for dl in 0..8 {
                        let dp = "layers." + dl
                        let dx = transformer_block(dx, model_get(dp + ".attention.in_proj_weight"), model_get(dp + ".attention.in_proj_bias"), model_get(dp + ".attention.out_proj.weight"), model_get(dp + ".attention.out_proj.bias"), model_get(dp + ".ff.0.weight"), model_get(dp + ".ff.0.bias"), model_get(dp + ".ff.3.weight"), model_get(dp + ".ff.3.bias"), model_get(dp + ".norm1.weight"), model_get(dp + ".norm1.bias"), model_get(dp + ".norm2.weight"), model_get(dp + ".norm2.bias"), 8)
                    }
                    neuron_stack_apply_noise(1.0)
                    let dx = neuron_stack_forward(dx)
                    let dp2 = t_mean_seq(dx)
                    let de = t_slice(dp2, -1, 0, 34)
                    topos_dream(de)
                }

                let last_said = msg_a
                let total_steps = total_steps + 1
                let epoch_steps = epoch_steps + 1
            }


            let msg_b = ask_api(system_prompt, last_said, model_b)
            if str_len(msg_b) < 3 {
                println("  [B failed, skipping]")
            }
            if str_len(msg_b) > 2 {
                println("  B: " + msg_b)

                let topos_before_b = topos_count()
                let generated = tokenize(msg_b)
                let input_len = tensor_len(generated)
                let seq_len = input_len
                neuron_stack_reset()
                cascade_reset()
                for step in 0..8 {
                    let flat = t_reshape(generated, seq_len)
                    let x = embedding_lookup(embed_w, flat)
                    let x = t_reshape(x, 1, seq_len, 512)
                    for layer_idx in 0..8 {
                        let prefix = "layers." + layer_idx
                        let x = transformer_block(x,
                            model_get(prefix + ".attention.in_proj_weight"),
                            model_get(prefix + ".attention.in_proj_bias"),
                            model_get(prefix + ".attention.out_proj.weight"),
                            model_get(prefix + ".attention.out_proj.bias"),
                            model_get(prefix + ".ff.0.weight"),
                            model_get(prefix + ".ff.0.bias"),
                            model_get(prefix + ".ff.3.weight"),
                            model_get(prefix + ".ff.3.bias"),
                            model_get(prefix + ".norm1.weight"),
                            model_get(prefix + ".norm1.bias"),
                            model_get(prefix + ".norm2.weight"),
                            model_get(prefix + ".norm2.bias"), 8)
                    }
                    neuron_stack_apply_noise(1.0)
                    let x = neuron_stack_forward(x)
                    let pooled = t_mean_seq(x)
                    let emotion = t_slice(pooled, -1, 0, 34)
                    topos_observe(emotion)
                    let x = layer_norm(x, model_get("layers.0.norm1.weight"), model_get("layers.0.norm1.bias"))
                    let logits = matmul(x, transpose(embed_w))
                    let logits_2d = t_reshape(logits, seq_len, 4100)
                    let last_logits = t_slice(logits_2d, 0, seq_len - 1, seq_len)
                    let last_logits = presence_penalty(last_logits, flat, 1.2)
                    let masked = topk_mask(last_logits, 50)
                    let probs = softmax(masked)
                    let next_token = t_multinomial(probs)
                    neuron_stack_suppress_repeat(0.85)
                    let generated = t_cat(generated, t_reshape(next_token, 1, 1))
                    let seq_len = seq_len + 1
                }
                let gen_flat = t_reshape(generated, seq_len)
                let new_words = detokenize_range(gen_flat, input_len, seq_len)
                println("  Silkie: [" + new_words + "]")


                gc()
                neuron_stack_reset()
                cascade_reset()
                begin_tape()
                let qkv_0 = register_param("qkv_0", model_get("layers.0.attention.in_proj_weight"))
                let qkv_1 = register_param("qkv_1", model_get("layers.1.attention.in_proj_weight"))
                let qkv_2 = register_param("qkv_2", model_get("layers.2.attention.in_proj_weight"))
                let qkv_3 = register_param("qkv_3", model_get("layers.3.attention.in_proj_weight"))
                let qkv_4 = register_param("qkv_4", model_get("layers.4.attention.in_proj_weight"))
                let qkv_5 = register_param("qkv_5", model_get("layers.5.attention.in_proj_weight"))
                let qkv_6 = register_param("qkv_6", model_get("layers.6.attention.in_proj_weight"))
                let qkv_7 = register_param("qkv_7", model_get("layers.7.attention.in_proj_weight"))
                let flat = t_reshape(generated, seq_len)
                let x = embedding_lookup(embed_w, flat)
                let x = t_reshape(x, 1, seq_len, 512)
                let x = transformer_block_train(x, qkv_0, model_get("layers.0.attention.in_proj_bias"), model_get("layers.0.attention.out_proj.weight"), model_get("layers.0.attention.out_proj.bias"), model_get("layers.0.ff.0.weight"), model_get("layers.0.ff.0.bias"), model_get("layers.0.ff.3.weight"), model_get("layers.0.ff.3.bias"), model_get("layers.0.norm1.weight"), model_get("layers.0.norm1.bias"), model_get("layers.0.norm2.weight"), model_get("layers.0.norm2.bias"), 8)
                let x = transformer_block_train(x, qkv_1, model_get("layers.1.attention.in_proj_bias"), model_get("layers.1.attention.out_proj.weight"), model_get("layers.1.attention.out_proj.bias"), model_get("layers.1.ff.0.weight"), model_get("layers.1.ff.0.bias"), model_get("layers.1.ff.3.weight"), model_get("layers.1.ff.3.bias"), model_get("layers.1.norm1.weight"), model_get("layers.1.norm1.bias"), model_get("layers.1.norm2.weight"), model_get("layers.1.norm2.bias"), 8)
                let x = transformer_block_train(x, qkv_2, model_get("layers.2.attention.in_proj_bias"), model_get("layers.2.attention.out_proj.weight"), model_get("layers.2.attention.out_proj.bias"), model_get("layers.2.ff.0.weight"), model_get("layers.2.ff.0.bias"), model_get("layers.2.ff.3.weight"), model_get("layers.2.ff.3.bias"), model_get("layers.2.norm1.weight"), model_get("layers.2.norm1.bias"), model_get("layers.2.norm2.weight"), model_get("layers.2.norm2.bias"), 8)
                let x = transformer_block_train(x, qkv_3, model_get("layers.3.attention.in_proj_bias"), model_get("layers.3.attention.out_proj.weight"), model_get("layers.3.attention.out_proj.bias"), model_get("layers.3.ff.0.weight"), model_get("layers.3.ff.0.bias"), model_get("layers.3.ff.3.weight"), model_get("layers.3.ff.3.bias"), model_get("layers.3.norm1.weight"), model_get("layers.3.norm1.bias"), model_get("layers.3.norm2.weight"), model_get("layers.3.norm2.bias"), 8)
                let x = transformer_block_train(x, qkv_4, model_get("layers.4.attention.in_proj_bias"), model_get("layers.4.attention.out_proj.weight"), model_get("layers.4.attention.out_proj.bias"), model_get("layers.4.ff.0.weight"), model_get("layers.4.ff.0.bias"), model_get("layers.4.ff.3.weight"), model_get("layers.4.ff.3.bias"), model_get("layers.4.norm1.weight"), model_get("layers.4.norm1.bias"), model_get("layers.4.norm2.weight"), model_get("layers.4.norm2.bias"), 8)
                let x = transformer_block_train(x, qkv_5, model_get("layers.5.attention.in_proj_bias"), model_get("layers.5.attention.out_proj.weight"), model_get("layers.5.attention.out_proj.bias"), model_get("layers.5.ff.0.weight"), model_get("layers.5.ff.0.bias"), model_get("layers.5.ff.3.weight"), model_get("layers.5.ff.3.bias"), model_get("layers.5.norm1.weight"), model_get("layers.5.norm1.bias"), model_get("layers.5.norm2.weight"), model_get("layers.5.norm2.bias"), 8)
                let x = transformer_block_train(x, qkv_6, model_get("layers.6.attention.in_proj_bias"), model_get("layers.6.attention.out_proj.weight"), model_get("layers.6.attention.out_proj.bias"), model_get("layers.6.ff.0.weight"), model_get("layers.6.ff.0.bias"), model_get("layers.6.ff.3.weight"), model_get("layers.6.ff.3.bias"), model_get("layers.6.norm1.weight"), model_get("layers.6.norm1.bias"), model_get("layers.6.norm2.weight"), model_get("layers.6.norm2.bias"), 8)
                let x = transformer_block_train(x, qkv_7, model_get("layers.7.attention.in_proj_bias"), model_get("layers.7.attention.out_proj.weight"), model_get("layers.7.attention.out_proj.bias"), model_get("layers.7.ff.0.weight"), model_get("layers.7.ff.0.bias"), model_get("layers.7.ff.3.weight"), model_get("layers.7.ff.3.bias"), model_get("layers.7.norm1.weight"), model_get("layers.7.norm1.bias"), model_get("layers.7.norm2.weight"), model_get("layers.7.norm2.bias"), 8)
                let logits = t_matmul(x, transpose(embed_w))
                end_tape()
                backward(logits)
                model_set("layers.0.attention.in_proj_weight", sgd_step(qkv_0, get_grad("qkv_0"), lr))
                model_set("layers.1.attention.in_proj_weight", sgd_step(qkv_1, get_grad("qkv_1"), lr))
                model_set("layers.2.attention.in_proj_weight", sgd_step(qkv_2, get_grad("qkv_2"), lr))
                model_set("layers.3.attention.in_proj_weight", sgd_step(qkv_3, get_grad("qkv_3"), lr))
                model_set("layers.4.attention.in_proj_weight", sgd_step(qkv_4, get_grad("qkv_4"), lr))
                model_set("layers.5.attention.in_proj_weight", sgd_step(qkv_5, get_grad("qkv_5"), lr))
                model_set("layers.6.attention.in_proj_weight", sgd_step(qkv_6, get_grad("qkv_6"), lr))
                model_set("layers.7.attention.in_proj_weight", sgd_step(qkv_7, get_grad("qkv_7"), lr))


                let topos_after_b = topos_count()
                let topos_minted_b = topos_after_b - topos_before_b

                if topos_minted_b > 1 {
                    neuron_stack_reset()
                    cascade_reset()
                    let df = t_reshape(generated, seq_len)
                    let dx = embedding_lookup(embed_w, df)
                    let dx = t_reshape(dx, 1, seq_len, 512)
                    for dl in 0..8 {
                        let dp = "layers." + dl
                        let dx = transformer_block(dx, model_get(dp + ".attention.in_proj_weight"), model_get(dp + ".attention.in_proj_bias"), model_get(dp + ".attention.out_proj.weight"), model_get(dp + ".attention.out_proj.bias"), model_get(dp + ".ff.0.weight"), model_get(dp + ".ff.0.bias"), model_get(dp + ".ff.3.weight"), model_get(dp + ".ff.3.bias"), model_get(dp + ".norm1.weight"), model_get(dp + ".norm1.bias"), model_get(dp + ".norm2.weight"), model_get(dp + ".norm2.bias"), 8)
                    }
                    neuron_stack_apply_noise(1.0)
                    let dx = neuron_stack_forward(dx)
                    let dp2 = t_mean_seq(dx)
                    let de = t_slice(dp2, -1, 0, 34)
                    topos_dream(de)
                }

                let last_said = msg_b
                let total_steps = total_steps + 1
                let epoch_steps = epoch_steps + 1
            }
        }

        neuron_stack_reset()
        cascade_reset()
        let dream_seed = t_randn(1, 512)
        let dream_x = dream_seed
        for dl in 0..8 {
            let dp = "layers." + dl
            let dream_x = transformer_block(dream_x, model_get(dp + ".attention.in_proj_weight"), model_get(dp + ".attention.in_proj_bias"), model_get(dp + ".attention.out_proj.weight"), model_get(dp + ".attention.out_proj.bias"), model_get(dp + ".ff.0.weight"), model_get(dp + ".ff.0.bias"), model_get(dp + ".ff.3.weight"), model_get(dp + ".ff.3.bias"), model_get(dp + ".norm1.weight"), model_get(dp + ".norm1.bias"), model_get(dp + ".norm2.weight"), model_get(dp + ".norm2.bias"), 8)
        }
        neuron_stack_apply_noise(1.0)
        let dream_x = neuron_stack_forward(dream_x)
        let dream_pooled = t_mean_seq(dream_x)
        let dream_emotion = t_slice(dream_pooled, -1, 0, 34)
        topos_dream(dream_emotion)
        println("  [epoch dream token minted - recollection of epoch " + (epoch + 1) + "]")

        let topos_now = topos_count()
        let saved = save_safetensors("examples/silkie_full.safetensors")
        let tsaved = save_topos("examples/silkie_topos.json")
        let ssaved = save_schemas("examples/silkie_schemas.json")
        let schema_now = schema_count()
        println("  [epoch " + (epoch + 1) + " | steps: " + epoch_steps + " | topos: " + topos_now + " | schemas: " + schema_now + " | " + saved + "]")
    }

    println("")
    println("============================================================")
    println("  AUTO TRAINING COMPLETE")
    println("  Total steps: " + total_steps)
    let final_topos = topos_count()
    println("  Final topos: " + final_topos)
    println("============================================================")
}
