mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-11 20:54:00 +01:00
The warden mires, the artillery stifles, the leech unknits. All three need contact, so a survivor that kites cleanly takes none of them — debuffs punish positional failure rather than taxing existence. isOn/factor are written as arithmetic rather than comparisons: Math.min(1, Math.ceil(t)) is 1 while a timer is live and 0 once it expires, so consumers multiply instead of branching. The whole status module therefore contributes zero branches, which is what makes the 100% gate affordable for a system this cross-cutting. Statuses are applied unconditionally too; a 0-duration spec is a provable no-op. applyStatus uses Math.max, so re-applying refreshes rather than stacks. That caps a horde's total lockdown at one duration by construction — a structural guarantee, not a tuned number. 123 tests, 100% coverage. Branches 117 -> 119: the draw halo gate and the snapshot chip filter. The status logic itself adds none. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VFyXexNjMQG9V7K8de17fc
39 lines
3.2 KiB
JSON
39 lines
3.2 KiB
JSON
{
|
|
"intent": "Give the survivor three status debuffs - slow, suppress (fire rate) and bleed (regen block) - so the new ranged and fast units have a lever beyond raw damage.",
|
|
"scope": [
|
|
"reverse_survivors/src/core/status.ts (new leaf module) and status.test.ts",
|
|
"reverse_survivors/src/core/types.ts (StatusKind, STATUS_POWER/LABELS, per-spec debuff fields, Survivor.statuses, Projectile payload)",
|
|
"reverse_survivors/src/core/sim.ts (tick and consume), snapshot.ts (chips), src/ui/Hud.tsx, src/render/draw.ts (halo), src/styles.css",
|
|
"Non-goal: director powers and difficulty tiers ship as their own commits"
|
|
],
|
|
"changes": [
|
|
"isOn/factor are arithmetic (Math.min(1, Math.ceil(t))) rather than comparisons, so the whole status system contributes ZERO branches; consumers multiply by the result instead of branching on it.",
|
|
"applyStatus uses Math.max, making refresh-not-stack a structural guarantee: a horde can never chain-lock the survivor past one status duration, regardless of how many enemies land hits.",
|
|
"Statuses are applied unconditionally at contact and projectile-hit sites; a 0-duration spec makes the call a provable no-op, which is cheaper than a guard branch under the 100% gate.",
|
|
"Projectiles carry their own debuff payload so a hit needs no lookup of a possibly-dead firer.",
|
|
"Statuses tick at the top of survivorStep, before they are read, so a status applied on tick N is felt from N+1 and an inert application is never observable.",
|
|
"Suppression scales the reload rather than the countdown, keeping the remaining timer linear in dt so replays and assertions stay exact.",
|
|
"The draw.ts halo is gated so an unafflicted survivor renders exactly as before, keeping the existing BASE draw-call counts valid."
|
|
],
|
|
"verification": [
|
|
{
|
|
"command": "npm run check (typecheck + eslint --max-warnings 0 + vitest --coverage)",
|
|
"result": "pass",
|
|
"evidence": "123 tests passed. Coverage 100% on all four metrics: statements 446/446, branches 119/119, functions 84/84, lines 429/429. Branch count rose 117 -> 119, accounted for by the halo gate and the snapshot chip filter; the status module itself adds none."
|
|
},
|
|
{
|
|
"command": "targeted assertions in sim.test.ts",
|
|
"result": "pass",
|
|
"evidence": "Warden contact slows movement by exactly STATUS_POWER.slow against an unslowed control run; artillery shells lengthen the next reload to 0.55 * 1.75; a leech contact blocks regen and it resumes on expiry; two simultaneous warden contacts do not exceed the 2.0s cap; a plain rusher leaves all three timers at 0."
|
|
}
|
|
],
|
|
"risks": [
|
|
"Bleed is a no-op unless the survivor has bought the regen upgrade, since it starts at regen 0. This is intended - the Leech counters a specific build - and matches the README description.",
|
|
"All three debuffs require contact, so a survivor that kites cleanly takes none of them. This is deliberate: debuffs punish positional failure rather than taxing existence."
|
|
],
|
|
"rollback": [
|
|
"git revert the commit; src/core/status.ts and status.test.ts are new files and disappear with it.",
|
|
"After rollback run `npm run check` in reverse_survivors/ and confirm the suite passes at 100% coverage."
|
|
]
|
|
}
|