steer.go raw

   1  package oracle
   2  
   3  import (
   4  	"path/filepath"
   5  	"strings"
   6  )
   7  
   8  // WalkWeights converts oracle directives into file weight modifiers for
   9  // walk.BuildWeighted. Files whose paths match the oracle's focus keywords
  10  // get higher weights, causing them to appear earlier in the walk order.
  11  //
  12  // The returned map is keyed by relative file path and valued by weight
  13  // multiplier (default = 1.0, boosted = 2.0-4.0).
  14  func WalkWeights(r *Reading, files []string) map[string]float64 {
  15  	if r == nil || len(files) == 0 {
  16  		return nil
  17  	}
  18  
  19  	weights := make(map[string]float64, len(files))
  20  
  21  	// Collect all keywords from the domain and changing line focuses.
  22  	domain := TrigramToDomain(r.OuterTrigram())
  23  	keywords := DomainKeywords(domain)
  24  
  25  	// Build a set of focus terms from directives.
  26  	var focusTerms []string
  27  	for _, kw := range keywords {
  28  		focusTerms = append(focusTerms, strings.ToLower(kw))
  29  	}
  30  
  31  	// Add changing line dimension focuses.
  32  	for _, lineIdx := range r.ChangingLines() {
  33  		bit := lineIdx % 3
  34  		isInner := lineIdx < 3
  35  		focus := ChangingBitFocus(bit, isInner)
  36  		for word := range strings.FieldsSeq(strings.ToLower(focus)) {
  37  			if len(word) > 3 { // skip short words
  38  				focusTerms = append(focusTerms, word)
  39  			}
  40  		}
  41  	}
  42  
  43  	// Score each file by keyword matches in its path.
  44  	for _, f := range files {
  45  		lowerPath := strings.ToLower(f)
  46  		base := strings.ToLower(filepath.Base(f))
  47  		w := 1.0
  48  
  49  		for _, term := range focusTerms {
  50  			if strings.Contains(lowerPath, term) || strings.Contains(base, term) {
  51  				w += 1.0
  52  			}
  53  		}
  54  
  55  		// Style modulation: targeted and reference styles boost test files;
  56  		// broad style boosts non-test files.
  57  		style := ADSRToStyle(0)
  58  		if len(r.Directives) > 0 {
  59  			style = r.Directives[0].Style
  60  		}
  61  		isTest := strings.HasSuffix(base, "_test.go") || strings.Contains(base, "test")
  62  		switch style {
  63  		case StyleTargeted, StyleReference:
  64  			if isTest {
  65  				w += 0.5
  66  			}
  67  		case StyleBroad:
  68  			if !isTest {
  69  				w += 0.5
  70  			}
  71  		case StyleSynthesis:
  72  			// Synthesis boosts files that connect packages (main, cmd, etc.).
  73  			if strings.Contains(lowerPath, "cmd/") || base == "main.go" {
  74  				w += 1.0
  75  			}
  76  		}
  77  
  78  		if w > 1.0 {
  79  			weights[f] = w
  80  		}
  81  	}
  82  
  83  	return weights
  84  }
  85  
  86  // DominantADSRPhase returns the ADSR phase with the highest count.
  87  // Used to determine the organism's current lifecycle position for oracle casting.
  88  func DominantADSRPhase(counts [4]uint32) uint8 {
  89  	maxIdx := uint8(0)
  90  	maxVal := counts[0]
  91  	for i := uint8(1); i < 4; i++ {
  92  		if counts[i] > maxVal {
  93  			maxVal = counts[i]
  94  			maxIdx = i
  95  		}
  96  	}
  97  	return maxIdx
  98  }
  99