package config import ( "crypto/sha256" "fmt" "os" "strconv" "strings" ) // SpreadStrainFromJoinLane returns a stable #RRGGBB hex color for UI strain grouping. // Not a signed key — informational telemetry only. func SpreadStrainFromJoinLane(lane string) string { lane = strings.TrimSpace(strings.ToLower(lane)) if lane == "" { return "" } sum := sha256.Sum256([]byte("aetherforge-strain:" + lane)) return fmt.Sprintf("#%02x%02x%02x", sum[0], sum[1], sum[2]) } // GenealogyReport returns forge-baked spread watermark fields for auth/stats telemetry. // Env overrides (AETHER_PARENT_AGENT_ID, AETHER_SPREAD_GENERATION) support spread-child // launches without re-forge. Never used for authentication. func (c RuntimeConfig) GenealogyReport(runtimeJoinLane string) (parentAgentID string, spreadGeneration int, spreadStrain string) { parentAgentID = strings.TrimSpace(c.ParentAgentID) if v := strings.TrimSpace(os.Getenv("AETHER_PARENT_AGENT_ID")); v != "" { parentAgentID = v } spreadGeneration = c.SpreadGeneration if v := strings.TrimSpace(os.Getenv("AETHER_SPREAD_GENERATION")); v != "" { if n, err := strconv.Atoi(v); err == nil && n >= 0 { spreadGeneration = n } } spreadStrain = strings.TrimSpace(c.SpreadStrain) if spreadStrain == "" { lane := strings.TrimSpace(runtimeJoinLane) if lane == "" { lane = strings.TrimSpace(c.BakedJoinLane) } spreadStrain = SpreadStrainFromJoinLane(lane) } return parentAgentID, spreadGeneration, spreadStrain }