On high level, I understand that all wallet addresses private/public keys are define from single private key,
No, they are not. Each address has exactly one corresponding public key, and each public key has exactly one private key. The seed is used to derive the private keys.
What I do not get, how the wallet app that I would use for potential recovery process "knows" how many addresses I actually generated/used and have unspent outputs (meaning BTC).
As Ledger generates new derived address for each tx and presumably new address for each tx change, there can be arbitrary number of addresses that had been used - and this is uknown to the recovery seed / wallet.
It doesn't know, it just guesses. Private keys and their addresses are derived in the same order and thus are given out and used in the same order. So when you restore a seed, the wallet will scan the blockchain for transactions and generate some number of addresses ahead of the last address known to have a transaction currently in the scan. This number of addresses is called the gap limit, and is typically 20. Every time a transaction is found corresponding to an address in the gap limit, it will refill the gap limit by generating more addresses.
How does then the recovery wallet app rebuilds from seed the wallet with all relevant addresses?
Read BIPs
39 and
32. BIP 39 specifies how the mnemonic is generated and then interpreted as a seed value. BIP 32 specifies how that seed value is used to generate the master private key and then how all other private keys are derived from that master private key.