If you don't need too many levels of poison, the previously posted answer is the best way to approach this. However, should you need upwards of 10 or so levels of poison, you could do something dynamic.
You'll need a second scoreboard objective for tracking the player's actual poison amplifier, which I've called poison_real
In a repeating chain, here's what you could do:
execute as @a store result score @s poison_real run data get entity @s ActiveEffects[{Id:19b}].Amplifier
effect give @a[scores={poison_level=1}] minecraft:poison 999999 0
(only applies when setting someone's score from 0 to 1)
scoreboard players remove @a poison_level 1
execute as @a at @s unless entity @e[type=minecraft:area_effect_cloud,name="poison_cloud",distance=..0.1] unless score @s poison_level = @s poison_real run effect clear @s minecraft:poison
execute as @a[scores={poison_level=0..}] at @s unless score @s poison_level = @s poison_real run summon minecraft:area_effect_cloud ~ ~ ~ {Radius:0.1f,CustomName:'"poison_cloud"',Duration:7b,Effects:[{Id:19b,Amplifier:0,Duration:999999}]}
execute as @e[type=minecraft:area_effect_cloud,name="poison_cloud"] at @s store result entity @s Effects[{Id:19b}].Amplifier int 1 run scoreboard players get @p poison_level
scoreboard players add @a poison_level 1
This chain detects a change in the poison_level
score, and if there is a change, it summons an area effect cloud with an Amplifier of the player's poison_level
.