Aaaaand it
was something obvious. As usual as soon as I post on a forum and go to bed, my brain digs out the embarrassingly simple solution overnight. It's all working, it's just that the client-side weapon animations weren't active - cl_lw was set to 0 for some reason. All good now.
What is a weapon prediction actually?
To answer your question simply (it's a big topic and I'm no expert) - prediction is where rather than having a client send a request to the server to do something (e.g. fire a weapon) and wait for the result to come back, it just does it based on the game info it has. So it instantly plays the firing animation and sound (as well as other things like bullet impacts or blood if you hit a player), and lets the server know it has done it. This means there's no perceived lag for the player on the client, but the server (which gets the update say 50ms later) has to look back to see if the shot really hit based on where the other players were at the time the client fired it. This can result in strange behaviours if the server/client disagree, but the gain in responsiveness is well worth it. There's an article on it here:
Latency Compensation Methods