Every human have a threshold, the guy is a novice. I think the session to review the code must be fair and related to his level, underline the bad and good parts. In some bad cases, it is possible to guide him by asking questions like: how your code will react is this event happen or how flexible is your code if the client ask you to add this feature?
I would take note of the advance topics that were not mastered and I would introduce them gradually trough lunch and learn, pairing, later code review, session training, books, tutorials, etc.
If you are hard on him or criticize everything, probably the guy will start to ignore your feedback after a couple of months of code review and may end to hate his job if he feel depreciated.
Secondly, I would write down a list of what need to be addressed, I will prioritize that list then plan what the review can cover by the available time without exhausting the reviewer and the reviewed. A programmer repeats his errors when they do not understand a topic. So I would not feel the need to review everything in detail because he will probably repeat the same mistakes and you will have another chance to pick them up in the next code review. This will spread your recommendations trough multiple reviews and it will lightening the process. Also, there is probably uncovered topics that the guy will pick up by himself in the following months.
Finally, on the side, I would track the technical debt in the company planning tools.
Working solo with a client as a novice is usually a stressful task. The code works, that means he understood the requirement, the business domain and able to demonstrate leadership.