It does not make it acceptable, quite the opposite as there would actually be less time pressure to ship code. What you describe would lead to an accumulation of issues over time that will degrade the codebase until it ships and then makes maintenance a nightmare.
A code base that will ship in 2 years will be shipping for various non-production reasons until then. There will be stakeholder demonstrations and alpha releases and things where the code must be functional (runnable), but it may not be production ready in terms of completeness, security etc.
The "accumulation of issues" is there regardless. Leaving TODO's isn't cutting corners or accumulating technical debt. It's simply something that is still to do. Any project will have an issue management system with outstanding issues, but a note in the code is worth more than a thousand words in an issue. "TODO: here is where the validation of parameters must be done, see issue #123". or "TODO: enable right-to-left in these two textboxes when right-to-left text input is added, see issue #234".
There is no value in keeping a main branch "clean" from TODO comments because it's somehow more hygienic. The code needs to be runnable at all times, even with incomplete features. Reaching zero TODO's before a product ships is a matter of grepping for the strings.
The situation you have described, with there being versions of the code that must not go live, is precisely what branches are for, and branching is cheap. Whether you should consider the particular branch named 'master' to be special in any way, is largely a matter of preference, though if you end up with a mature product, it is quite possible that you will want to be able to cut a release from more than one branch.
Absolutely you can either designate an unstable “develop” branch and do stakeholder demos from there while keeping master clean, or you can develop on master and ship from stabilization branches. You can have any number of branches and assign any level of quality and polices to each. But you can’t avoid TODOs entirely by keeping them only on feature branches as what you’ll need is a branch with all features integrated but not necessarily shippable.
If you do stakeholder demonstration from an integrated “develop” branch and ship from master, you can have a policy of “no TODOs in master” meaning you won’t ship the TODOs. I’m not saying one must have TODOs ever in the branch-that-will-be-released but that they can be very useful and almost unavoidable to have in some integrated branch, because you may need to show a product without it necessarily being ready. Exactly what quality gates you ship with is a preference, for example specific comment tags (PERF, FIXME, TODO, ...). These are just words. In my codebase TODO means "this works but isn't optimal, so should be revisited IF the code ever has a reason for change". In other codebases it might mean "This is utterly broken and can't be shipped". Whether shipping is acceptable of course depends on which of those interpretations one uses (And using both would be a process error).
You seem to have somewhat diverged from my point, which was a reply to this statement:
> “this is a thing which is okay during development but absolutely must be changed/fixed before shipping this product”.
There is no valid reason to submit effectively defective code to the main branch. There is a major difference between incomplete functionality, which obviously is what the codebase contains during development, and defective or sub-standard implementation.
As an example (and from one of your examples), leaving validation of inputs "for later" is a sure way of shipping code that does not validate inputs and, again, there is no reason not to properly implement this from the get-go.
This sort of issues only accumulate if you let them by cutting corners.
Real-life example: I saw things like "TODO: Check for null pointers" in code. This should be rejected outright during code review. If you should check for null pointers, then do check for null pointers.
Validation may not be possible (Because it requires an external service for example, or validation rules may not even be decided. For example. I suspect that many MVP demos have a login/signup, which might validate the email. I also suspect that e.g. minimum password rules are enforced, it's usually done much later).
But yes I agree it's a poor example if it's possible to do right away it must be done right away. But I think you get my point. RTL-input may be the better example: it's a nice-to-have for some people, probably not part of an MVP but still a likely part of what some stakeholder calls critical functionality if you support RTL input locales.
My point is that while you may be able to categorize some things as "critical" or "important" (i.e. things one can argue should not reach the mainline even during development) there will always be a gray areas where you can't complete the development, but should still have a functioning app in some sense.