Interesting problem. I think I have a working solution you can try. You might need to augment slightly if you have additional separators not shown in your sample data or probably more complex examples but it should give you something you can build on.
First split the code
into separate rows on the delimiter (/ or &) by converting to a json array (this provides a sequence for ordering).
Then replace the code
with its new value and re-aggregate, adding back the separator for all but the last row.
with n as (
select ID, Value, seq, Replace(Value,CodeType,Concat('(',CodeExt,')')) NewValue,
case when seq < Max(seq) over(partition by ID) then
case when Code like '%&%' then '&' when Code like '%/%' then '/' else '' end
end sep
from t
cross apply (
select Value, [Key] seq
from OpenJson(Concat('["',Replace(Translate(code,'&/', ',,'),',','","'),'"]'))
)s
)
select ID, String_Agg(Concat(NewValue, sep),'') within group(order by seq) Code_New
from n
where Value != NewValue
group by ID;
Result:

See Working Fiddle Demo