testsAndMisc/docs/superpowers/contracts/reverse-survivors-difficulty-tiers-2026-08-09.json
Krzysztof kuhy Rudnicki 5d0caa9725
Some checks failed
Pre-commit checks / pre-commit (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
reverse-survivors CI / check (push) Has been cancelled
reverse_survivors: difficulty tiers
Haunting, Normal and Crusade scale enemy hp and speed, the survivor's
health, your income, and the length of the night. Normal is exactly 1.0 on
every multiplier — it is the identity tier, which is what lets every
existing raw-value assertion keep passing untouched.

Enemy speed now derives from a single helper, so difficulty and frenzy
compose in one place rather than fighting at three call sites.

Also fixes a bug this surfaced: handleRestart ignored the selected tier, so
restarting after choosing Crusade silently reverted to Normal. The
react-hooks purity rule flagged Date.now() in the new handler, and
extracting restartSeed() exposed the omission.

Endless mode is deliberately left out — fmtTime(Infinity) renders
Infinity:NaN, which would cost a guard plus tests for a mode whose only
content is the same game but longer.

README rewritten for all four features, including the reversal of its old
placement promise.

160 tests, 100% coverage.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VFyXexNjMQG9V7K8de17fc
2026-08-09 23:17:07 +02:00

16 lines
1.3 KiB
JSON

{
"title": "Reverse Survivors: difficulty tiers",
"objective": "Add three difficulty tiers - Haunting, Normal and Crusade - scaling enemy hp and speed, the survivor's health, director income, and the length of the night. Normal must be the exact identity tier so no existing behaviour or assertion changes.",
"acceptance_criteria": [
"`npm run check` passes standalone: tsc --noEmit clean, eslint --max-warnings 0 clean, vitest at 100% on all four metrics.",
"Normal is exactly 1.0 on every multiplier, so all pre-existing raw-value assertions hold unchanged.",
"An explicit duration argument still overrides the tier's duration.",
"Changing difficulty restarts the game on the new tier, and restarting preserves the selected tier."
],
"out_of_scope": [
"Endless mode: fmtTime(Infinity) renders Infinity:NaN and would need a guard plus tests for a mode whose only content is the same game but longer.",
"localStorage persistence of the chosen tier: its catch arm is only reachable by stubbing a throwing setItem, which tests the mock rather than the game."
],
"verifier": "npm run check (typecheck + eslint --max-warnings 0 + vitest --coverage at 100%), plus an App-level test asserting the clock changes from 5:00 to 6:00 when Crusade is selected"
}