The way I work, is that the entire project is in "Ship" quality, the entire time of development; just not yet complete. Incomplete functionality means a blank screen or a button that doesn't do anything. It
never means that something crashes.
My goal is zero crashes, ever; at any time during development. The same with memory leaks or severely anomalous behavior.
It's an old-fashioned way of working that results in basically zero tech debt.
I'm allergic to debt, of any kind.
The nice thing about working this way, is you get incredibly well-formed UX, and you don't have that awful "QA surprise," at the end of the project.
It also goes a lot faster than you might think, as bugs get fixed close to the time of their creation.