CR-002: record change request and decisions

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
fireshaper 2026-10-03 14:39:31 -04:00
parent c36d1edf55
commit ea37ce8ced
15 changed files with 159 additions and 2 deletions

View File

@ -611,3 +611,9 @@ Implementation decisions not spelled out in `memory-bank/implementation-plan.md`
- **The first contract of each band is a guaranteed job:** Standard cargo (no skill) to an already-discovered location, never first contact. A new pilot has no skill points (tutorial XP does not reach level 1), so without this a Courier-sized job could still need a skill. The other slots are drawn as before. First contact now applies to 5 of 8 slots, about 6% of contracts, inside the 5–15% the Step 3.9 test expects.
- **Boards list contracts band by band** (small to large), so a new player sees Courier-sized work first.
- **Existing stored boards are unchanged** until their period ends (at most an hour); new boards use the bands.
## CR-002 — Open Markets, Bays as HQs (Phase 10B)
- **Change request CR-002 is stored in `memory-bank/change-requests/`** and inserted as Phase 10B, before Phase 11.
- **Decision numbering:** the CR's new 0.5.27 (Ship delivery) and 0.5.28 (Undiscovered locations) are recorded as **0.5.35** and **0.5.36**, since 27–34 were already in use. Decision 0.5.5 is replaced and the glossary gains "Contract board" and "Deadhead".
- **Error code:** the CR's `location_undiscovered` is the existing `location-undiscovered`.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 861 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@ -0,0 +1,126 @@
# Change Request CR-002 — Open Markets, Bays as HQs
**Project:** Deadhead: Space Freight Tycoon
**Applies to:** a build with Phases 1–10 and CR-001 (Faster Start) complete
**Do this:** as **Phase 10B**, after Phase 10A and before Phase 11
**Related docs:** `implementation-plan.md`, `change-request-faster-start.md`, `game-design-document.md`, `DECISIONS.md`
> **Numbering note (added when implemented):** the plan's §0.5 already used 27 (pilot location storage), 28 (Git hosting) and 29–34 (CR-001). The new decisions below numbered 0.5.27 and 0.5.28 are recorded as **0.5.35 Ship delivery** and **0.5.36 Undiscovered locations**. The error code `location_undiscovered` is the existing `location-undiscovered`.
---
## 1. Why
Contracts are currently only offered at locations where the player has a bay, and repositioning is only allowed to and from bay locations. A ship that delivers to a location without a bay (for example the Moon) is stranded: there is no contract board there, and it cannot reposition home.
The fix follows the American/Euro Truck Simulator model:
- **Every discovered location has a contract board (the freight market).** Any idle ship can pick up work wherever it is, which makes backhaul work.
- **Bays are HQs (like ATS garages).** You need a bay to hire pilots there, to take delivery of newly bought ships there, and to unassign pilots there. Bays no longer control where contracts are available.
- **Discovery still gates expansion.** An undiscovered location has no board until the player delivers there.
## 2. Rules for this change
- All rules in `implementation-plan.md` §0.1 still apply: steps in order, one commit per step, each step's test must pass, `packages/sim` stays pure, all numbers live in `packages/content`.
- **Do not write data migrations for old contract boards.** Resetting the dev and test databases is fine. Schema migrations are still required.
- Update existing tests whose expectations change. Do not delete a test unless §5 says the step is replaced.
- Update `architecture.md` for every schema or API change and `progress.md` after every step.
- Stop for the user's review at the end of Phase 10B.
## 3. Decision changes
Record these in `DECISIONS.md` and in `implementation-plan.md` §0.4 and §0.5.
**Glossary changes (§0.4)**
- **Bay** → A docking bay the player leases at a discovered location. It is an HQ: pilots are hired there, newly bought ships are delivered there, and pilots can be unassigned there. A bay does **not** control where contracts are offered.
- **Contract board** (new) → The freight market at a discovered location. Every discovered location has one per player per board period, whether or not the player has a bay there.
- **Deadhead** (new) → A reposition: a ship flying empty to another location. Fuel only, no payout, no XP.
**Replaced**
- **0.5.5 (Contract boards are stored)** → A board exists for every **discovered location**, per player, per period. It is generated on the first request in a period and stored; later requests in that period return the stored board. Every contract expires at the end of its board period.
- **Step 3.14 rule (reposition only to a bay)** → An idle ship can deadhead from **any** location to **any discovered** location other than its current one, subject to the normal range and landing checks.
**New**
- **0.5.27 Ship delivery.** Buying a ship requires choosing one of the player's bays. The new ship appears there, idle and uncrewed.
- **0.5.28 Undiscovered locations.** Requesting the board of an undiscovered location fails with a `location_undiscovered` error. Deadheading to an undiscovered location is not allowed; only a contract delivery discovers a location.
**Unchanged (confirm, don't modify)**
- **0.5.2 Pilot locations.** Hiring happens at a player bay; unassigning is allowed only at a location with a player bay.
- **CR-001 deal.** The deal still includes the Earth bay.
## 4. Steps — Phase 10B
### Step 10B.1 — Sim: boards at any location
- Change the contract board generator's input from "the bay's location" to "the board's location". No other generation rules change.
- Rename any sim types or functions that say "bay board" to "location board".
- **Test:** The Step 3.9 tests still pass with a location input. Generating a board for the Moon with no bay data supplied anywhere works and is deterministic.
### Step 10B.2 — Sim: deadhead validation
- Reposition validation allows any origin. The destination must be discovered, must differ from the origin, and must pass the range and landing checks. The bay requirement is removed.
- Update the Step 3.14 tests.
- **Test:** A Courier idle at the Moon with no Moon bay can deadhead to Earth. Deadheading to an undiscovered location fails with `location_undiscovered`. Deadheading to the ship's own location fails. Deadheading out of range fails with the out-of-range reason. A deadhead record still has zero payout and zero XP.
### Step 10B.3 — Database: boards keyed by location
- Change `contract_boards` to be keyed by player, location, and board period (the tutorial board keeps its own key).
- Update `architecture.md`.
- **Test:** Migrations run on a fresh database and are a no-op the second time. Two boards for the same player and period at different locations can coexist; a second board for the same player, location, and period is rejected by a unique constraint.
### Step 10B.4 — Server: board endpoint for any discovered location
- Replace "get contract board for a bay" with "get contract board for a location" in the route catalog and server. Any discovered location works; an undiscovered location returns `location_undiscovered`.
- Update the Step 6.9 tests.
- **Test:** The Moon's board is returned for a player with no Moon bay. Two requests in the same period return the same board. Requesting Mars's board before discovery fails with `location_undiscovered`; after a delivery discovers Mars, it succeeds.
### Step 10B.5 — Server: no more stranded ships
- Contract dispatch works from any discovered location where the ship is idle (it already validates that the ship is at the contract's origin; confirm no bay check remains).
- Deadhead dispatch uses the Step 10B.2 rules.
- Update the Step 6.10 and 6.11 tests.
- **Test (the original bug):** A ship delivers Earth→Moon with no Moon bay. After arrival, the Moon's board is available, a Moon→Earth contract can be dispatched with that ship, and it resolves normally. Separately, the same ship can instead deadhead Moon→Earth.
### Step 10B.6 — Server: ship delivery to a bay
- Buying a ship takes a bay id. The ship appears idle and uncrewed at that bay's location. Buying without a bay, or with a bay the player doesn't own, fails.
- Update the Step 6.5 tests.
- **Test:** With bays at Earth and the Moon, buying a Freighter for the Moon bay places it at the Moon. Buying with no bay id fails with a validation error. Buying with another player's bay id fails and changes nothing.
### Step 10B.7 — Client: Contracts screen by location
- The Contracts screen's selector lists all discovered locations instead of bays. Each entry shows a badge with the number of idle ships there.
- Default selection: the location of the most recently arrived idle ship; otherwise Earth.
- Fleet screen: each idle ship gets a "Find work here" action that opens its location's board.
- Update the Step 9.4 tests.
- **Test:** Component test: the selector lists every discovered location and no undiscovered ones; idle-ship badges match state; the default is the most recently arrived idle ship's location; "Find work here" opens the right board.
### Step 10B.8 — Client: deadhead action
- Rename the Fleet screen's "Reposition" action to "Deadhead (fly empty)". It is available for every idle ship. The destination picker lists discovered locations; ones out of range or not landable are shown disabled with the reason. Show fuel cost and trip time for each.
- Update the Step 9.6 tests.
- **Test:** Component test: an idle ship at the Moon with no Moon bay shows the action; the picker excludes undiscovered locations and the ship's current location; an out-of-range destination is disabled with its reason; fuel and time match the sim.
### Step 10B.9 — Client: bays as HQs
- Market screen: "Buy" opens a bay picker ("Deliver to which HQ?"). With only one bay, preselect it.
- Locations screen and map panels: every discovered location has a "View contracts" link. The "Lease bay" action explains what a bay does: "Open an HQ here: hire pilots and take delivery of new ships at this location."
- Update the Step 9.8, 9.9, and 10.3 tests.
- **Test:** Component test: Buy shows the bay picker and sends the chosen bay id; with one bay it is preselected. Every discovered location shows "View contracts", with or without a bay. The lease action shows the HQ explanation.
### Step 10B.10 — Plan amendments and regression
- Apply the amendments in §5 to `implementation-plan.md`, and update `game-design-document.md` §4 and §10 to match §1 of this document.
- Run the full suite.
- **Test:** CI is green. Manual check: on a fresh account after the CR-001 deal, deliver to the Moon, pick up a Moon→Earth contract with the same ship, and deliver it back to Earth without leasing a Moon bay.
## 5. Amendments to `implementation-plan.md`
| Step | Change |
|---|---|
| 0.4, 0.5 | Apply §3 of this document. |
| 3.9 | Input is a location, not a bay (10B.1). |
| 3.14 | Deadhead rules replace reposition-to-bay (10B.2). |
| 5.3 | `contract_boards` keyed by player, location, and period (10B.3). |
| 6.5 | Ship purchase takes a bay id (10B.6). |
| 6.9 | Boards for any discovered location (10B.4). |
| 6.10, 6.11 | No bay checks on dispatch; deadhead rules (10B.5). |
| 9.4 | Selector lists discovered locations (10B.7). |
| 9.6 | "Deadhead (fly empty)" for every idle ship (10B.8). |
| 9.8, 9.9, 10.3 | Bay picker on purchase; "View contracts" everywhere; HQ explanation (10B.9). |
| 12.1 | The simulated player picks up contracts at whatever location its ships are at, and only deadheads when no eligible contract exists there. Add a check: across the whole run, no ship is ever idle with no eligible contract **and** no reachable deadhead destination. |
| 12.5 | After Mars is discovered, also confirm Mars's contract board is available without a Mars bay. |
## 6. Out of scope
Garage-style bay capacity or slot limits, bay upgrades, recurring bay rent, pilots that pick their own jobs from their home bay (ATS-style AI drivers), and anything else in `implementation-plan.md` §0.3.

View File

@ -42,7 +42,9 @@ Random events, reputation, fuel price variation, throttle setting, multi-leg rou
- **Location** — a place a ship can land (planet, moon, station, platform).
- **Discovered** — a location the player has delivered to at least once (Earth and Moon start discovered).
- **Bay** — a docking bay the player rents at a discovered location. Contracts are offered only at bays (plus the tutorial board).
- **Bay** — a docking bay the player leases at a discovered location. It is an HQ: pilots are hired there, newly bought ships are delivered there, and pilots can be unassigned there. A bay does **not** control where contracts are offered. *(Changed by CR-002.)*
- **Contract board** — the freight market at a discovered location. Every discovered location has one per player per board period, whether or not the player has a bay there. *(CR-002.)*
- **Deadhead** — a reposition: a ship flying empty to another location. Fuel only, no payout, no XP. *(CR-002.)*
- **Contract** — a job: cargo of a type and mass, from origin to destination, with a payout and skill requirements.
- **Dispatch** — a ship + pilot sent on a trip, either carrying a contract or repositioning empty.
- **Game time** — the in-world clock, derived from real time × compression factor.
@ -58,7 +60,7 @@ These answer the pre-build review. Log each one in `DECISIONS.md` as it is imple
2. **Pilot locations.** An assigned pilot is wherever their ship is. An unassigned pilot stays where they were unassigned. Pilots travel only by flying a ship. Unassigning is allowed only at a location with a player bay. New hires appear at a player bay the player chooses.
3. **Tutorial movement.** The avatar and loaner move with each tutorial run. The tutorial board starts at the loaner's current location (Earth→Moon or Moon→Earth). The company pays fuel and pilot pay; the player receives only the tutorial share. *(Amended by CR-001: the board has three contracts of different masses (0.5.31), and the loaner is a dedicated content ship (0.5.29).)*
4. **Tutorial end.** *(Replaced by CR-001.)* The tutorial ends when the player accepts the deal (0.5.30). Buying a ship and leasing an Earth bay no longer end it.
5. **Contract boards are stored.** A bay's board is generated on the first request in a period and stored. Later requests in that period return the stored board, so a discovery mid-period does not change it. Every contract expires at the end of its board period; nothing carries over.
5. **Contract boards are stored.** *(Replaced by CR-002.)* A board exists for every **discovered location**, per player, per period. It is generated on the first request in a period and stored; later requests in that period return the stored board. Every contract expires at the end of its board period.
6. **Cargo tier.** Standard is tier 0. A non-Standard contract has a tier from 1 to 5, and that tier is the required level in the cargo's skill.
7. **Long Haul.** A config list of distance cut-offs, one per Long Haul level. The required Long Haul level is the number of cut-offs the route distance exceeds.
8. **Config-driven tuning.** First-contact chance, first-contact multiplier, contract mass range, and Long Haul cut-offs all live in GameConfig. *(Amended after the CR-001 playtest: the single mass range is replaced by per-ship-size mass bands, `contractMassBands`.)*
@ -88,6 +90,8 @@ These answer the pre-build review. Log each one in `DECISIONS.md` as it is imple
32. **Loan** (CR-001). The company has a loan balance. When a dispatch resolves with positive credits (after pilot pay), the lender takes min(balance, credits × repayment share). The player can pay down any amount up to the balance at any time. No interest, no missed payments, no fail state.
33. **Scripted tutorial contracts** (CR-001). Content can define special tutorial contracts keyed to a tutorial run number. A scripted contract replaces one board slot on that run and can carry a custom name, pay multiplier, and a flavor message shown after delivery.
34. **Onboarding goals** (CR-001). A fixed, ordered list of goals in content, each with a condition evaluated from player state and a one-time credit reward the player claims. Goals appear after the tutorial ends.
35. **Ship delivery** (CR-002). Buying a ship requires choosing one of the player's bays. The new ship appears there, idle and uncrewed.
36. **Undiscovered locations** (CR-002). Requesting the board of an undiscovered location fails with a `location-undiscovered` error. Deadheading to an undiscovered location is not allowed; only a contract delivery discovers a location.
---
@ -467,6 +471,12 @@ Steps 10A.1–10A.18 are specified in `memory-bank/change-requests/CR-001-faster
---
## Phase 10B — Open Markets, Bays as HQs (CR-002)
Steps 10B.1–10B.10 are specified in `memory-bank/change-requests/CR-002-open-markets.md` §4, with its §5 amendments to earlier steps. Done after Phase 10A and before Phase 11; stop for review at the end.
---
## Phase 11 — PWA
### Step 11.1 — Installable PWA

View File

@ -129,3 +129,18 @@ Spec: `memory-bank/change-requests/CR-001-faster-start.md`. Decisions recorded a
- [x] HQ tutorial hint when enough runs are done but the loaner is away from Earth; dispatch sheet shows job details and lists every problem with numbers; onboarding test race fixed.
- [x] Contract size bands (user's choice): `contractMassBands` gives every board jobs for each ship size, each band starting with a no-skill Standard job to a discovered place. Smoke test: guest → 4 runs → deal → a Courier job resolves with a loan repayment.
## Phase 10B — Open Markets, Bays as HQs (CR-002)
Spec: `memory-bank/change-requests/CR-002-open-markets.md`. New decisions recorded as plan §0.5.35–0.5.36.
- [ ] Step 10B.1 — Sim: boards at any location
- [ ] Step 10B.2 — Sim: deadhead validation
- [ ] Step 10B.3 — Database: boards keyed by location
- [ ] Step 10B.4 — Server: board endpoint for any discovered location
- [ ] Step 10B.5 — Server: no more stranded ships
- [ ] Step 10B.6 — Server: ship delivery to a bay
- [ ] Step 10B.7 — Client: Contracts screen by location
- [ ] Step 10B.8 — Client: deadhead action
- [ ] Step 10B.9 — Client: bays as HQs
- [ ] Step 10B.10 — Plan amendments and regression