Gate was process.env.NODE_ENV === 'development' — unsafe default. react-scripts inlines NODE_ENV=development when unset, so prod deploys forgetting the env var exposed the delete-all button. Switched to explicit opt-in REACT_APP_DEV_TOOLS=1. process.env.REACT_APP_DEV_TOOLS as static literal gets inlined by DefinePlugin at webpack build time — runtime mutations in tests had no effect, and dev-start without the env produced bundles with the branch dead-stripped. Extracted gate to src/config/devTools.js using dynamic key access (process.env['REACT_APP_' + 'DEV_TOOLS']) so DefinePlugin cannot inline it; the value is read at runtime. dev-start.sh now exports REACT_APP_DEV_TOOLS=1. Button had also drifted outside the campaigns collapse block to the page bottom; moved it back inside the campaigns section after the grid. Tests cover both paths: gate logic (unset/0/arbitrary/1) in BulkDelete.gate.test.js, prod safety render (button absent when unset) in BulkDelete.render-hidden.test.js, dev feature render (button present when DEV_TOOLS=1) in BulkDelete.render-shown.test.js.
scripts/
Dev orchestration + manual demo tool. NOT test.
dev-start.sh / dev-stop.sh
Local dev stack: backend (:4001, sqlite) + frontend (:3999, server mode).
One command. Writes env vars for you. Logs to tmp/server.log, tmp/fe.log.
./scripts/dev-start.sh # start (idempotent: leaves running ports as-is)
./scripts/dev-stop.sh # stop both
replay-combat.js
Live backend demo. Drives full combat via server adapter (same contract as App). Player display live-updates. Watch UI react to state changes.
# start backend + frontend first (see docs/DEVELOPMENT.md)
node scripts/replay-combat.js [rounds] [delayMs]
# defaults: 100 rounds, 200ms/step
Coverage per round: damage, heal, all 22 conditions, toggleActive, removeParticipant, addParticipant (reinforcements), updateParticipant, pause/resume, reorderParticipants, endEncounter. Revives dead each round to sustain full round count.
See also
tests/audit/— exploratory bug-finders (manual run, non-deterministic){shared,server,src}/tests/— jest unit/integration/characterizationscratch/— gitignored throwaway