appetite.go raw

   1  // Package forage implements autonomous internet feeding — the organism
   2  // identifies gaps, constructs URLs, fetches content, and digests it
   3  // through enzyme pipelines. The internet is supersaturated solution.
   4  // The lattice is the filter.
   5  package forage
   6  
   7  import (
   8  	"fmt"
   9  	"sort"
  10  
  11  	"git.mleku.dev/mleku/dendrite/pkg/gap"
  12  	"git.mleku.dev/mleku/dendrite/pkg/ratio"
  13  )
  14  
  15  // Need represents a single information need derived from the organism's
  16  // negative space. Each need has a type that determines how the organism
  17  // searches for it.
  18  type Need struct {
  19  	Type     NeedType    // what kind of information
  20  	Topic    string      // the specific subject (NIP number, package name, etc.)
  21  	Gap      gap.Gap
  22  	Priority ratio.Ratio // 0 = low, 1 = critical
  23  }
  24  
  25  // NeedType classifies what the organism needs to learn.
  26  type NeedType int
  27  
  28  const (
  29  	NeedSpecification NeedType = iota // protocol spec (NIP, RFC)
  30  	NeedSourceCode                    // library source
  31  	NeedDocumentation                 // package docs
  32  	NeedExample                       // usage examples
  33  	NeedExplanation                   // conceptual description
  34  )
  35  
  36  func (t NeedType) String() string {
  37  	switch t {
  38  	case NeedSpecification:
  39  		return "specification"
  40  	case NeedSourceCode:
  41  		return "source"
  42  	case NeedDocumentation:
  43  		return "documentation"
  44  	case NeedExample:
  45  		return "example"
  46  	case NeedExplanation:
  47  		return "explanation"
  48  	default:
  49  		return "unknown"
  50  	}
  51  }
  52  
  53  // Appetite analyzes gaps and produces a ranked list of information needs.
  54  // The organism's negative space shapes what it hunts for.
  55  func Appetite(gaps []gap.Gap) []Need {
  56  	var needs []Need
  57  
  58  	for _, gap := range gaps {
  59  		switch gap.Type {
  60  		case "missing_site":
  61  			needs = append(needs, Need{
  62  				Type:     NeedDocumentation,
  63  				Topic:    gap.Tag,
  64  				Gap:      gap,
  65  				Priority: gap.Severity,
  66  			})
  67  
  68  		case "orphan_event", "orphan_pubkey":
  69  			needs = append(needs, Need{
  70  				Type:     NeedSpecification,
  71  				Topic:    fmt.Sprintf("Nostr event references and %s resolution", gap.Tag),
  72  				Gap:      gap,
  73  				Priority: gap.Severity,
  74  			})
  75  
  76  		case "low_occupancy":
  77  			needs = append(needs, Need{
  78  				Type:     NeedExample,
  79  				Topic:    "lattice growth patterns and element diversity",
  80  				Gap:      gap,
  81  				Priority: gap.Severity,
  82  			})
  83  
  84  		case "weak_region":
  85  			needs = append(needs, Need{
  86  				Type:     NeedExplanation,
  87  				Topic:    "constraint design for stronger bonding",
  88  				Gap:      gap,
  89  				Priority: gap.Severity,
  90  			})
  91  
  92  		default:
  93  			needs = append(needs, Need{
  94  				Type:     NeedExplanation,
  95  				Topic:    gap.Description,
  96  				Gap:      gap,
  97  				Priority: gap.Severity,
  98  			})
  99  		}
 100  	}
 101  
 102  	sort.Slice(needs, func(i, j int) bool {
 103  		return needs[j].Priority.Less(needs[i].Priority)
 104  	})
 105  
 106  	return needs
 107  }
 108