As a practical note, I find that it’s useful to, in addition to what you mention about telling the LLM to avoid certain patterns, additionally tell it to go over its changes and rewrite e.g. code which returns a placeholder value in a failure case with code which throws a descriptive error in a failure case. Seems like there are many cases where the LLM isn’t able to one-shot follow all of the instructions you give it, but is able to recognize that failure and course-correct after the fact.
Seconding this observation.
As a practical note, I find that it’s useful to, in addition to what you mention about telling the LLM to avoid certain patterns, additionally tell it to go over its changes and rewrite e.g. code which returns a placeholder value in a failure case with code which throws a descriptive error in a failure case. Seems like there are many cases where the LLM isn’t able to one-shot follow all of the instructions you give it, but is able to recognize that failure and course-correct after the fact.