Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions docs/DECISION-LOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,43 @@ consequences, owner, and conditions to revisit. Newest first.

---

### 2026-07-30 · D-029 · Menu-responsive demand rewrite: distinct regimes achieved; universal-generalist gate borderline (economic root cause)
- **Status:** provisional · **Owner:** Builder → owners · **Follows** the PR #5 adjudication (D-028's Fail/Rewrite,
refined: the fix is a headless demand-model rewrite, not M1). Branch `rewrite/m0-menu-responsive-demand`.
- **Decision/finding:** Replaced menu-independent arrival composition with a **menu-responsive consideration
model** (`DemandModel.Capture`): per-segment depth + positioning focus + occasion variety + a representative
price-position gate set BOTH arrival volume and composition; purchase (`PickBest`) stays separate. This makes
the per-market frontiers **distinct regimes** — value/throughput wins the value lunch, premium wins the
enthusiast evening, mixed wins social — which the old fixed-composition model could not. Manipulation-resistant
(filler/never-ordered/anchor bounded), legible, deterministic; forecast reuses the same `Capture`.
- **Residual (honest):** the strict "no plan within 10% of the frontier in every market" gate is **borderline-
missed on held-out seeds** — a premium-anchored generalist's worst-market regret is ~6–13% (median ~9%, sweep
over 4 bases), dominator on 2/3 fresh bases. **Decisive cause (economic, not demand):** consideration is
market-name-agnostic, so a premium menu serves the same fraction of the premium slice in every market, and
premium multi-course checks (~5× a value cover) make that profitable everywhere. Regret is fixed by (pool mix)
× (per-cover economics), both outside the demand model → no composition candidate (C1–C4) can close it. This is
the concrete answer to §22's "does the product need an economic rebalance / broader redesign": **yes, the
residual needs an economic rebalance or the excluded systems (reputation/repeat-visits), NOT abandoning the
demand model** (which is correct and kept).
- **One fixture change:** lunch pool 65→82% value + 120→150 arrivals, to match its stated "value-heavy,
high-volume" identity (achieves 3 of 4 gates). Pushing further (~95% value) to force the 4th gate is
gate-chasing and was declined. Flagged for owner scrutiny.
- **Consequence / gate:** `Verdict: Conditional-Pass / Action: Continue` (open PR for independent review + owner
decision). Supersedes D-028's "needs M1" framing: the demand rewrite (headless, in scope) delivered most of the
property; the remaining residual is economic. Goldens re-baselined (see D-030). Do not merge / no human tests /
no M1. Full report: `reports/m0/M0-DEMAND-REWRITE-REPORT.md`; iteration evidence:
`reports/m0/demand-rewrite/candidate-1.md`.

### 2026-07-30 · D-030 · Goldens re-baselined for the demand rewrite; Focused Value strategy rebuilt
- **Status:** locked · **Owner:** Builder
- **Decision:** The menu-responsive demand changes (arrival volume/composition, MakeParty sampling the captured
mix, the value-heavy lunch pool) and the rebuilt **Focused Value** strategy (a full-throughput value operation
so a value plan wins the value-heavy lunch) intentionally change the simulated order stream, so the three
golden checksums were re-baselined: Focused Value/lunch `0xFB04479B19656E6B`, Premium Craft/enthusiast
`0x198E44A139793975`, Balanced Competent/social `0x6CBD8F76B46A51E1`. Prior (D-027): `0xC814AFAA4D8752DE` /
`0x4D834261A7A6813E` / `0x2D2C5DCA4431A5EF`. Also recalibrated the causal report's weak-demand attraction floor
(70%→35% of pool) for the new demand regime (does not affect the checksum; cause strings are not hashed).

### 2026-07-29 · D-028 · CORRECTION to D-025: High B is NOT resolved — a mixed dominator remains (Fail/Rewrite)
- **Status:** locked · **Owner:** Builder · **Supersedes the "no dominator" result in [[D-025]].**
- **Decision/finding:** After the affordability fix, a **strengthened** harness search (multi-start hill-climb,
Expand Down
116 changes: 116 additions & 0 deletions docs/design/M0-DEMAND-REWRITE-CONTRACT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# M0 Demand-Model Rewrite Contract (design lock)

**Status:** Design-locked, implementation NOT complete. Branch `rewrite/m0-menu-responsive-demand` off PR #5 head
`7bd8060`. This replaces one failed load-bearing M0 assumption. It is not M0.5, M1, visual, reputation,
repeat-visit, or a scope expansion.

## 1. Product question
Can menu, pricing, staffing, and capacity decisions create multiple understandable and viable restaurant
strategies **by influencing both customer attraction and service outcomes**, with visible consequences that
make players want to revise their plan and run another service?

## 2. Failed prior assumption (preserved, not euphemized)
> Customer arrival composition can remain fixed independently of the restaurant's menu and prices while still
> producing meaningful market-specific strategies.

Independently adjudicated **Fail/Rewrite** (PR #5): a fixed mixed value-chassis + premium-anchor plan is
near-optimal in all three markets because `MakeParty` samples each party's segment from the fixed
`SegmentMixBp` and the per-segment `ConversionBp` signal (`segConv`) is computed then discarded. The premium
anchor skims the always-present high-budget minority at no attraction cost. See `M0-CORRECTION-3-REPORT.md`
and the PR #5 adjudication comment.

## 3. New assumption under test (must be able to fail)
A deterministic, single-service, headless model of **restaurant consideration** can create credible
positioning tradeoffs **without** repeat visits, reputation, marketing, or a living city.

## 4-8. Model sequence (conceptually distinct stages)
```
Potential market pool (SegmentMixBp = pool, NOT arrivals)
→ RestaurantOffer derived from menu/prices/expected operation
→ per-segment Consideration (offer vs segment budget/occasion/quality/pace)
→ Captured demand (pool × consideration) — sets arrival volume AND composition
→ seeded Arrival realization
→ in-restaurant purchase (order/substitute/decline — UNCHANGED: WTP + affordability)
→ service → outcome
```
`RestaurantOffer` is a small explicit vector (e.g. ExpectedMealCost, ValueAvailability, PremiumAvailability,
ExpectedQuality, ExpectedPace, MenuBreadth) derived from actual choices — never a player-picked label, never
inferred from max price alone (must resist filler-dish manipulation; weight by likely orders). Purchase stays
separate: a customer may choose the restaurant and still reject an overpriced dish.

## 9-10. Forecast & causal relationships
Forecast exposes the funnel: potential → captured → arrivals → completed covers → revenue → contribution, and
names attraction risks (weak value appeal, premium demand too small, high expected meal cost, poor occasion
fit, capacity shortfalls) in plain language (no raw utility formulas). Causal report distinguishes
**attraction** failures (never considered / wrong segment / price-position deterrence) from **conversion**
failures (rejected prices, no suitable dish) from **service** failures (seating/kitchen/FOH/execution). It
must not blame operations for customers who never intended to visit.

## 11-13. Numerics / RNG / scope
Integer & fixed-point only, `FixedMath.MulDivRound`; named seeded RNG streams (no wall-clock, no
`Math.random`); smooth consideration (no cliffs), permits low and high consideration, segment-varying,
name-agnostic (no market-name / strategy-fixture branch). Preserve all existing invariants (accounting,
determinism, immutable forecast, affordability, WTP, capacity, patience, execution, attribution, FIFO, labor,
guards). Replace only: fixed arrival composition, demand generation that ignores the offer, forecast demand
assumptions, exogenous-demand reports, search evaluation that conflates attraction with conversion.

## 14-15. Non-goals (hard)
Repeat visits, reputation, reviews, critics, marketing, loyalty, word-of-mouth, CLV, neighborhood/city,
competitors, travel, reservations, delivery, inventory/suppliers/spoilage, new recipes/markets/segments,
hiring, graphics/Godot/pathfinding/save/multi-restaurant/managers/campaign/audio/assets/multiplayer/mod.
No content-volume increase.

## 16-17. Strategy-integrity & positioning gates (pass criteria)
- **No fixed complete plan** within **10%** of the best discovered held-out result in all three markets
(report 5/10/15/20% sensitivity). Value/throughput plan within 5% of best lunch; premium plan within 5% of
best enthusiast; lunch vs enthusiast optima differ on ≥2 of {menu, price regime, staffing, capacity,
captured mix, bottleneck}. **Mixed menus remain viable** (esp. social) — the deterrent must be occasion-fit
opportunity cost, NOT a mixed-menu penalty, breadth tax, cuisine-purity score, name branch, or hard ban.
- Demand gates: menu/prices materially shift arrival composition; a premium anchor changes attraction not
only order mix; a broad menu does not capture every segment at full strength; filler/never-ordered dishes
have bounded influence.
- Forecast gates: ≥85% overall / ≥75% per-market & per-family directional agreement (price, positioning, menu,
seat, kitchen, FOH); audited price & seat directions correct; positive ranking correlation each market.

## 18. Required owner decision
After the build: does the menu-responsive demand model establish the strategy-integrity property (Continue to
independent technical re-review), or does it hit a §7 fail condition (Rewrite/Abandon the demand approach)?

---

## Implementation status & the load-bearing risk (honest)
**IMPLEMENTED (Candidate 1, "relevant-option depth"). Verdict: Conditional-Pass / Continue.** See
`reports/m0/M0-DEMAND-REWRITE-REPORT.md` (§A–H) and `reports/m0/demand-rewrite/candidate-1.md` (iteration log).
`DemandModel.Capture` now sets arrival volume AND composition from per-segment depth + positioning focus +
occasion variety + a representative price-position gate; purchase stays separate. The per-market frontiers are
now **distinct regimes** (value wins lunch, premium wins enthusiast, mixed wins social); manipulation-resistant,
legible, deterministic; 139 tests green. **The strict universal-generalist gate (§16 below) is borderline-missed
on held-out seeds** (premium-anchored generalist worst-market regret ~6–13%, median ~9%; dominator on 2/3 fresh
bases). Decisive cause is ECONOMIC (market-agnostic consideration ⟹ a premium menu serves the same fraction of
every market's premium slice, and premium multi-course checks earn ~5× a value cover), so no composition
candidate can close it; it needs an economic rebalance or the excluded systems. One principled fixture change was
made (lunch pool 65→82% value, matching its "value-heavy" identity); pushing to ~95% to force the gate was
declined as gate-chasing. **Owner decision (§18) required.**

The failed v1 prototype (below) is preserved as evidence:
**v1 (reverted):** `RestaurantOffer` = average main price; consideration = price-level fit × identity fit;
captured mix + a mix-weighted `drawBp` volume scalar. Measured on held-out seeds it **FAILED both ways**: the
mixed dominator still won all three markets (0% regret), and focused value/premium plans got *weaker* (the
mix-weighted `drawBp` penalized focused menus, and price-level fit alone does not deter the minority skim). The
surviving Candidate 1 fixes this by (a) driving composition from undistorted per-segment ratios, not a
mix-weighted scalar, and (b) using a mean-price position gate + occasion-specific depth rather than price alone.

**Lesson / critical uncertainty (per §33):** consideration based on price-fit + best-dish-fit is *necessary
but insufficient* — a mixed menu genuinely fits everyone somewhat, so a naive model lets it attract everyone
(reproducing the exploit) OR, if volume is mix-weighted, it wrongly punishes focused menus. The load-bearing
design is the **coupled second piece**: an occasion/positioning-coherence term where a market's *occasion*
(derived from the pool's own parameters — budget distribution, patience, not the market name) rewards a
restaurant that is a *clear fit* for that occasion and gives a muddled cheap+premium offer only a partial draw
from each pole, so a **focused** restaurant captures more of its pool than the mixed one — while a mixed
restaurant still wins the market whose occasion *is* "moderate/varied" (social). Calibrating this to (a) drop
the mixed generalist below the 10% band, (b) keep mixed viable in social, (c) not punish mixed arbitrarily, is
the crux and the likely stop point if the model cannot be made to work.

**Estimate:** ~24-40 focused hours across the six workstreams (offer, consideration/arrival, forecast funnel,
causal attraction layer, search, docs). Critical path = consideration/arrival model + calibration (highest
uncertainty). This exceeds a single builder session; the branch, contract, and v1 evidence are the handoff.
64 changes: 32 additions & 32 deletions reports/balance/distribution.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
# M0 Balance / Distribution Report

Generated by `RestaurantSim.Harness`. Seeds per cell: **200** (base seed 700000).
Generated by `RestaurantSim.Harness`. Seeds per cell: **80** (base seed 700000).
Contribution is per single service in integer cents rendered as dollars. "win%" = share of seeds
where this strategy had the highest contribution in that scenario (same seed compared across strategies).

## Neighborhood Lunch Rush (`lunch-rush`)

_Value-heavy, high-volume, price-sensitive, small parties, early peak. Rewards fast throughput and lean value menus._
_Value-heavy, high-volume, price-sensitive, small parties, early peak. Rewards fast throughput and lean value menus. Pool is strongly value-dominated to match its stated identity: under menu-responsive demand a market's winner is set by its customer pool, so a genuine value-lunch occasion must be mostly value diners (few premium diners to skim)._

| Strategy | median contrib | p10 | p90 | loss% | avg covers | avg sat | avg ticket | win% |
|---|--:|--:|--:|--:|--:|--:|--:|--:|
| Focused Value | $838.65 | $404.50 | $1127.80 | 0% | 93 | 521 | 16m | 68% |
| Premium Craft | $421.64 | -$76.56 | $865.04 | 14% | 26 | 748 | 15m | 16% |
| Broad Menu | $219.00 | -$421.00 | $931.50 | 38% | 83 | 543 | 19m | 15% |
| Overcapacity | -$635.50 | -$843.50 | -$476.50 | 100% | 22 | 524 | 20m | 0% |
| Understaffed | -$476.00 | -$558.00 | -$376.50 | 100% | 12 | 497 | 22m | 0% |
| Balanced Competent | -$36.00 | -$445.50 | $483.50 | 53% | 64 | 554 | 20m | 0% |
| Overpriced Weak Execution | -$78.60 | -$377.00 | $323.90 | 62% | 10 | 435 | 25m | 0% |
| Station Bottleneck | -$495.50 | -$634.50 | -$371.00 | 100% | 15 | 578 | 18m | 0% |
| Intentionally Bad | -$140.00 | -$284.50 | -$7.50 | 91% | 7 | 568 | 19m | 0% |
| Focused Value | $1682.50 | $1480.00 | $1892.00 | 0% | 170 | 604 | 11m | 93% |
| Premium Craft | $1064.12 | $635.46 | $1549.56 | 1% | 42 | 719 | 17m | 6% |
| Broad Menu | $393.00 | -$121.50 | $933.50 | 15% | 79 | 580 | 19m | 0% |
| Overcapacity | -$572.00 | -$756.00 | -$424.50 | 100% | 23 | 538 | 19m | 0% |
| Understaffed | -$402.00 | -$529.00 | -$261.50 | 100% | 14 | 512 | 21m | 0% |
| Balanced Competent | -$20.50 | -$429.50 | $388.00 | 53% | 64 | 576 | 19m | 0% |
| Overpriced Weak Execution | -$245.90 | -$522.50 | $219.20 | 76% | 10 | 404 | 26m | 0% |
| Station Bottleneck | -$316.00 | -$473.50 | -$50.50 | 93% | 19 | 603 | 19m | 0% |
| Intentionally Bad | -$118.00 | -$237.50 | $32.00 | 80% | 9 | 548 | 21m | 0% |

**Winner:** Focused Value · **profitable strategies (median >= +$150):** 3

Expand All @@ -28,40 +28,40 @@ _Mid-budget social diners in groups, multi-course, moderate patience. Rewards a

| Strategy | median contrib | p10 | p90 | loss% | avg covers | avg sat | avg ticket | win% |
|---|--:|--:|--:|--:|--:|--:|--:|--:|
| Focused Value | $1118.20 | $615.75 | $1501.05 | 0% | 102 | 579 | 17m | 14% |
| Premium Craft | $1963.26 | $608.50 | $3024.90 | 2% | 75 | 612 | 24m | 72% |
| Broad Menu | $786.50 | -$189.00 | $1620.50 | 13% | 94 | 560 | 24m | 8% |
| Overcapacity | -$289.00 | -$683.00 | $84.00 | 84% | 36 | 568 | 21m | 0% |
| Understaffed | -$393.50 | -$556.00 | -$198.00 | 99% | 17 | 510 | 25m | 0% |
| Balanced Competent | $688.00 | -$76.00 | $1568.50 | 11% | 86 | 598 | 22m | 5% |
| Overpriced Weak Execution | -$646.50 | -$900.10 | -$298.20 | 98% | 9 | 397 | 28m | 0% |
| Station Bottleneck | -$471.00 | -$679.00 | -$175.00 | 97% | 20 | 611 | 20m | 0% |
| Intentionally Bad | -$204.50 | -$393.00 | $65.50 | 84% | 11 | 530 | 24m | 0% |

**Winner:** Premium Craft · **profitable strategies (median >= +$150):** 4
| Focused Value | $1816.50 | $1461.00 | $2195.00 | 0% | 153 | 722 | 10m | 60% |
| Premium Craft | $1412.94 | $274.46 | $2633.06 | 6% | 70 | 590 | 24m | 36% |
| Broad Menu | $241.50 | -$449.00 | $1153.00 | 30% | 89 | 529 | 25m | 2% |
| Overcapacity | -$578.50 | -$882.50 | -$211.00 | 98% | 33 | 573 | 21m | 0% |
| Understaffed | -$421.00 | -$553.00 | -$199.00 | 100% | 17 | 517 | 25m | 0% |
| Balanced Competent | $135.00 | -$419.50 | $943.00 | 36% | 75 | 597 | 22m | 1% |
| Overpriced Weak Execution | -$719.40 | -$986.50 | -$438.50 | 98% | 9 | 402 | 28m | 0% |
| Station Bottleneck | -$521.00 | -$740.00 | -$209.50 | 100% | 20 | 617 | 21m | 0% |
| Intentionally Bad | -$237.50 | -$381.00 | $10.50 | 87% | 11 | 519 | 24m | 0% |

**Winner:** Focused Value · **profitable strategies (median >= +$150):** 3

## Destination Enthusiast Evening (`enthusiast-evening`)

_High-budget enthusiasts, lower volume, high quality expectations, patient. Rewards premium craft and skilled execution._

| Strategy | median contrib | p10 | p90 | loss% | avg covers | avg sat | avg ticket | win% |
|---|--:|--:|--:|--:|--:|--:|--:|--:|
| Focused Value | $667.70 | $400.00 | $927.50 | 0% | 63 | 631 | 13m | 0% |
| Premium Craft | $2471.16 | $1379.50 | $3127.42 | 0% | 75 | 595 | 24m | 83% |
| Broad Menu | $1448.50 | $611.50 | $2061.50 | 1% | 89 | 565 | 24m | 9% |
| Overcapacity | $399.00 | -$129.00 | $1102.50 | 15% | 51 | 556 | 22m | 0% |
| Understaffed | -$208.00 | -$407.00 | $27.00 | 85% | 22 | 464 | 27m | 0% |
| Balanced Competent | $1256.00 | $800.00 | $1655.00 | 0% | 79 | 634 | 18m | 7% |
| Overpriced Weak Execution | -$585.80 | -$878.30 | -$196.30 | 97% | 10 | 335 | 29m | 0% |
| Station Bottleneck | -$154.00 | -$499.50 | $207.00 | 70% | 26 | 575 | 22m | 0% |
| Intentionally Bad | -$170.50 | -$345.50 | $108.50 | 79% | 12 | 469 | 25m | 0% |
| Focused Value | $394.50 | $95.50 | $691.50 | 2% | 71 | 716 | 10m | 0% |
| Premium Craft | $2313.06 | $845.32 | $3445.88 | 0% | 76 | 583 | 25m | 76% |
| Broad Menu | $1183.00 | -$21.00 | $2072.00 | 10% | 91 | 549 | 25m | 6% |
| Overcapacity | $348.00 | -$106.00 | $998.50 | 13% | 50 | 575 | 21m | 0% |
| Understaffed | -$188.50 | -$405.50 | $60.00 | 86% | 24 | 480 | 27m | 0% |
| Balanced Competent | $1359.00 | $866.50 | $1695.00 | 0% | 83 | 654 | 18m | 17% |
| Overpriced Weak Execution | -$613.50 | -$903.80 | -$248.80 | 93% | 10 | 344 | 28m | 0% |
| Station Bottleneck | -$153.00 | -$518.00 | $231.00 | 68% | 26 | 588 | 22m | 0% |
| Intentionally Bad | -$166.00 | -$334.00 | $151.50 | 73% | 13 | 468 | 25m | 0% |

**Winner:** Premium Craft · **profitable strategies (median >= +$150):** 5

## Dominance check

- **lunch-rush** best strategy: `Focused Value`
- **social-dinner** best strategy: `Premium Craft`
- **social-dinner** best strategy: `Focused Value`
- **enthusiast-evening** best strategy: `Premium Craft`

Distinct winning strategies across scenarios: **2** of 3. No single strategy wins across all markets: context changes the best plan. ✅
Loading