In Software Engineering there are Problem-Solving tasks and there are Optimization tasks.
The implementation of Functional Requirements (specifications) is a Problem-Solving task. This can be effectively done by Gen-AI. The LLMs are able to translate from a specification (in English) to executable code (in some Programming Language).
The fine-tuning of Non-Functional Requirements (both static and dynamic) is an Optimization task. There are interdependencies among these non-functional requirements, so that decisions must be made about the trade-offs. They also demand experimentation, in particular the dynamic aspects, that should be measured at run-time. Therefore this cannot be effectively done by Gen-AI.
For example: the trade-off between Latency and Throughput, or between Memory Consumption and CPU time. Very often when we decrease the Latency this has a negative impact in the Throughput because we may have less threads running in parallel. Or when we choose a Data Structure that is faster, it also increases the Memory Consumption. A Human Being should be involved in these decisions, because they are Trade-Offs and we only understand them after performing Experiments at Run-Time. The Fine-Tuning of the Non-Functional Requirements is a Multi-Objective Optimization Problem. It cannot be delegated to Gen-AI.
Another example is the Optimization of Machine Learning models. The models have Offline Metrics (such as Precision and Recall in the case of Classification models) and Online Metrics (such as CTR and Bounce Rate in the domain of Programmatic Advertising). The optimization of these models cannot be delegated to Gen-AI. It often requires lots of experimentation, including for example new techniques of Feature Engineering (such as encodings), Algorithm Selection (such as Decision Trees vs Neural Networks) and Hyper-Parameter Optimization for each algorithm. A good Data Scientist with Domain Knowledge cannot be replaced by Gen-AI agents.