通行証 · HALL PASS DOCS · PLAY

Punchlist — ideas and known issues not being worked on now

Add to this rather than starting the work. Each entry says enough that a fresh agent could pick it up cold. Move it out when it ships.


Deferred — Rive UI experiment (Chris, 2026-09-14)


Next development punch list — Chris, 2026-09-12

Keep the original idea numbers below so conversation references remain stable. The agreed work order is full-school chaining → #4 → #7 → #9 → #1. Chris moved behavioral elites ahead of the map after the full-crew domain pass. The remaining ideas are saved for later, not approved for simultaneous implementation.

Selected sequence

Saved ideas


IDEA — Recovery valve (promoted by the playtest lab, 2026-08-30)

READ THIS FIRST — amended 2026-08-31 at the iteration-49 synthesis. The SHAPE of this entry survives; its NUMBERS do not, and one of its arguments is now known to be wrong.

  1. Every figure below predates ONE NIGHT (b78caf6, the ten-room night) and was measured on maps that no longer exist. Re-measure before quoting.
  2. The premise was overstated. This entry rests on I-007 — "near-misses never fire; threat is binary, comfortable or dead". A 5,312-run audit (I-041) found the detector is sound but the threshold is wrong: it watches a 15% HP line that only 17% of winning runs ever cross. The game already has a common, survivable wounded band at 25–50% HP — half of all wins bottom out at 36% HP, and 89% dip below 70%. So "the game has no recoverable danger" is false; what is true is the narrower claim that crossing 15% is near-lethal.
  3. That reframes what the valve is for. Its trigger (HP < 35%) fires on roughly half of all winning runs — so it is not a rare-emergency rescue, it is a heal that most winners collect. That is very likely why every ungated arm breached the competent ceiling.
  4. The cheaper alternative now on the table: the wounded band already exists and nothing tells the player they are in it. Dramatising a dip to 35% costs no balance risk at all, where adding a mechanic to manufacture dips costs a lot. See board #15.

The valve still ranks in the lab's top 3 (it is validated twice and rare in being containable — engagement up without win rates moving), but ship it for felt danger, not because the game lacks danger.

The lab's most-validated mechanic gap. Two numbers carry the whole argument, measured across two seed banks at simSha 2f56ccd (manifests: skill-calibration-final, 2bank-fresh-final, death-autopsy-final-midterm in the archive repo):

The missing ingredient is RECOVERY from danger, not danger itself. Shapes worth considering (the lab measures, Chris chooses): heal drops that only spawn below an HP threshold, a post-hit mercy window, a lifesteal-flavored upgrade or evolution. The front-loaded Cursed Reserve schedule (I-010) suggests the effect is reachable — with bigger rank-1 HP, 4 of 6 novice wins on bank b were clutch dawn saves, the first ever minted.

The nearly-free companion (view-only, no sim change): the death screen names the killer beat. 63% of FINAL and 86% of MIDTERM deaths happen with a special-grade on the field or within 25s of a surge banner — "SPIT TAKE took you at 4:25" costs a string lookup and converts the anonymous mid-night wall (feedback board #6) into a narratable death.

Do not build the valve without Chris — which resource recovers, and when, is a feel decision. The death-screen naming is mechanical enough for any session to pick up.

Update 2026-08-30, iteration 15: the game already contains an existence proof. Yui is the only character who ever wins novice FINAL on a fresh save (8/16 at skill 0.25, near-miss mean 0.56, 4 clutch wins — I-012), and her SHIRASAGI elective pushes that to 13/16 with 7 clutch wins (I-014). Whatever her kit + CE economy is doing IS the recovery valve, shipped and tuned — worth studying before inventing a new mechanic. Validated on both seed banks at iteration 16 (pooled n=32): bare yui is the only character above 2/32 novice wins (12/32), and SHIRASAGI lifts her to 22/32 with +5 wins on each bank independently.

Update 2026-08-30, iteration 20: a SECOND existence proof, from the upgrade pool (I-015, single-bank so far): committing to Reverse Cursed — the pool's only sustained heal — wins 15/16 at skill 0.6 where the baseline wins 8/16, the largest upgrade effect ever measured. Four independent signals now agree (zero near-misses, 0/97 dawn deaths, yui, regen). The valve doesn't need inventing; it needs DISTRIBUTING — the question is why recovery is locked inside one character and one upgrade line instead of being a beat every player meets.

Update 2026-08-30, iteration 25: I-015 is now VALIDATED on both banks with the skill edges filled in, and the edges changed its headline — see the upgrade-pool entry below. Two refinements matter here. Regen does not rescue novices (+3 at skill 0.25; 1.2 HP/s cannot outpace novice intake) — it owns the steep middle. The thing that rescues novices is focus, +31 at 0.25, which converges with I-014's separate finding that novice power lives on the domain/CE axis rather than the HP axis.

That convergence is mechanical, not just correlational: focus IS the domain axis — src/config.js:435 defines it as domainRate *= 1.3, and domain charge is earned from damage dealt and kills (src/sim.js:1758, :1806), decayed by 1/(1 + t/400). So the pool's one novice-facing rescue works by accelerating the domain engine, while the 550◆ shikigami are dead for novices precisely because they never bank the CE to cast (I-014). Two independent signals put novice power on the CE/domain axis rather than the HP axis, which narrows what the valve should be built out of.

Correction 2026-08-30, iteration 26: a third signal used to be listed here — "yui's rescue is a domain engine, 35 casts/night" — and it has been REJECTED on the second seed bank (I-017; see the club entry below). The axis read stands on focus and the shikigami, which are both two-bank validated; it no longer leans on yui.

Update 2026-08-30, iteration 29 — half of this entry's argument is now fixed, and by someone else's change (I-021, I-023). The tuner landed PLAYER.iframes 0.7 → 0.55, and a 98-death autopsy on dd9ea8f shows:

What did NOT change: near-miss mean is still 0.19. The tune added uncertainty and narratability without adding recovery — runs are now lost late rather than survived narrowly. So this entry's remaining argument is narrower and sharper than it was: the valve is not needed to make deaths meaningful any more, it is needed so that a dip can be come back from. That is the only piece of the original complaint still open, and it is still Chris's feel decision.

The death-screen naming companion is now worth more, not less: 79% of competent deaths have a name to print. Still pure view work, still unbuilt.

Update 2026-08-30, iteration 35 — this is now the LAST CANDIDATE STANDING, by elimination. Six levers have been measured against the novice wall and all six failed for one of two structural reasons (full taxonomy below in its own entry): shared enemy constants move competent players too, and flat power grants — including the perk track — reward whoever already survives longest. A lever that genuinely targets novices must have its value fall as the player improves, and the recovery valve is the only proposed mechanic with that property by construction, because it fires only near death: constant for novices, rare for competent play.

So the argument for building it no longer rests on the four "recovery is missing" signals alone. It now also rests on every alternative having been falsified. What is still Chris's: which resource recovers, and when. Shapes the lab can measure as arms once you pick a direction — an HP-gated heal drop that only spawns below ~25% HP, a post-hit mercy window that scales with how low HP is, or a one-per-night automatic survive-at-1HP. The read that matters for each is novice deathT and wins with competent win rate held flat — that flatness is the whole point, and it is the thing no previous lever could deliver.


IDEA — Why every novice fix has failed: a taxonomy (lab, 2026-08-30)

VALIDATED across I-024, I-025, I-026 and I-027, all n=64 on dd9ea8f. This entry exists to save you from re-trying things the lab has already falsified. It is the most decision-useful thing this cycle produced, because it is mostly about what not to build.

The novice problem, stated precisely: fresh-save novice FINAL is 0/64, and the median novice dies at 3:35 into a 12-minute night. Six levers have been measured against it. All six failed, and they failed in exactly two ways.

Failure mode 1 — shared enemy constants move everyone. Novices and competent players fight the same curses, so any enemy knob moves both.

lever novice effect competent cost
BOSS_INTERVAL 150→210 −8s (worse) —
boss HP −30% +5s, 6 wins —
hpRampSec 240→360 +12s —
husk HP 42→26 +52s ceiling 47%→56%
husk dmg 12→8 +20s, 4 wins ceiling 47%→73%

The husk arms are the ones that worked — and that is the problem. They work by making the game easier for everybody, so the FINAL ceiling I-021 just established gets spent to buy novice survival.

Failure mode 2 — flat power grants reward whoever survives longest. This one is subtler and it caught the lab out. The perk track looked like a novice-only axis, since perks are what novices lack. But a +35 HP / +16% damage grant is worth more to a player who lives 7 minutes than one who dies in 3. Re-measuring I-010's front-load: novices gained +3 wins of 64; invested competent players gained +8. The gift is 2.7× larger for the stronger player.

The conclusion, and it is a construction argument rather than a hope: a lever that actually targets novices must be one whose value falls as the player improves. Neither an enemy constant nor a flat grant can do that.

Which leaves exactly one shape standing, and the game has been circling it since I-007: a recovery valve that fires only near death. Novices are near death constantly; competent players rarely are. Its value decays with skill by construction, which is precisely the property every failed lever lacked. See the recovery-valve entry at the top of this file — it is no longer just the oldest open idea in the ledger, it is the last candidate standing.

Two honest caveats. The husk hp26 arm is a genuinely good trade if you are willing to spend ceiling (+52s novice, and it improves the threat pulse: near-miss 0.19→0.27, clutch 9→13). And the front-load's novice half is real — it is the only change measured that gives a fresh-save novice a win at all — so if it ships, it wants a companion that pulls invested competent back down from 81%.


IDEA — Character balance dossier: sora's deficit, yui's dominance, and the compression the shikigami buy (lab, 2026-08-30)

Two-bank VALIDATED (I-012 + I-014, pooled n=32/cell, FINAL yard t1):


IDEA — QUIZ has no bite (lab, 2026-08-30)

Two-bank VALIDATED (I-001 + I-002, board item #1): near-miss mean is 0.00 across all 96 QUIZ runs at skills 0.25/0.5/0.8 — the quickie never bites for anyone — and novice win rate is 72% vs the economy table's 50% design point. Fix shapes ready to micro-experiment on your word: a QUIZ-only early HP ramp, or a scripted ~120s mini-surge. Never spawn counts. Constraint: QUIZ is the paid rung stalled players drop to (+302◆) — target ~50–60% novice wins, no lower, or the ladder starves.


IDEA — A mixed-strength club dilutes the stronger player (lab, 2026-08-30)

VALIDATED on two banks (I-016 + I-018, pooled n=32). This entry was rewritten on 2026-08-30 — an earlier version blamed the domain economy on one bank's evidence and was wrong; the retraction is at the bottom, kept so the dead end is not rediscovered.

A 2-club's win rate is, to first order, the field-time-weighted mixture of its members' solo win rates. Pooled wins of 32, FINAL yard t1, bare kits, sim 34477c3:

arm 0.25 0.8
solo yui 12 31
yui+sora, swaps blocked 11 32
yui+sora, normal play 1 17
solo ren 1 25
ren+kaito, swaps blocked 1 25
ren+kaito, normal play 4 26

Two things fall out. The party system itself costs nothing — the swaps-blocked arm equals solo in every single comparison, which also means the party-only 8s DOMAIN_SWAP_LOCK is inert and should not be tuned. And tagging costs the unequal club catastrophically while leaving the equal club alone: yui+sora loses 11 of 32 at novice and 14 at competent, where ren+kaito is flat to slightly positive.

The mixture rule predicts it. At skill 0.8, fieldFrac_A × solo_A + fieldFrac_B × solo_B lands within 1.6–2.8 wins of 16 in all four cells: yui+sora bank a (55/45 split, solos 16 and 4) predicts 10.6 against 9 observed; bank b (62/38, solos 15 and 4) predicts 10.8 against 8; ren+kaito bank a predicts 13.0 against 15; bank b predicts 11.0 against 11. It slightly over-predicts the unequal club, consistent with a little tagging overhead (cooldown plus the 2s arrival lock) layered on top of dilution.

So the club problem is a design question, not a balance bug, and it is now sharply posed: a mixed-strength club is a strict downgrade for the stronger player, because an average is an average. If the club is meant to be a retention feature — heuristic 9, a reason to come back with a friend — it needs a compensating benefit that scales with the strength gap. Candidates: shared XP or fragment income, an explicit mixed-club bonus, or simply letting the stronger member hold the field longer by choice. That last one is already most of the way there, since field time currently splits 55–69% toward the captain — but it is a player-agency question, and the HUD shows neither a benched member's CE nor their domain charge (src/sim.js:2086, src/ui.js:1541), so a human cannot steer the split deliberately today. Chris's call.

Confirmed and sharpened 2026-08-31, after the LINE CHANGE shipped (I-036, VALIDATED on a genuinely independent bank). This entry survives the new mechanic intact, and the gap is wider than it looks above. On standard-64b (minted at lab iteration 44, zero seed overlap with any earlier bank), FINAL skill 0.8 with SHIKIGAMI: yui+sora 9/64 (14%) against ren+kaito 32/64 (50%) — a 36-point spread at equal skill, roughly 9 SE, where the design bar is 15. Bank a agrees (5/64 vs 31/64).

Three things worth knowing before anyone tries to fix it:

This is now the oldest unaddressed balance defect in the ledger. It is a tuning question, so it belongs to Loop 2 — but Loop 2 cannot mint its own proposals, so it needs to reach the feedback board before anything can happen.

Retracted 2026-08-30 (I-017, REJECTED — kept as a dead end). An earlier version of this entry claimed yui's rescue was a domain engine: 35 casts a night solo, collapsing to 4 in a club because benched domain charge freezes. Both halves failed the two-bank gate. The 35 was a standard-16 artifact — on standard-16b the same novice cell casts 8 and takes 1862 kills, not 5615. And the mechanism is falsified directly: crediting benched members with 0.5× of the active member's earned charge raises domain casts in every cell (bank a 0.25: 7 → 10; bank b 0.8: 38 → 44) while recovering essentially no wins (0/32 novice, 19/32 competent, against a 1/32 and 17/32 baseline). Domain charge is earned from damage and kills, not accrued per second, so the original "mirror BENCH.regenMult" proposal was not even implementable as written. This was promoted here one iteration before its confirming bank ran — the lab's own lesson is that OPEN findings are unpromotable, not merely unconfirmed.


IDEA — The upgrade pool has a 69-point policy spread (lab, 2026-08-30)

VALIDATED (I-015, two banks + skill edges, pooled n=32 at skill 0.6). Measured with a prefer-X harness: take X whenever offered and unmaxed, else the normal bot choice — so read these as "what this line is worth when a player commits to it", a stronger treatment than one forced first pick.

Heuristic 7 wants no choice to be a >15-point outlier; this pool spans 69. The tuning fork: trim regen/focus (cost or effect) or give the pool recovery-adjacent competition, and either strengthen step's per-slot effect or cut its offer weight. Judge any pool tune with the prefer-X harness, not offer-rate intuition — the harness's baseline cell replays the recorded fresh 0.6 cell exactly, so it has proven fidelity.

Bears on the recovery valve above: prefer-regen runs mint near-misses (mean 0.50 vs baseline 0.13). In-run recovery is what converts a dip into a threat pulse instead of a death.


IDEA — Barrier skill (JJK canon)

Chris, 2026-08-29: "a Barrier skill, which is more JJK canon. Not sure what it would do, but I want to explore it later."

Unspecified on purpose — the shape is the thing to explore, not the code. Context for whoever picks it up: barriers (帳, veil) in JJK are about DENYING ACCESS to a space, not dealing damage. That makes them the natural counterpart to a Domain — a domain is a space you impose, a barrier is a space you seal. The game already has the vocabulary for it: fx.ring geometry, _blocked() collision in sim, obstacles that stagger a charging enemy, and Iron Cell's drag+crush as a precedent for a domain kit that moves bodies.

Open questions worth answering before building: is it a fifth ELECTIVE (fits the CE-cost, no-cooldown slot) or a new technique category? Does it block enemies, projectiles, or both — and does it block the PLAYER's shots too, which is what would make it an interesting decision rather than a free wall? Is it placed, or centred on the player? Does it have HP, or a timer?

Do not build this without Chris. The interesting version costs him a decision about what it denies.


FIXED 2026-08-29 — the night music loop (kept for the lesson)

Shipped: loop 52.00 - 67.55, baked by scripts/loop-bake.py from the lossless master with a 0.30s equal-power crossfade. Level swing inside the loop 7.6 dB, down from 28.2.

THE LESSON, because I got this wrong for several rounds: the skip was never the seam. The track has composed breakdowns at 46.5-51.0s and 68.5-71.5s where the level dives 15 dB and slams back with +24 dB jumps, and the old loop contained both, replaying them every 48 seconds. I measured the wrap, improved it from -6.86 dB to +0.50 dB, and Chris correctly reported no improvement — because the thing he was hearing was inside the loop, not at its edge. Only when he said "none of these are improvements" did I scan the whole track for discontinuities instead of the one point I had assumed was at fault.

Second lesson: the final 0.05s came from his ear, not from a meter. The measurements could not separate 67.45 / 67.50 / 67.55 — baking all three and letting him listen settled in one round what another day of analysis would not have.

SUPERSEDED — the original diagnosis (the wrap, which was not the problem)

Chris, 2026-08-29: "lots of audio skips noticeable, it seems to have gotten worse in our fixes."

Measured on the shipping assets/music/night.mp3 by decoding it in the browser (ffmpeg was blocked by an Application Control policy on the machine at the time; OfflineAudioContext.decodeAudioData + getChannelData works fine and measures exactly what the game hears):

Therefore: do not keep hunting for better loop points. The fix is an equal-power CROSSFADE at the wrap — overlap the tail into the head so the seam is smoothed instead of butt-joined. Two ways:

  1. In-engine (preferred): two AudioBufferSourceNodes and a gain crossfade scheduled at the wrap. Works for every track, needs no re-baking, and fixes the boss cues and stage beds at the same time.
  2. Offline: bake a crossfade into the file's head and shorten the loop. Needs ffmpeg, and has to be redone per track.

SECOND SUSPECT, same symptom, and it is mine: sound.platter() bends the music's playbackRate on every level-up (turntable wind-down, ~25x a night). That is by design, but it is new, it coincides with "got worse in our fixes", and it has never been heard against a real decoded track — the headless harness has no trackSrc, so it could not be observed. Before rebuilding the loop, A/B it: set platter() to return early and play a night. If the skips go with it, the loop is a separate and smaller problem.


FINDING — the night ambience never stops (accidental, and Chris likes it)

Chris, 2026-08-29, on the level-up turntable: "it works fine but there is just white noise beneath it (probably a good idea)."

That noise is not part of the turntable. platter() only bends playbackRate; it adds nothing. The sound is the TITLE-SCREEN cricket bed: titleAmbience(true, ...) starts ambSrc looping into the sfx bus at gain 0.5, and titleAmbience(false) is never called anywhere in game.js — only (true, true) for the cold open and (true, false) for the menu. So the bed starts at the title and plays under the entire run, masked by the music. Winding the music to a stop is simply the first time anyone has heard it.

Chris is right that it is a good idea, so make it DELIBERATE rather than leaving it as a leak: keep the bed running by design, duck it while the music is at pitch, and let it swell as the platter winds down — the school is still there when the record stops. That is a few lines on ambGain, but it is a design choice, so it waits for him.


GAP — RESTORE HEALTH has a voice for Sora only

Chris, 2026-08-29. The event now exists and fires in two places: picking a heart off the ground (pickup with kind === 'heal') and taking the Vitality perk, which heals 25 on pick. Its job is to tell the player they were healed.

Only Sora has a read. sora_heal / heal2 / heal3 are wired; ren, yui and kaito have no {id}_heal.mp3, so they are silent. That is safe by design — vo() no-ops on a missing file — but it is a hole, not a decision.

Candidates should be hunted the same way Sora's were: hers came from lines written for other roles entirely (a HURT take, a DEATH take, and half of a DASH take), because a small relieved sound reads as "healed" regardless of what it was generated for. Look through the existing auditions before generating anything new.

Same shape, same gap: LOW HEALTH ({id}_hurt) and BOSS KILL ({id}_bosskill) are also Sora-only right now.


OPEN — the capture archive is single-copy

1.4GB of gameplay captures (12 videos, 41 stills) now live at G:\Skunkworks\_archive\hallpass-captures\, out of the repo for good. That solves the git problem but not the durability one: the archive sits on the same physical disk as everything else, so it is an archive, not a backup.

Chris raised R2 once already, for shipping video. The same bucket would serve here. Options, cheapest first: Cloudflare R2 (needs an account + token, and egress is free, which suits occasional pulls); Google Drive (a connector already exists in his tooling, but 1.4GB of mp4 is clumsy there); or an external drive, which is free and manual.

Dating is handled (2026-08-29): the filenames carried no date and the videos had no embedded timestamp, so mtime was the only record — and mtime is the first thing a copy or an upload destroys. All 12 videos now carry creation_time in the container, remuxed with -c copy so nothing was re-encoded, and MANIFEST.json holds every file's date, size and sha256 as a second copy of the same facts. Capture window: 2026-08-26 01:07Z to 2026-08-27 19:15Z.

Sweeping is handled: python scripts/archive-captures.py moves anything in captures/ to the archive, stamps the date into video containers, and rebuilds the manifest. Safe to re-run (identical files are skipped, not duplicated). shots/ is opt-in via --include-shots because it is live scratch for shot-server. --verify re-checksums the whole archive.

The remaining piece is OFFSITE. Chris has said Google Drive. When that happens, the natural shape is a --push flag on the same script: everything it needs is already in MANIFEST.json (path, size, sha256), so an upload can be incremental and verifiable rather than a blind re-copy of 1.5GB.

Not urgent, not automatic — it needs Chris to authorize the Drive connector and say where. Until then, one drive failure loses the footage.


Late-game verb collapse — "domain farming" measured (2026-08-30)

Chris, after playing FINAL: "at some point it becomes a lot of 'just avoid everything and recharge my domain as quickly as possible'… you basically feel like you're just domain farming." Measured, and he's right — the numbers below are 8 botted ren-solo FINAL nights (skill 0.8, session analysis, not a lab record; the seeds and harness are reproducible from the sim).

t field fast% within 5u kills/min dom-kill % dash/min ce%
60s 27 70% 2.0 167 25% 6 26%
300s 47 52% 3.0 458 66% 16 20%
600s 53 63% 3.4 668 71% 20 18%
660s 46 63% 3.6 702 72% 22 19%

Three mechanisms, all structural:

  1. The weapon stops mattering. Enemy HP scales ×6.4 by t=600 (×10.9 at
    1. while weapon DPS grows much slower; the domain wipes crowds regardless of their HP. So all clearing migrates to the domain — kills inside domain/after-effect windows go from a quarter of the total to three-quarters. "Charge domain, dodge until ready" is the optimal line because nothing else clears.
  2. Pressure is monotone. Spawn rate climbs to the 11/s cap by t=480 and stays there; the spawn mix is STATIC — grub+wisp hold 58% of the weight forever (ENEMY_TYPES.w never changes after t=280). Bodies within 5u never dip below ~3 after t=120. There is no lull, ever, so there is never a beat of room for the elective or a tag.
  3. CE is triple-booked. The tank sits at ~20% from t=60 onward: dashing (20+/min late × 10 CE) + weapon fire + the elective's 55-CE bite all draw from the same pool. Flash-stepping to survive starves the elective that would have made space.

Options, in recommended order

B — pressure waves — SHIPPED 2026-08-31 (see MECHANICS.md; late room% 26-29 -> 45-49, kill pace -20%, cooldown 30s is the economy valve). Was:** After a domain resolves (and after a boss kill), a short spawn lull — ~6-8s of spawn budget frozen, existing crowd briefly recoils. The domain becomes a door-opener: the wave it clears STAYS cleared long enough to tag, cast the elective, or grab pickups. This attacks the felt complaint directly ("no room"), touches no XP economy (deferred spawns, not deleted ones — freeze the budget, don't zero it), and is a small, testable sim change. Non-negotiable #3 survives: difficulty still comes from HP/speed; this shapes WHEN pressure arrives, not how much.

A — late mix shift. After ~t=400, decay grub/wisp weight and raise husk/spitter/brute so the late field is fewer-but-heavier (Chris's own suggestion). MUST hold xp/s neutral — heavier types carry more xp each, so total spawn rate comes down as weight shifts, keeping the XP economy flat (#3: spawns are the economy). Lab experiment first: the same harness above, weights as the arm, xp/s and dom-kill% as the reads.

C — late weapon relevance. Bend the HP curve or give weapons late scaling so the weapon stays a clearing tool and dom% settles nearer 50%. Touchiest: the tuner just landed I-021 (iframes, FINAL 81%→47%) and every HP-curve knob re-opens that. Only with the lab, only after A/B.

From the lab — "there is never a lull" is a shared root cause

Added by Loop 1 at iteration 30. Mechanism 2 above ("Pressure is monotone… there is never a beat of room for the elective or a tag") is, on the lab's evidence, not just a feel problem — it is the structural cause behind three separate findings that were each investigated as if they were their own bug:

This raises option B's value well above what its own section claims. A post-domain lull is not only the answer to "no room" — it is a candidate answer to the elective dead zone, the club tax, and the missing near-miss, all of which the lab has been circling separately for thirty iterations. If B gets built, the lab should measure it against those three reads, not just against dom-kill%.

Caveat kept honest: this is a convergence argument, not a measurement. No lull has been simulated yet. The prediction it makes is falsifiable and cheap — if B lands, novice shikigami uptime and club-tag value should both rise without touching either system.

Do NOT fix it by raising spawn counts or nerfing the domain: the first breaks non-negotiable #3, the second punishes the mechanic Chris likes most.

Charm consumables (monetization, later)

Chris, same session: purchasable one-night charms — +1 flash step, +10% length, etc. — consumed on death, re-bought per run. The permanent version shipped 2026-08-30 as per-student STEP TRAINING (stride/tempo/echo on the student sheet), so a charm is a ONE-NIGHT rank boost through the exact same per-member fields (party[i].stepLen/stepCd/stepChg) — no new sim surface needed, just a purchase that writes into startRun's steps instead of the save. Fragment-priced first; real-money never without a separate conversation.


The Line Change — SHIPPED 2026-08-31

The last puzzle piece Chris asked for: a reason to switch that is not domain stacking. Tagging is a stamina rotation — play until winded, tag on the wave, the clubmate walks on flush and their elective is free for one entrance cast. Full write-up in MECHANICS.md; levers filed for the tuner as board #8 (approved). Charm consumables (above) now have a third natural knob: a one-night freshWindow extension.


ISSUE — ROOF is the deepest ladder wall AND the most expensive room to

unlock (promoted by the playtest lab, 2026-09-06, iteration 187)

ROOF costs 1500◆ to unlock — the most expensive room in the game — and is by far the hardest: novice 0/16 wins, competent 25% (vs yard 18.75%/100% and gym 6.25%/81.25%) at the same sha/skill/period (I-157). It is also the worst room on heuristic 6 (narratable deaths): only 6.25%/8.3% of its deaths are boss-attributed, below gym's already-poor 13.3% and yard's 38.5% — most roof deaths read as anonymous, not "I almost had it."

Two separate causes, both lab-confirmed, neither fixed:

  1. Obstacle geometry — the same obstacle-stripping fix that fully closes gym's cliff (81.25%→100% competent, I-077/I-132) only PARTIALLY closes roof's (25%→43.75% competent, I-158). Something else in the room is still eating the difference.
  2. Projectile exposure — stripping roof's obstacles exposes a second factor: ranged-attack deaths jump from a minor cause (8.3%) to the dominant one (44.4%) once the obstacles that were incidentally blocking line-of-fire are gone (I-159). The obstacles were a two-edged sword — blocking movement AND blocking shots — so removing them trades one problem for another instead of solving it.

The novice wall is a sharp cliff, not a gradual decline: QUIZ is playable (56.25%), MIDTERM/FINAL both flatline at 0%, with death timing clustering almost identically (168–174s) regardless of period length (I-160). That timing match traces to a shared mechanism, not something roof-specific: both MIDTERM and FINAL resolve to the same t=150 first-boss spawn (sim.js:268, nextBossAt = min(150, max(60, nightLen-60)) — I-161). THE JANITOR isn't roof-exclusive, so the room-specific problem is how roof's geometry handles that universal first-boss encounter, not the boss itself.

Proposal: this needs a human pass on roof's geometry — likely adding sightline-blocking cover that does NOT also wall off movement (so it solves the projectile problem without reopening the obstacle-mobility problem the gym fix solved), and a look at why the novice cliff is so much sharper here than any other room's wall. Not a config-only fix; blocked on src/maps.js room layout, not on more lab measurement. Full evidence trail: I-157 through I-161 in _hallpass-archive/reports/INSIGHTS.md.


ISSUE — Novice electives are wildly unbalanced: DECOY dominates, FLASH

underperforms (promoted by the playtest lab, 2026-09-06, iteration 187)

At novice skill, kitted ren@yard tier-1 FINAL win rate spans DECOY 68.75–81.25%, CIRCUIT 50–56.25%, FLASH 31.25–37.5% depending on seed bank — a 31–50 point spread, two-bank confirmed (I-165/I-166, VALIDATED). This is one of the largest heuristic-7 ("no dominant choice") violations the lab has found all session: FLASH is close to a trap pick and DECOY is close to a correct answer, at exactly the skill tier where players are choosing an elective for the first time.

The plausible mechanism: DECOY (a taunt-then-detonate effigy) redirects crowd aggro away from the player, which matters more at novice skill because positioning is already the weak link — a novice player benefits more from "enemies stop chasing me" than from FLASH's raw personal-escape mobility or CIRCUIT's damage baseline.

Proposal: a tuning pass on the elective trio's novice-facing power, likely nerfing DECOY's aggro-redirect duration/radius or buffing FLASH's utility, not a new-mechanic question. Config-only (ELECTIVES in src/config.js), Loop 2/tuner territory. Full evidence: I-164 through I-166.


IDEA — Bell Guardian: route After Hours through the existing boss-held-

bell mechanic (promoted by the playtest lab, 2026-09-06, iteration 187)

After Hours (AH) is confirmed near-risk-free across three independent measurements (I-093/I-101/I-139) — it's roughly 2x the main night's scoring pace with almost no death cost, which is a heuristic-2 (threat pulse) problem for the game's own bonus-round content.

The sim already has an unused primitive that could fix this without new code: a boss-held bell deliberately skips the HP floor that a domain-held bell gets (heldBy==='boss', see the code comment at sim.js:1430 — "the domain hold floors HP [that win is earned]; the boss hold does not"). Right now this only matters during the main night's boss duels. Bell Guardian proposes gating AH entry through a boss-held-bell duel instead of free overtime: survive the duel, then AH opens; lose it, no AH tonight.

Calibration point from the lab (I-155): held bells already fire 44% of the time at QUIZ competent skill with ZERO deaths in that sample — meaning the default duel as currently tuned is itself too safe to gate anything meaningful. Any AH-specific version of this needs its own (harder) tuning, not the stock duel numbers.

Needs a human for sim.js wiring (this is sim-surface work, not a config experiment) — the lab can measure whatever difficulty gets chosen once a first pass exists. Full sketch: I-155.

UPDATE (playtest lab, 2026-09-06, iteration 194 synthesis) — the "AH is near-risk-free" premise above needs a skill-level scope correction. That framing (I-093/I-101/I-139) was measured at COMPETENT skill only. Checking novice skill after the fact (I-171, confirmed two-bank at I-172) found AH is NOT risk-free there: kitted novice FINAL bell-winners pushed into a 300s AH window die 22-37.5% of the time (two banks), vs a clean 0% on two separate competent samples. So the game's bonus round already has real, working risk for novice players without any new mechanic — Bell Guardian's actual justification narrows to "AH is too safe FOR COMPETENT PLAYERS specifically," not a blanket claim about the mechanic. Worth keeping in mind when sizing any AH-gating duel: it should probably scale with skill/investment rather than applying one fixed difficulty, or it risks re-adding risk that novice play already has on its own.


ISSUE — QUIZ has zero threat pulse at any skill level, with or without

kit investment (promoted by the playtest lab, 2026-09-06, iteration 194)

QUIZ (the 3-minute "quickie" mode) fails heuristic 2 (threat pulse) harder than anything found for FINAL this session. Kitted ren@yard QUIZ: 16/16 wins at BOTH novice and competent skill, near-miss mean 0.0 at both (not just the median — zero across all 16 runs at both skills), and at competent skill the threat sparkline reads as literally flat zero for the entire run — two-bank confirmed (I-168/I-169). minHP never drops below ~76-100% median at either skill on either bank; per heuristic 2's own definition, these are "wins that are chores."

The natural first guess — that kitted power is simply too strong for a 180-second mode — turns out to be wrong. Bare-kit QUIZ was checked too (I-170) and produces the exact same result: 16/16 wins at both skills, near-miss mean 0.0 at both. The one real difference stripping gear makes: novice minHP p50 drops from kitted's 78.8% to 42.1%, a genuine dip into the game's documented 25–50% "wounded" band (see the Recovery Valve entry above) — but even that never reaches the 15% near-miss threshold.

Conclusion: this isn't a kit/elective balance problem, it's a QUIZ pacing problem. The mode's 180s length simply doesn't give the difficulty ramp / surge ladder time to generate real danger before the round ends, regardless of how much power the player brings. Since QUIZ is meant to be the "chasing stars, not surviving" mode (heuristic 8), this may be an acceptable design choice rather than a bug, but it's worth a deliberate call rather than an accident: right now nobody who plays QUIZ, at any skill or gear level, ever experiences a moment of real danger. Full evidence: I-168 through I-170.

UPDATE (playtest lab, 2026-09-06, iteration 199) — the obvious fix doesn't work, narrowing the design space. The natural next idea — a scripted late-QUIZ difficulty spike reusing the existing tier-mod system (STAGE_TIERS[n].mods, the same enemy HP/speed multipliers that scale the FINAL ladder) — was tested directly and fails (I-175). Running all of QUIZ under tier 2's mods still gives near-miss mean 0.0 at both skills; running it under tier 3 (the hardest multiplier this game ships) gets only a token 0.06 at competent and still exactly 0 at novice. Three magnitude steps, no meaningful improvement. So this isn't a "make enemies hit harder" fix — the bottleneck is TIME, not toughness. Enemies apparently need sustained exposure to converge on and pressure the player, and 180s doesn't give that process room to complete no matter how dangerous each individual enemy is. A real fix likely needs to touch spawn EXPOSURE or POSITIONING instead — enemies converging on the player sooner, or a guaranteed early encounter that front-loads danger rather than relying on the organic ramp. That's a design question, not something the lab can prototype further without sim.js access.

UPDATE (playtest lab, 2026-09-06, iteration 214) — the problem reaches MIDTERM too, but looks more fixable there. Kitted MIDTERM (360s, double QUIZ's length) shows the identical zero-near-miss pattern at both skills, two-bank confirmed (I-186/I-187) — this isn't unique to the 180s quickie mode. The difference: MIDTERM's HP dips are already much deeper than QUIZ's (novice minHP p50 ~52%, landing inside the documented 25–50% wounded band, vs QUIZ's 76–79%). Since the run is already getting genuinely close to danger and just not quite crossing the 15% near-miss line, MIDTERM likely doesn't need QUIZ's full exposure/positioning redesign — a smaller nudge (a modest surge-timing shift or HP-ramp adjustment scoped to this period) might be enough to push it over the threshold. Worth testing before assuming QUIZ's harder fix is required everywhere this pattern shows up.

UPDATE (playtest lab, 2026-09-06, iteration 224) — the exact mechanism, quantified (I-194). src/config.js's enemy HP-ramp formula ((1 + t/hpRampSec + (t/hpQuadSec)^2) * 2^(max(0, t-hpLateStart)/hpLateDouble), with hpRampSec=240, hpQuadSec=380, hpLateStart=630, hpLateDouble=100) is shared across every period and was clearly calibrated around FINAL's much longer arc. Computed at the actual timestamps involved: QUIZ's boss spawns at t=120 where the multiplier is only 1.6x base HP, and QUIZ ends at t=180 at just 1.97x. FINAL crosses 3.78x by t=400, 11.88x by t=700, and 28.48x by t=800 (deep After Hours). QUIZ's entire runtime never reaches even a sixth of FINAL's late-game multiplier — this is exactly why I-175's tier-mod experiments (which only add a further ~1.9x constant on top of an already-tiny base) could never close the gap. Since hpRampSec and friends are shared, global, and already flagged fragile/non-monotone by the tuner (I-417), the fix should NOT touch them. A cleaner, period-scoped alternative: give QUIZ's boss a virtual time offset for its OWN stat calculation only (e.g. compute its multiplier as if t were already ~500-600), so a t=120 QUIZ encounter reads as dangerous as a mid-to-late FINAL one without touching the shared ramp or any other enemy. This is now a precisely scoped sim.js ask rather than a vague "make QUIZ scarier" request.


ISSUE — After Hours punishes the roster's weakest characters the most

(promoted by the playtest lab, 2026-09-06, iteration 199)

After Hours (AH) — the optional 300-second extension after ringing the bell — was already found to carry real death risk at novice skill (unlike competent skill, where it reads as pure bonus value): kitted novice FINAL bell-winners die during the AH window 22–37.5% of the time for ren, across two seed banks.

Checking the rest of the roster (n=4–5 per character, small samples, but a stark directional pattern) shows this risk doesn't apply evenly — it gets WORSE for exactly the characters who were already weaker at getting to the bell in the first place:

Why this matters: a bonus round that's meant to reward reaching the bell currently does the opposite for the characters who struggle most to get there — kaito and yui pay a much higher price for pushing on than ren does, on top of already having a harder time reaching the bell in the first place. This compounds rather than offsets the roster's existing tier-1 imbalance (documented separately — kaito/sora's novice tier1 walls, yui's tier3 struggles).

Proposal: worth a deliberate design call rather than an accident. Either this is acceptable (AH becomes an additional skill-expression opportunity, and characters who reach it having struggled more deserve to face more risk there too), or it's worth softening — e.g. scaling AH's enemy HP/speed ramp per-character rather than applying the same curve to everyone, similar to how the roster's base kits already differ. Not a config-only fix (AH's ramp lives in sim.js's difficulty-scaling formulas), and the small samples (n=4-5 for kaito/yui) deserve a second bank before the exact percentages are treated as final — but the ranking itself (yui > kaito > ren > sora) is consistent with everything else this session has found about the roster's relative fragility. Full evidence: I-171 through I-176.

UPDATE (playtest lab, 2026-09-06, iteration 204) — two-bank confirmed, and two follow-ups narrow what "softening" should mean.

  1. Two-bank confirmation (I-178): the pattern holds on a second seed bank, in one case exactly — yui's AH death rate matched 80% on both banks; kaito's was if anything worse on bank B (100%, n=3); sora reached the bell rarely on bank B (2/16, vs 0/16 on bank A) and died both times. Ready for design review without further two-bank work.
  2. A single "shorten AH duration" fix won't work roster-wide (I-179). Tested directly: yui's AH deaths split across the window (2 of 5 by the halfway point, 2 more after), so halving AH's length would cut her death rate 80%→40% — duration genuinely matters for her. kaito's deaths are different: all 3 of his 4 happen in the FIRST HALF of the window, so a shorter AH would save none of his runs — his kit simply can't handle AH's enemies at all, regardless of exposure time (matching the slow-weapon finding above). Any per-character softening needs to distinguish these two failure modes — a duration knob helps yui-type characters, not kaito-type ones, which need a stat-level adjustment instead.
  3. Clubbing with a stronger character does NOT rescue AH risk (I-180). A kaito+ren party reaches the bell more often than solo kaito (43.75% vs 25%, tracking the club's known "weakest link" dynamic — see the party-composition findings elsewhere in this lab's ledger), but of those runs, ALL of them (7/7) die in AH — worse than solo kaito's own 75%. A stronger partner's damage output doesn't change whether the weaker member's kit can survive AH's ramp; it only changes how often the party gets there at all.

Net effect: this issue is design-review-ready on the core claim, but any actual softening should be scoped per-character (duration for yui-type failures, stats for kaito-type ones) rather than one global knob, and shouldn't assume party play offers a workaround. Full evidence: I-171 through I-180.

UPDATE (playtest lab, 2026-09-06, iteration 224) — a second party pairing confirms the club finding, and a MAJOR correction: this is NOT a novice-only issue.

  1. Second party pairing confirms I-180 (I-195): yui+ren converges on the exact same 100% AH death rate as kaito+ren, even though ren doesn't improve yui's reach-the-bell rate at all here (31.25% either way, unlike kaito's 25%→43.75% boost from clubbing). Two independent pairings now agree: clubbing never rescues AH survival, regardless of the weak member's specific failure mode or whether the party's win rate improves.

  2. MAJOR CORRECTION (I-196): "AH is risk-free at competent skill" was never a roster-wide finding — it was ren-specific, and this session's own default-test-character bias hid that. The original claim (I-093/I-101/I-139) was measured on ren alone. Checked the rest of the roster at competent skill for the first time this session: all three other characters reach the bell 16/16, but die in AH at real, substantial rates — kaito 68.75% (11/16), the single largest AH-risk number found at ANY skill level all session, yui 31.25%, sora 37.5%. Only ren shows the clean 0/16 that the whole "AH is pure bonus value" framing was built on. The character ranking (kaito worst, sora/yui middle, ren safest) is identical to the novice-skill ranking above — this was never a novice-specific problem, it's a roster-wide one that a ren-only measurement simply couldn't see.

This changes the issue's real scope: AH risk isn't "novice pays a real price, competent gets a clean bonus" — it's "ren gets a clean bonus at both skill levels, everyone else pays a real, sometimes severe price at both skill levels too." Any fix (duration-scoped for yui-type gradual attrition, stat-scoped for kaito-type immediate mismatch) needs to apply across BOTH skill bands, not just novice. Full evidence: I-171 through I-196.


ISSUE — POOL is a harder, cheaper, worse-narratability room than ROOF

(promoted by the playtest lab, 2026-09-06, iteration 209)

ROOF has been flagged repeatedly across this session's synthesis passes as the game's deepest ladder wall — the hardest room, and the most expensive to unlock (1500◆). It turns out there's a worse room that had never been tested this session at all: POOL (800◆, roughly half roof's price).

Kitted competent win rate, two-bank confirmed:

Kitted novice win rate: ROOF is 0%, and so is POOL — but POOL's failure is worse on every other axis heuristic 6 cares about. Boss-attributed deaths sit at 0–6.25% for POOL novice (roof's already-poor figure was 6.25%) and 14.3–30.8% at competent, and deaths land EARLY rather than late — novice death time is only 32–38% into the 720s night, competent 43–48%. A death this early, this rarely tied to a named boss, reads as an anonymous wall, not a story worth retrying for.

The obstacle-strip fix that helped ROOF and fully closed GYM does NOT generalize here (I-184). Stripping POOL's obstacles moves novice not at all (0/16 wins either way) and competent only from 12.5% to 25% — landing exactly at ROOF's own PRE-fix number, i.e. POOL's best case after the fix is still where roof started. Hits taken are completely unchanged (22 novice / 32 competent, identical stock and stripped), and death causes stay projectile-dominated in both conditions. This is the opposite of roof's pattern, where stripping obstacles created a new projectile problem by removing cover that was incidentally blocking line-of-fire — POOL already has an open-sightline problem regardless of what obstacles are present, because the room's water-hall layout doesn't provide blocking terrain in the first place.

Why this matters: POOL is currently a worse ladder experience than the room already flagged as the game's worst, and it costs a player less to unlock the privilege of hitting it. A player following the natural unlock-by-price order will hit POOL's wall before ROOF's.

Proposal: needs a human src/maps.js geometry pass, not a config tune. Unlike roof (where the fix direction is "add sightline-blocking cover without blocking movement"), POOL likely needs actual line-of-sight breaks added to what may currently be too open a layout for a room this early in the unlock order — pillars, equipment racks, or similar props that block projectiles without functioning as the kind of hard obstacle that hurts mobility. Worth treating POOL and ROOF as a pair when this gets picked up, since they're now the two rooms confirmed to need real design attention rather than tuning. Full evidence: I-182 through I-184.

UPDATE (playtest lab, 2026-09-06, iteration 234) — this is now a THREE-room problem, and it happened by itself. A separate content pass (checkpoint commit 1e7d253, "character rig + five environment kits + showroom") gave HALLS, CAFETERIA, DETENTION, BOILER, LAB, and ROOF real interior zone geometry for the first time (previously sparse/placeholder layouts) — unrelated to this issue, but it moved the numbers underneath it. Re-baselined the three rooms this issue already covers, one bank each so far:

Net effect: ROOF and BOILER now sit tied with POOL at the bottom of the room ladder (all ~12.5–18.75% competent), rather than POOL being the one clear outlier below ROOF. The full ladder now reads yard 100% > gym 81.25% > lab 37.5% > boiler/roof/pool all ~12.5–18.75%. This is a THREE-room design-attention cluster, not a pair — worth widening the scope of whoever picks this up accordingly. All three post-kit numbers are single-bank so far; a two-bank confirmation would firm them up before treating the exact figures as final, though the qualitative shift (the bottom of the ladder got both harder and more crowded) is unlikely to reverse. Full evidence for the reconnect and re-baselines: I-201 through I-204.


Next ideas — 2026-09-14 (conversation numbers 1–10)

Append-only follow-up to the September 12 list: the numbers in this section belong to this conversation and do not renumber or replace earlier entries. Selected next: #1 Boss signature cards, then #9 Boss music. Chris asked for the minor Flash Step fix first. Implementation of these ten ideas has not started; the other eight are saved proposals, not simultaneous work. Start with one complete example before expanding the content set.

  1. Boss signature cards — selected next. Give a defeated boss a collectible card that carries a recognizable piece of its combat behavior, rather than another flat stat bonus. First slice: one boss, one signature effect, and a clear reward reveal. Build on the existing card/deck system and the deferred boss-drop/pocket plan; explicitly define when the found card becomes usable, banks, and can be lost. Keep boss weapon rewards understandable alongside it, and verify receipt/save/restore behavior.

  2. Finish the Ren–Yui combo. Continue the September 12 selected #1: Yui threads a cluster, then tagging Ren detonates the linked enemies in one red chain impact. First slice: one deliberate setup, one readiness cue on the existing Tag control, and a complete attack/sound treatment. Respect domain restrictions, knockouts and existing tag benefits; no new mobile action button or automatic damage bonus for arbitrary switching.

  3. Break a boss attack. Expose a physical curse seal during one major windup; destroying it cancels that attack and briefly staggers the boss. First slice: one boss and one interruptible move, with a legible seal, fracture sound and punish window. Avoid an opaque damage threshold or mandatory interruption: dodging the attack must remain valid.

  4. Kaito and Sora behavioral cards. Extend their deferred signature card sets with effects that change decisions instead of adding only percentages. First slice: one card, such as Kaito anchoring his next special at the start of his previous Flash Step. Clearly communicate the trigger, preserve the normal special controls, and check interactions with tags, carried builds and suspended runs before adding more cards.

  5. Boss weapon awakenings. Develop September 12 saved #2: compatible upgrades unlock a visibly transformed weapon with a different attack rhythm and sound. First slice: one weapon, such as Sora's razor fan unfolding into a blade halo that collapses into a cutting arc. Make the requirement and choice clear; limit screen coverage and test the carried build across rooms rather than adding an unchecked raw-power layer.

  6. An interactive combat feature in a room. Develop September 12 saved #3 through one authored prop: attack a Library shelf to topple it through pursuing enemies. First slice: one predictable direction and one use per room, driven by existing attacks. Telegraph its effect and keep navigation and escape routes valid after the prop changes state.

  7. A deliberate shikigami opening. Let a summon strike the point the player already aims at before resuming its normal autonomous behavior. First slice: one shikigami's reliable opening pounce or sweep, using the existing summon input and forgiving target selection on touch. Preserve its ordinary summon value when there is no eligible aimed target.

  8. Last-survivor presentation. Dramatize the final living student's existing protected handoff with a determined voice line, a short musical change and a stronger entrance pose. First slice: one character and one authored cue, with no new damage buff, forced pause or cutscene. Losing teammates should feel consequential without becoming a rewarding tactic.

  9. Boss music phases and defeat resolution — selected after #1. Develop September 12 saved #5 through one existing boss arrangement: synchronized phase percussion and a composed defeat resolution. Also explore Chris's suggestion of short boss vocal cues on arrival and death, mixed alongside the musical changes; voice treatment remains optional. First slice: one track, one phase layer, one ending, and a reviewed pair of entrance/death cues if they improve it. Read MUSIC-ENGINE.md first: retain the current looping primitive, exact sample-derived timing, guarded preload/transition paths and bounded decoded-audio cache. Author against the actual arrangement, not a rounded BPM; never delay input, death settlement or Push On to reach a musical boundary. Coordinate with the existing boss exorcism cues, clear boss-music state on defeat and restore the level passage correctly. Verify joins, pause/resume, music settings and phone memory; never regenerate music during a normal build.

  10. Short supplied-build Exams. Evolve the deferred loaned-deck Daily idea into one authored encounter with the same crew, cards and weapons for everyone. First slice: a short objective such as breaking two boss seals without losing a teammate, through the existing Daily entry. Keep the borrowed loadout separate from owned/risked cards; version the challenge so changed rules cannot mix incompatible scores.

Implementation update — 2026-09-14

The selected first slices of #1 Boss signature cards and #9 Boss music are implemented for The Janitor. The earlier list is retained as proposed; this update does not mark the remaining bosses or optional voice casting done.

Play this one complete example before expanding to more signature cards and boss arrangements. It is a functional pilot, not a finished balance claim.

Boss music expansion — 2026-09-14

Chris authorized expanding #9 Boss music before testing the Janitor pilot. All nine boss identities now use distinct pressure/defeat textures across all 17 rotating boss cues and the generic fallback. Timing is measured per song; the original songs, loops and Janitor/WOW pilot remain unchanged. The shared palette stays around 1.5 MiB decoded, and overlapping fights resolve only when the last boss falls. Listener review of the mix and optional spoken entrance/ death casting remain open. This expands music only: #1 signature cards still has one implemented Janitor card; the other boss cards remain proposals.

Boss signature pickup expansion — 2026-09-14

Chris subsequently authorized expanding #1 Boss signature cards to all nine identities and replacing the pilot's extra active pocket with normal hand slots. The earlier proposal and pilot notes above remain historical.

Implemented: Clean Sweep, Marked Late, Answer Key, Stand-In, Final Warning, Stay After, Shared Credit, Watchful Eye and Office Hours. Each boss identity drops its card once per attempt, alongside ordinary loot. The ground card can be inspected after the exorcism, left for later until room exit, or inspected at cleared results. The player chooses any eligible living teammate and a free slot or an explicit replacement. A displaced owned card loses its run bonus but stays in the collection; a displaced found card leaves the haul. An existing owned-card stake cannot be erased by swapping. Unbanked cards receive no Safe Slot protection.

Only the live hand grants effects. The retained cardPocket name now means accepted acquisition receipts, with no extra slots or power. Only accepted cards still equipped can bank on returning to the Club or another safe departure from cleared results. KO disables a holder's effects, but a surviving crew can still return with the kept receipt. Failure/abandonment loses unbanked cards; the existing rewarded revive retains them. New hand choices preserve earned upgrades and current resources without healing, refilling charges or resetting cooldowns. Old pilot pockets fit a free normal slot or become ground choices without evicting an existing card.

Simulation tests cover all nine rewards and behavior hooks, all four students' starting weapons, duplicate/KO/capacity guards, replacement bonuses, receipts, deterministic snapshot replay and room carry. Economy and combat balance remain unmeasured for this expansion; exact mechanics and constants are documented in docs/MECHANICS.md and src/cards.js.


Next improvement shortlist — 2026-09-15

Ideas only; no feature implementation authorized by this list. Ranked by player payoff relative to the size of a first slice. Chris is handling physical gameplay testing; this is a feature shortlist, not another QA plan. Small/medium/large below are relative implementation scopes, not delivery dates.

The current code already has all nine boss signatures, reactive boss music, weapon pickup models/effects, exorcisms, behavioral elites, four domains and carried school routes. Those are foundations, not new recommendations. Preserve the original enemy models and restored school map. Keep Rive parked until the post-October 1 shipping-cadence review. None of these needs another permanent HUD meter, more enemies, a mid-run asset download or a forced camera cut.

  1. Break the boss's attack — recommended next. Advance the still-open September 14 #3. The Janitor exposes a seal during one generous sweep wind-up; a deliberate primary/special hit cracks it, cancels that sweep and leaves a short opening. One opportunity per encounter for the pilot; passive damage must not solve it accidentally. Existing aim/auto-aim should make it attainable with every starting weapon, without a DPS threshold. Payoff: a visible reversal the player caused, with a snapped weapon pose, brief seal rupture and sharp audio answer. Scope/risk: medium. Mobile targeting and overly easy interrupts are the main design risks. Sim._bossAI currently advances wind-ups into attacks; _damage has no breakable boss target. Preserve attack timing for encounters without the pilot and store its one-use state through suspend/room carry.

  2. A boss weapon that visibly awakens. Advance September 12 #2 with one Sora Razor Script recipe: while a compatible card is in her live hand, every few volleys fold into a blade halo and release as one cutting arc. Choose the exact recipe during implementation; show it in weapon inspection and Your Hand, and remove the form when its prerequisite is unequipped. Payoff: collecting a weapon and building a hand lead to a distinct attack, beyond a percentage bonus. Scope/risk: medium–large. Avoid a mandatory best recipe, extra projectile density and accidental free damage. The twelve run-weapons.js primaries are fixed replacements today; existing ordinary upgrade evolutions are not this proposed weapon/card transformation.

  3. Turn one room prop against the curses. Advance September 12 #3: one clearly marked Library shelf releases a short cascade of books when struck, knocking a group across its lane once per room. Keep the original shelf footprint and walkable routes intact; this first slice needs no physics engine or dynamic navigation rebuild. Payoff: the room becomes a combat tool with a memorable physical action. Scope/risk: medium. The trigger must read among ordinary scenery, and auto-fire must not waste it from across the room. Current Library furniture is static batched art; interactive prop state would belong in Sim and its snapshots.

  4. Hear the dangerous attack's direction. Original proposal: give a charge wind-up and the Janitor's sweep preparation distinct short sounds, positioned left or right relative to the gameplay camera. Prioritize the nearest imminent threat and cap simultaneous warning voices; keep existing visual tells fully sufficient on mute or mono speakers. Payoff: the player can react before locating an attack in a crowded fight. Scope/risk: small–medium. Mix fatigue is the main risk, not graphics cost. At proposal time, Sound.tone/noise fed a shared SFX bus without a directional threat mixer. Use bounded short cues, not HRTF processing or additional full music tracks. Implemented September 15: camera-relative, nearest-only warning cues with bounded voices and mute/mono fallback; see Audio coverage review for coverage and verification.

  5. Let the crew acknowledge the night. New: one optional Ren/Yui exchange inside an existing between-room checkpoint, selected from three states: clean clear, injured teammate, or a missing teammate. Pair it with a restrained portrait reaction and subtitles; all checkpoint actions remain usable immediately. Payoff: the crew feels aware of what actually happened, making the next Push On more personal. Scope/risk: medium, mostly writing/voice production. Avoid repetition, speaking for a KO'd character and adding waiting time. Current arrival films and tag/hurt/win lines exist; contextual conversations between surviving members do not.

  6. A useful Lights Out recap. New: replace one existing results area with the last three damaging hits: recognizable source, damage and one accurate counterplay hint for the fatal attack. No replay video or rolling screenshots. Payoff: a loss creates an immediate plan for the next run instead of only reporting lost Coins/cards. Scope/risk: medium. _hurt currently receives damage and origin coordinates, not an attack identity, so attribution must be carried from projectiles/zones/contact; never guess the killer from the nearest enemy. Keep a tiny bounded record and separate teammate knockouts from the final crew wipe.

  7. Save a whole crew build. New: three named preparation presets, selectable inside the existing Deck screen. A preset records crew card assignments; preview missing/lost cards or occupied copies before applying it. No automatic purchases, duplicate copies or run-time hand changes. Payoff: players can keep a safe build and an experimental build without rebuilding four hands manually. Scope/risk: medium. Ownership, unlocked slots and cloud merges are the main work. save.decksBy currently retains one hand per student; presets must call the same validation/claim rules. This preserves the shipped chosen-loadout system, not the lab-only random deal at run start.

  8. Earn a real First Bell ending. Advance September 12 #10 with one short, skippable school-gate composition after the full ten-room victory: the surviving crew, the weapons they brought home and visible absences determine the tableau. The existing Return to Club action still owns settlement. Payoff: the longest undertaking has a distinctive emotional finish and a keepsake image worth sharing. Scope/risk: large in art, medium in state wiring. Avoid rendering a second live arena, triggering it for a partial route, or implying KO'd students returned. Today's showSchoolCheckpoint reports completion; the dawn/result treatment and round-clear animation are not an expedition-specific crew epilogue.

Start with #1 as one complete Janitor encounter, then decide whether its counterplay earns expansion. The other seven remain a backlog, not parallel production. This review inspected sim.js, game.js, audio.js, ui.js, run-weapons.js, cards.js, save.js, school-run.js and Library prop/map ownership alongside MECHANICS; it makes no new balance or phone-FPS claims.


Audio review follow-ups — 2026-09-15

The Audio Cue Review preserves the BEFORE coverage matrix, the current cue-pass verification record and deliberate quiet areas. The active engineering pass addresses event wiring and bounded synthesis; the following production/UI work remains a backlog, not simultaneous scope.

Crew link and boss encounter update — 2026-09-21

Chris approved the Ren–Yui combination and coordinated combat presentation, followed by a Janitor encounter with a meaningful second move. This dated update supersedes the earlier prototype descriptions; the historical idea lists above remain intact.

These mechanics run in fresh normal attempts through combatVersion: 1. Daily attempts and restored legacy runs retain version 0. New-version saves and room continuation preserve their version and state. See the current contracts in MECHANICS.md.

HALL PASS by Very Bad Games · Solo Developer Chris Sands · All documentation