maniator / maniator/verticopolis

[Feature]: [P3] Move-in gate: known approximations (household mean, intra-pass staleness, inspector cause map)

Open
#648 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
TypeScript
Stars
5
Forks
1
PR merge metrics
No merged PRs in 30d

Description

Deferred from the /gds-code-review of the move-in sustainability gate (spec-move-in-sustainability-gate-2026-07-23, branch claude/move-in-sustainability-gate). Three real-but-minor approximations in wouldEvictFreshTenant / the gate, parked for scope. The gate ships correct for the reported churn (noise/far-walk/lobby-far/rent), and the congestion over-block found in the same review was fixed inline (congestion is neutralized in the gate context).

  1. Probe household fixed at mean 3 (Edge Case Hunter, under-block). The probe uses residents: CLASSIC_HOUSEHOLD (3) in both modes. A real Modern condo draws 2-5. The daycareFamilyBonus(dist, residents) scales with household size, so a noisy condo whose survival depends on a daycare halo can pass the gate at 3 yet churn a real 2-person buyer who gets less bonus. Narrow (needs a daycare-offset-dependent spot AND a below-mean buyer). Fix shape: probe the worst-case (smallest) household for the halo term, or fold into the horizon calibration below. Relates to spec §11 move-in-gate-horizon-calibration.

  2. Intra-pass context staleness (Edge Case + Blind, under-block). attemptMoveIns builds satCtx once and reuses it while the same pass seats tenants, so the demandMap/occupancy a later candidate is judged against does not reflect earlier same-pass fills. A later condo can pass the gate on pre-fill coverage and then erode on unmet demand. Deterministic, and the next tick rebuilds the context, so it self-heals within one in-game hour. Fix shape: invalidate/rebuild the gate's demandMap after N move-ins in a pass, or rebuild the context per candidate (perf cost + a golden re-pin).

  3. Inspector wontLeaseText verdict vs cause use two demand maps (Edge Case, legibility). The verdict comes from a fresh computeDemandMap inside the predicate; the cause comes from dominantGripe -> sim.demandMap() (hour-memoized). Within an hour of an occupancy change they can disagree, so the line can show "Won't lease" but drop the specific "too few shops" cause and fall to the generic string. No crash (fallback handles it); the actionable cause is just less specific in a narrow window. Inspector-only. Fix shape: thread one demand map through both the verdict and the cause.

Also noted (not a row): a floor-1 served-check divergence between the engine gate (servedSet.has) and wontLeaseText (isFloorServed, always true on floor 1) is currently unreachable (offices are not founded on floor 1, condos are not placed there); revisit only if a floor-1 rentable becomes possible.

Story: move-in sustainability gate. Notes mirror the backlog row of the same id.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with wouldEvictFreshTenant, the move-in gate, and attemptMoveIns to trace household sizing and the reused satCtx demandMap. Then inspect dominantGripe and sim.demandMap() for the inspector cause path. Done means the three listed approximation cases are addressed without reintroducing the already-fixed congestion behavior, with any needed golden result re-pinned.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
game-dev
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.