I just tried it and it works for me. That is, I built in a permaMod that affects OP this way with code on a button press, and the OP changes are reflected immediately upon opening the refit screen.
One other key point - and this applies to any other ship variant manipulation with code - is if you're going to change a variant, and its .getSource() != VariantSource.REFIT, you need to clone the variant and set the fleet member's variant to the cloned version of it. You can search FleetEncounterContext for .clone() to see an example of code doing that.
i'm using a BuffManager to apply the hullmod (which is probably now a less-than-efficient way of doing it)
the code that applies the variant is like so
if(shipVariant.isStockVariant()) {
shipVariant = shipVariant.clone();
shipVariant.setSource(VariantSource.REFIT);
member.setVariant(shipVariant, false, false);
}
inside of a BuffManager that is applied to a FleetMember in dialog. after this, the BuffManager applies the hullmod, and finally FleetMemberAPI.updateStats is called
i'll add a check for the source to apply the cloned variant if the source isn't refit, but otherwise i think i'm doing the same thing as you. the only thing i could think of is you may be using a dev version where this single oddity is already fixed.
edit:
here's my investigation after adding the check.
this picture shows off the dialog-applied hullmod
https://i.imgur.com/66V6kWu.pngthis picture shows off the ship's OP after applying the hullmod, with the ballistic weapons in frame.
https://i.imgur.com/IJlQEOt.pngthis picture shows off the fleet refit screen, where it shows the free OP that the ship should have.
https://i.imgur.com/gnc0FdM.pngadditionally, and this is a bug i hadn't noticed before, when closing and reopening the refit dialog for that specific ship, the free OP disappears as well, and it appears i was mistaken about the OP appearing if you install something on the ship. it only appears if you switch what ship you are looking at.
looking at the logs, it appears the WeaponOPCostListener is called very often, much more often than applyEffectsBeforeShipCreation is, which is called twice because of the affectsOpCosts method returning true in the hullmod