Fix card/judge disagreement under text lag; session handover
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
7b44e01333
commit
22f5f11dde
@ -932,3 +932,73 @@ the literal back), and (2) the ECONOMY TUNING PASS (baselines: content's
|
||||
3-night run data + door's Phase-1 measurements + floor's idle/attentive table).
|
||||
After those land, the next lanes are content-expansion (encounters, repeat
|
||||
gating), venue 2, and the v0.4 art pass per docs/ASSETS.md.
|
||||
|
||||
---
|
||||
### SESSION — SOLO BUILD-OUT (Fable) — 2026-07-19 23:30
|
||||
**Branch/commits:** main (three commits this session; deployed live)
|
||||
**The headline: THE ECONOMY TUNING PASS IS DONE — against bots, held to bands.**
|
||||
`tests/sim/economy.ts` is a full node-side bot night (QueueManager + judge +
|
||||
Meters + deferred pipeline + churn model, no Phaser); `economy.test.ts` runs
|
||||
careful/sloppy/dawdler bots over 5 seeds and asserts NINE feel-bands. Those
|
||||
tests are now the economy's contract — a knob change that kills the feel fails
|
||||
CI, not a playtest three weeks later. Where the numbers landed (careful bot):
|
||||
admits 87 > denies 69 (was 48/68 — the room fills now), vibe pinned-share 0.34
|
||||
(was 0.99 — the meter is alive), aggro peaks ~36 (was 6), slam queue avg 7
|
||||
peak 16+ (was 1.0/8 — the 10:30 slam is REAL, verified live: 22 in the queue
|
||||
at 12:33 AM), hype decays while you work (was a permanent x3 ratchet), sloppy
|
||||
dies of vibe with 3 strikes, extreme dawdling riots before it profits.
|
||||
**What the tuning changed (all commented at the definition):**
|
||||
- judge: denyViolator 6→2, denyClean 2→1, admitClean 3→2, admitBadId 2→1.
|
||||
- queue: calmPerSec 0.9→0.35, NEW hypeDecayPerSec 0.045 (theatre fades while
|
||||
you serve — kills the ratchet).
|
||||
- arrivals: slam peak 0.42→0.72/min, night total ~70→~120.
|
||||
- generator: logo rate 0.35→0.18; sunnies/bucketHat/blazer weights halved.
|
||||
- NEW `core/meters.vibeCoolingPerMin`: the room cools above 50 (-0.4) and
|
||||
faster above 70 (-0.8), emitted per clock-minute — nobody stays impressed.
|
||||
- **Dazza's attention span (`ACTIVE_RULE_CAP = 4`)**: only his last four rules
|
||||
are live; older ones get greyed on the card + a retraction toast ("dazza:
|
||||
forget the 'NO THONGS' thing. new priorities"). With all 8 cumulative, ~55%
|
||||
of the late crowd was deniable and rule-following EMPTIED the room.
|
||||
- **Natural churn**: patrons go home after 50-140 clock-min (`floor:leave`,
|
||||
new contract event, CrowdSim emits, NightScene frees capacity). Without it
|
||||
capacity was a one-way ratchet and the door locked shut from 1 AM.
|
||||
- **Capacity strike bug FIXED**: the strike reason embedded the patron id, so
|
||||
the reason-dedupe never collapsed and every over-80 admit filed its own
|
||||
strike — 3 admits = licence gone. Now one stable reason per night. (This is
|
||||
what was really killing the long Kayden nights in Phase 2.)
|
||||
**Also this session:**
|
||||
- Floor SFX wired: stall bangs (doorBang), pat-down bin drops (clickerClunk),
|
||||
via optional sfx handles on the overlay constructors.
|
||||
- Cut-off dialogue now wears its blood-alcohol: `drunkify` on the patron's
|
||||
reply, deterministic per dollSeed.
|
||||
- **Encounters 4 → 8** (eighteenToday, kaydensMate, bigNightOut, twoOfThem —
|
||||
register per the §4.3 rules, humane never secretly optimal) + cross-night
|
||||
repeat gating (`GameState.seenEncounters`, recorded off the encounter
|
||||
incident, excluded by the scheduler until everyone's been met). Scheduler
|
||||
reworked: end-order greedy + backward latest-safe pass — a random draw can
|
||||
no longer strand a pick; overflow drops gracefully.
|
||||
- nightShift window tightened to [150,195] (its noLogos dilemma dies when the
|
||||
rule cap rescinds noLogos at 200).
|
||||
- **Bug found & fixed in browser verification**: Dazza's texts lag the clock
|
||||
(send cooldown), so a rule could be rescinded before its card row existed —
|
||||
the one-shot guard then swallowed the retirement forever and the card LIED
|
||||
about what was enforceable. Card sync is idempotent now; verified converged
|
||||
under worst-case lag.
|
||||
- **The Kayden contradiction has now fired in real play** (content's open
|
||||
item): floor stint → his 9:15 PM influencer admit → lied on the report →
|
||||
Friday's paperwork: "kayden wrote his version of p2 up too. it does not
|
||||
match urs. he is very proud of the log". Screenshot in session notes.
|
||||
**Tests:** 632 passing / 0 failing (was 621). Gate clean. **Deployed to
|
||||
https://monsterrobot.games/not-tonight/ (bundle index-W0Kf_Kh7.js, verified 200).**
|
||||
**Broke / known-wonky:**
|
||||
- The sim bot cheats (perfect information, no inspection time beyond a fixed
|
||||
cost) — bands are calibrated to it, not to humans. John's playtest may want
|
||||
the arrival curve ±15%; the bands make retunes safe to try.
|
||||
- Dawdler test covers EXTREME stalling (6s); mild-stall dominance is killed by
|
||||
hype decay but has no dedicated band.
|
||||
- Rule retractions land as toasts; a phone text would be richer (needs a dazza
|
||||
schedule slot — next content session).
|
||||
- Sloppy bot dies by VIBE before aggro ever moves — arguably right (admit-
|
||||
everything tanks the room via laps/ripens) but worth a human sanity-check.
|
||||
**Next:** John's ear pass (M in a live night) and a human feel-pass over the
|
||||
new economy — the bands make it safe to turn knobs. Then venue 2.
|
||||
|
||||
@ -669,9 +669,14 @@ export class DoorScene extends Phaser.Scene {
|
||||
private retireStaleRules(): void {
|
||||
const live = new Set(activeRules(this.night.state.clockMin).map((r) => r.id));
|
||||
for (const r of announcedRules(this.night.state.clockMin)) {
|
||||
if (live.has(r.id) || this.retiredRules.has(r.id)) continue;
|
||||
this.retiredRules.add(r.id);
|
||||
if (live.has(r.id)) continue;
|
||||
// Always re-sync the card: Dazza's texts can LAG the clock (the send
|
||||
// cooldown queues them), so a rule can be rescinded before its card row
|
||||
// has even landed. retire() is an idempotent no-op until the row exists,
|
||||
// and every later text re-runs this sync — the card converges.
|
||||
this.codeCard.retire(r.id);
|
||||
if (this.retiredRules.has(r.id)) continue; // toast once per rule, though
|
||||
this.retiredRules.add(r.id);
|
||||
const line = RULE_RETRACTIONS[this.retiredRules.size % RULE_RETRACTIONS.length]!;
|
||||
this.showToast(line.replace('{rule}', r.short));
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user