As to your original question, what's "acceptable" is impossible for us to answer. You yourself must decide how much reworking you can do while still moving ahead at the required pace of new development. Such has been the goal of project managers for decades.
No matter what system of development you're using (waterfall, UML, Rational Rose, Agile), two things are absolutely required:
- The client must have communicated to you exactly what the code should do in the general case when performing some task. This isn't as impossible as it sounds; usually the "general case" breaks down to a "nominal case", an "exceptional case", and an "error case". The situations for these should be described and the expected behavior of the system in these situations defined.
- Given requirements at a level of specificity that covers all expected scenarios, the code must adhere to the requirements. For the nominal, exceptional and error cases, the system should perform as defined before it is released to the customer.
Given these two things have happened for each task the system is capable of performing in all known situations, you have done all that is humanly possible to ensure a quality product. However, there will still be "defects"; the code cannot be guaranteed to perform as expected outside of the known scenarios, which may have inadvertently excluded some possible scenarios. That's not your fault as a developer; either you as an analyst did not think to ask what should happen in some particular case (probably because it seemed to fall into some defined situation), or the client did not properly define the requirements such that all possible cases were covered. Happens all the time. What happens as a result from a business perspective depends on the design methodology and business pattern, but you as a developer will probably eventually extend the code to cover the missed situations, and then you will verify that the system still works in all other situations.
This is where TDD really shines; if you accept that regression of functionality due to the introduction of defects in future work is possible, then it naturally follows that having a test that is always available to prove that the code will meet the requirements (and thus that you wrote what you thought you wrote) is an invaluable means to avoid said regression.