As you say, comments should express what is no longer apparent from the code (the reason that the code was as it is, the approaches that were tried and discovered, had flaws that led to the code being the way he is now, etc.)
But in a more general sense, think that the code is logically grouped into related pieces. Namespaces, classes, methods, blocks, strings. These fragments form a hierarchical overview of the application. Therefore, by commenting on the blocks and giving a general overview of what they are doing, you can summarize the code quickly and simply so that someone else can find a bit that suits them, understand, and then use or modify it effectively and with minimal risk failure.
So, explaining that File.Open opens a file is useless.
But explaining that a block of 10 lines of code will find, open, read and save the settings for your application, you will save a reader who must really read and decode the full text. In a few words, they can understand the whole purpose of the code and know if they need something they need to deepen. Or, if they want to call the code, they will understand what it does and how to use it - again, without having to delve into the finer details of how it reaches its behavior.
Thus, the commentary should begin with any important piece of code (at any / all levels described above), where the summary will save the reader who needs to read the code in order to clearly understand what it is doing. And anywhere you need to comment on code to explain how and why it does what it does.
Remember that your comment describes the code to someone who has not seen this before. Or yourself, when you review it after 6 months. A few well-chosen words can save hours of work trying to decipher a complete understanding of some code.