Several projects I have worked on have satisfied all the requirements, yet for some reason lingered on. Typically what happens is that the client is spending time with their new product and is asking the vendor (consultant) to modify such-n-such "just a little". Or perhaps they realize that although requirement such-n-such is satisfied, it isn't what they intended. To create a happy customer, the vendor/consultant usually complies, and the project doesn't end.
Working in sprints (2-4 weeks) has certainly mitigated the problem, as the customer sees the product sooner and able to give course-corrections (feedback).
Here are some other ideas I've had:
Just say no. Maybe the client will respect me more for this, maybe they will feel abandoned.
Make sure each requirement is testable and has tests. When each test passes, the requirements are satisfied. This still doesn't account for requirements that the client insists the vendor/consultant misinterpreted. Also things like usability are subjected to the client's interpretation.
Have a big ceremony, the more elaborate the ceremony the more obvious it is that the project is over. This is more of a psychological activity to change the client's mindset into a "project is over" mentality.
Capture client changes and imply that you'd be delighted with the opportunity to work on the next phase, with proper funding of course.
Near the end, create a burdensome change request process meant to discourage changes. This seems counter to agile as well as good customer service.
What are some best practices you know of that ensure a distinct end to a software project?
This question is probably more relevant in the client-consultant context than an in-house developer situation. I feel it's absolutely vital in fixed bid projects.