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).
|
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
|
After those land, the next lanes are content-expansion (encounters, repeat
|
||||||
gating), venue 2, and the v0.4 art pass per docs/ASSETS.md.
|
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 {
|
private retireStaleRules(): void {
|
||||||
const live = new Set(activeRules(this.night.state.clockMin).map((r) => r.id));
|
const live = new Set(activeRules(this.night.state.clockMin).map((r) => r.id));
|
||||||
for (const r of announcedRules(this.night.state.clockMin)) {
|
for (const r of announcedRules(this.night.state.clockMin)) {
|
||||||
if (live.has(r.id) || this.retiredRules.has(r.id)) continue;
|
if (live.has(r.id)) continue;
|
||||||
this.retiredRules.add(r.id);
|
// 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);
|
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]!;
|
const line = RULE_RETRACTIONS[this.retiredRules.size % RULE_RETRACTIONS.length]!;
|
||||||
this.showToast(line.replace('{rule}', r.short));
|
this.showToast(line.replace('{rule}', r.short));
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user