main.go raw

   1  // Command memdump reads a dendrite memory database and prints its contents.
   2  package main
   3  
   4  import (
   5  	"fmt"
   6  	"os"
   7  
   8  	"git.mleku.dev/mleku/dendrite/pkg/memory"
   9  )
  10  
  11  func main() {
  12  	dir := "_output/inst0/memory"
  13  	if len(os.Args) > 1 {
  14  		dir = os.Args[1]
  15  	}
  16  
  17  	db, err := memory.Open(dir)
  18  	if err != nil {
  19  		fmt.Fprintf(os.Stderr, "open: %v\n", err)
  20  		os.Exit(1)
  21  	}
  22  	defer db.Close()
  23  
  24  	fmt.Printf("=== Memory DB: %s ===\n\n", dir)
  25  
  26  	// Generation metadata.
  27  	fmt.Println("--- Generations ---")
  28  	for gen := uint32(0); gen < 20; gen++ {
  29  		meta := db.QueryGeneration(gen)
  30  		if meta == nil {
  31  			break
  32  		}
  33  		fmt.Printf("  gen %d: parent=%q inst=%d\n", gen, meta.ParentHash, meta.InstanceID)
  34  	}
  35  
  36  	// Fitness trajectory.
  37  	fmt.Println("\n--- Fitness Trajectory ---")
  38  	traj := db.QueryFitnessTrajectory(20)
  39  	for _, p := range traj {
  40  		fmt.Printf("  gen %d: %d/%d (%.4f)\n", p.Gen, p.Score.Num, p.Score.Denom, p.Score.Float64())
  41  	}
  42  
  43  	// Fitness dimensions.
  44  	dims := []struct {
  45  		name string
  46  		dim  byte
  47  	}{
  48  		{"source", memory.DimSource},
  49  		{"binary", memory.DimBinary},
  50  		{"behav", memory.DimBehav},
  51  	}
  52  	for _, d := range dims {
  53  		pts := db.QueryFitnessDimension(d.dim, 20)
  54  		if len(pts) > 0 {
  55  			fmt.Printf("\n--- Fitness: %s ---\n", d.name)
  56  			for _, p := range pts {
  57  				fmt.Printf("  gen %d: %.4f\n", p.Gen, p.Score.Float64())
  58  			}
  59  		}
  60  	}
  61  
  62  	// Health history.
  63  	fmt.Println("\n--- Health ---")
  64  	health := db.QueryHealthHistory(20)
  65  	for _, h := range health {
  66  		fmt.Printf("  gen %d: %d/%d occupied (%.1f%%), avg-lockin=%.3f\n",
  67  			h.Gen, h.Occupied, h.Total,
  68  			float64(h.Occupied)/float64(h.Total)*100,
  69  			h.AvgLockIn.Float64())
  70  	}
  71  
  72  	// Type signature trends (top tags).
  73  	tags := []string{"func", "type", "ident", "literal", "assign", "if", "return", "for", "import", "field"}
  74  	fmt.Println("\n--- Type Trends ---")
  75  	for _, tag := range tags {
  76  		trend := db.QueryTypeTrend(tag, 20)
  77  		if len(trend) == 0 {
  78  			continue
  79  		}
  80  		fmt.Printf("  %s:", tag)
  81  		for _, p := range trend {
  82  			fmt.Printf(" gen%d=%d", p.Gen, p.Count)
  83  		}
  84  		fmt.Println()
  85  	}
  86  
  87  	// Bond history.
  88  	fmt.Println("\n--- Bond History ---")
  89  	for _, tag := range tags {
  90  		hist := db.QueryBondHistory(tag, 20)
  91  		if len(hist) == 0 {
  92  			continue
  93  		}
  94  		fmt.Printf("  %s:", tag)
  95  		for _, p := range hist {
  96  			fmt.Printf(" gen%d=%d", p.Gen, p.Count)
  97  		}
  98  		fmt.Println()
  99  	}
 100  
 101  	// Missing trends.
 102  	fmt.Println("\n--- Missing Sites ---")
 103  	for _, tag := range tags {
 104  		miss := db.QueryMissingTrend(tag, 20)
 105  		if len(miss) == 0 {
 106  			continue
 107  		}
 108  		fmt.Printf("  %s:", tag)
 109  		for _, p := range miss {
 110  			fmt.Printf(" gen%d=%d", p.Gen, p.Count)
 111  		}
 112  		fmt.Println()
 113  	}
 114  
 115  	// Hexagram operations (OpNone=0, OpAccrete=1, ..., OpRecycle=8).
 116  	opNames := map[byte]string{
 117  		0: "none", 1: "accrete", 2: "dissolve", 3: "nucleate",
 118  		4: "prune", 5: "strengthen", 6: "explore", 7: "collapse", 8: "recycle",
 119  	}
 120  	fmt.Println("\n--- Hexagram Ops ---")
 121  	for op := byte(0); op <= 8; op++ {
 122  		pts := db.QueryHexagramOps(op, 20)
 123  		if len(pts) == 0 {
 124  			continue
 125  		}
 126  		fmt.Printf("  %s:", opNames[op])
 127  		for _, p := range pts {
 128  			fmt.Printf(" gen%d=%d", p.Gen, p.Count)
 129  		}
 130  		fmt.Println()
 131  	}
 132  
 133  	// Digest: cross-referenced analysis.
 134  	fmt.Println("\n--- Digest ---")
 135  	dig := db.WalkDigest(tags, 10)
 136  	if dig == nil {
 137  		fmt.Println("  (insufficient data — need 2+ generations)")
 138  	} else {
 139  		fmt.Printf("  generations seen: %d\n", dig.GenerationsSeen)
 140  		fmt.Printf("  occupancy trend:  %s\n", dig.OccupancyTrend)
 141  		fmt.Printf("  fitness trend:    %s\n", dig.FitnessTrend)
 142  		fmt.Printf("  explore ratio:    %.1f%%\n", dig.ExploreRatio.Float64()*100)
 143  		fmt.Printf("  overextended:     %v\n", dig.OverExtended)
 144  
 145  		if len(dig.Types) > 0 {
 146  			fmt.Println("  per-type:")
 147  			for _, tag := range tags {
 148  				td, ok := dig.Types[tag]
 149  				if !ok {
 150  					continue
 151  				}
 152  				fmt.Printf("    %s: bond_rate=%.1f%% missing_delta=%+d\n",
 153  					td.Tag, td.BondRate.Float64()*100, td.MissingDelta)
 154  			}
 155  		}
 156  	}
 157  }
 158