Step 10G.11: CR-007 plan amendments, regression and review screenshots

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
fireshaper 2026-10-04 17:27:04 -04:00
parent 66425753c4
commit edbe31593b
8 changed files with 16 additions and 3 deletions

View File

@ -53,7 +53,10 @@ export function PriorityChip({ windowHours }: { windowHours: number }) {
className="rounded-full"
>
<Pill tone="amber" icon="bolt">
Priority · within {real ? realTimeOf(windowHours) : formatWindow(windowHours)}
Priority · within{" "}
<span className="normal-case">
{real ? realTimeOf(windowHours) : formatWindow(windowHours)}
</span>
</Pill>
</button>
);

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View File

@ -82,6 +82,7 @@ Record these in `DECISIONS.md` and in `implementation-plan.md` §0.5.
- If a scripted contract is keyed to the upcoming run number, it replaces the medium slot.
- Update the Step 3.10 tests to match.
- **Test:** The board has exactly three contracts with three different masses, all within Company Courier capacity. Same inputs give an identical board. With two runs completed, the "Unmarked crates" contract appears at double pay; with any other count, it does not. The light contract gives more XP per real minute than the full one, and the full one gives more credits per real minute than the light one. The sum of the four slowest possible tutorial trip times is under 6 real minutes.
- **Amended by CR-007:** Tutorial contracts carry named Standard goods made at the loaner's location and wanted at the other end (never Priority); masses stay at the three tiers (Step 10G.5).
### Step 10A.4 — Sim: loan repayment
- Add a pure function that splits a credit amount into repayment and net, given the loan balance and repayment share.

View File

@ -61,7 +61,7 @@ These answer the pre-build review. Log each one in `DECISIONS.md` as it is imple
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.** *(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.
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. *Amended by 0.5.55 (CR-007): High-Value and Dangerous tiers come from the good.*
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`.)*
9. **Game epoch.** Two fields: a real start timestamp and the in-game ephemeris date it maps to. The clock is global for all players.
@ -72,7 +72,7 @@ These answer the pre-build review. Log each one in `DECISIONS.md` as it is imple
14. **Ship names** are generated from the world seed. No renaming.
15. **Bays** have no ship limit.
16. **Tutorial purchases.** *(Replaced by CR-001.)* During the tutorial, buying ships, leasing bays and hiring pilots are blocked with a `tutorial-active` error.
17. **Cargo fallback.** If no cargo type is both produced at the origin and demanded at the destination, use Standard.
17. **Cargo fallback.** If no cargo type is both produced at the origin and demanded at the destination, use Standard. *Amended by 0.5.54 (CR-007): the class fallback uses each location's `cargoClassMix`; the good then falls back to a Standard good on the route, else any Standard good made at the origin.*
18. **Testable clock.** The server reads time through an injectable clock. Tests call job handlers directly; E2E tests use a test-only clock-offset endpoint that does not exist in production.
19. **Summaries.** Dispatches have an acknowledged-at column; resolved dispatches without one form the "while you were away" summary.
20. **Same domain.** In production, the client and API share one domain, with the API under `/api`, so the session cookie is first-party (iOS Safari blocks cross-site cookies).
@ -164,6 +164,7 @@ These answer the pre-build review. Log each one in `DECISIONS.md` as it is imple
- Add data for Earth, Moon, Mars, Ceres Station, and Jupiter Cloud Platform following the destinations table in the GDD.
- Earth and Moon start discovered. Earth is atmospheric with the highest launch multiplier; Moon is vacuum with a low multiplier; Mars is atmospheric; Ceres is a belt station (vacuum); Jupiter Cloud Platform is a cloud platform requiring atmospheric landing.
- **Test:** A test loads all locations through the schema without errors, asserts exactly five locations, asserts exactly Earth and Moon start discovered, and asserts every cargo id referenced in produces/demands exists.
- **Amended by CR-007:** `produces`/`demands` list good ids (derived from the goods catalog); the old class lists are kept as `cargoClassMix`, and each location has `shippers` (Step 10G.1).
### Step 2.3 — Add the three ship models
- Courier: fastest, smallest hold, short range, atmospheric, lowest price.
@ -177,6 +178,7 @@ These answer the pre-build review. Log each one in `DECISIONS.md` as it is imple
- Cargo types: Standard (no skill), Heavy (Heavy Cargo skill), High-Value (Expensive Cargo skill), Dangerous (Dangerous Cargo skill). Non-standard types pay more per tonne-distance.
- Skills: Long Haul, Heavy Cargo, Expensive Cargo, Dangerous Cargo, each max level 5.
- **Test:** A test validates all entries, asserts every cargo type's required skill exists, and asserts each non-standard cargo pays more than Standard.
- **Amended by CR-007:** Cargo types are the four cargo classes; a goods catalog (`data/goods.ts`) adds named goods with class, mass range, pay multiplier, tier (High-Value and Dangerous), Priority eligibility and where they're made and wanted (Step 10G.1).
### Step 2.5 — Add the default game config
- Set time compression to 60 (1 real minute = 1 game hour).
@ -226,6 +228,7 @@ These answer the pre-build review. Log each one in `DECISIONS.md` as it is imple
- Define a Contract shape: id, origin, destination, cargo type, tier, mass, payout, required skill and level, required Long Haul level, offered-at time, expires-at time (end of its board period), first-contact flag.
- Add a payout function: base pay per tonne per million km × tier multiplier × mass × distance, times the first-contact multiplier when flagged. Payout is fixed at offer time using the distance at that moment (decision 0.5.11).
- **Test:** Payout scales linearly with mass and distance. Dangerous cargo pays more than Standard for identical mass and route. A first-contact contract pays more than an otherwise identical normal contract.
- **Amended by CR-007:** Contracts carry `goodId`, `shipper`, `priority` and `deliveryWindowGameHours`; payout includes the good's pay multiplier and the Priority bonus (Step 10G.2).
### Step 3.9 — Contract board generation
- Add a function that generates a bay's contract board from: the bay's location, the set of discovered locations, the board period index (real time ÷ board period), and the player's world seed.
@ -234,6 +237,7 @@ These answer the pre-build review. Log each one in `DECISIONS.md` as it is imple
- **Amended after the CR-001 playtest:** contract mass comes from per-ship-size bands (`contractMassBands`, e.g. 3 × 5–20 t, 3 × 21–100 t, 2 × 101–400 t), and the first contract in each band is Standard cargo to a discovered location, so every ship size always has a job a new pilot can fly.
- **Amended by CR-002:** Input is a location, not a bay: boards are generated for any discovered location (Step 10B.1).
- **Amended by CR-006:** `BoardInput` takes the player's fleet (ship models and pilot skills); bands the fleet can't carry shrink to a preview and flyable bands are mostly jobs the fleet can take (decision 0.5.52, Step 10F.3).
- **Amended by CR-007:** Class selection unchanged; each contract then gets a good (mass from its band, inside the good's range when they overlap), maybe Priority with a window, and a shipper (Step 10G.3).
### Step 3.10 — Tutorial contract board
- Add a separate generator for the tutorial "company board": Earth↔Moon only, Standard cargo only, payout reduced by the tutorial payout share, always flown with the company loaner Courier. Contracts start at the loaner's current location: Earth→Moon when it is at Earth, Moon→Earth when it is at the Moon.
@ -249,6 +253,7 @@ These answer the pre-build review. Log each one in `DECISIONS.md` as it is imple
- Return "valid" or the first failing reason.
- **Test:** One test per failure reason, each constructing a scenario that triggers exactly that reason. One test for a fully valid dispatch.
- **Amended by CR-004:** Validation (contract and deadhead) gains `pilot-resting`, checked before the other pilot checks (Step 10D.3).
- **Amended by CR-007:** Validation gains `too-slow`: a Priority contract's trip must fit its delivery window (Step 10G.4).
### Step 3.13 — Dispatch record creation
- Add a function that turns a validated dispatch into a Dispatch record: id, ship, pilot, contract (or none for reposition), origin, destination, departure real time, arrival real time (computed from travel time and clock conversion), fuel cost, expected payout, seed.
@ -460,12 +465,14 @@ These answer the pre-build review. Log each one in `DECISIONS.md` as it is imple
- **Test:** Component test switches bays and shows the right board. A first-contact contract displays its badge.
- **Amended by CR-002:** The selector lists every discovered location with an idle-ship badge, defaulting to the most recently arrived idle ship's location, else Earth; Fleet gets "Find work here" (Step 10B.7).
- **Amended by CR-006:** A contract's mass is highlighted, with a "Too heavy" tag, when none of the player's ships at the location (or in the fleet, when none are there) can carry it (decision 0.5.53, Step 10F.1).
- **Amended by CR-007:** Cards headline the good with class/tier, Priority and Too slow chips, and show shipper · mass · distance (Step 10G.8).
### Step 9.5 — Dispatch flow
- Selecting a contract opens a dispatch sheet: choose an eligible ship+pilot pair at the origin. Show trip time, fuel cost, net profit, and ETA in both game time and real time. Ineligible pairs are listed but disabled with the reason shown (out of range, can't land, skill too low, too heavy).
- Confirm sends the dispatch; on error, show the server's message.
- **Test:** Component test: an eligible pair shows correct numbers from the sim; an ineligible pair shows the correct reason; confirming calls dispatch; a server error message is displayed.
- **Amended by CR-004:** The dispatch sheet disables resting pilots with a countdown and shows duty after the trip, warning "Will need rest on arrival" (Step 10D.7).
- **Amended by CR-007:** For a Priority contract each pair shows its trip against the window; too-slow pairs are disabled with the numbers (Step 10G.9).
### Step 9.6 — Fleet screen
- List all ships: name, model, location or route, assigned pilot, and for in-flight ships a progress bar and countdown. Idle ships at a bay location have a "Reposition" action to another bay location.
@ -578,6 +585,7 @@ Steps 10G.1–10G.11 are specified in `memory-bank/change-requests/CR-007-cargo-
- **Amended by CR-001:** Change the thresholds to: deal accepted under 10 real minutes; first pilot hired between 30 and 45 minutes; first discovery under 90 minutes; and a new check that after the deal the player always either has a ship in flight or can afford fuel for at least one contract. The simulated player accepts the deal as soon as it is available, takes the highest credits-per-minute contract, and pays down the loan only through automatic repayment. Adjust content values, not thresholds.
- **Amended by CR-002:** 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.
- **Amended by CR-004:** The simulated player follows rest rules: it rests a pilot when no eligible contract exists at its location and deadheading isn't better. Re-check all CR-001 timing targets with rest in place; adjust content values, not thresholds. Add a check that no pilot is ever dispatched while resting.
- **Amended by CR-007:** The simulated player considers Priority contracts and skips ones its ships are too slow for. Re-check all timing targets; adjust content values, not thresholds.
### Step 12.2 — Revisit the tutorial economy test
- Replace the placeholder average in the Step 2.5 test with the average tutorial payout measured by the balance script.

View File

@ -212,3 +212,4 @@ Spec: `memory-bank/change-requests/CR-007-cargo-goods.md` (supplied as "CR-005 /
- [x] **Step 10G.8 — Client: contract card redesign.** New `components/Goods.tsx`: `goodName` (a Priority good may use its `priorityName`, e.g. Emergency Parts), `ClassChip` ("High-Value · T1", toned by class), `PriorityChip` ("Priority · within 5h" in game hours; tap switches to real time, hover shows both), `tooSlowForAll` (idle ships at the origin exist and none makes the window, via sim `contractTripGameHours`), `formatWindow`, `realTimeOf`. Location board cards, top to bottom: route and payout; the good as an `h3` headline with class, Priority, First contact, Too heavy and Too slow chips; route strip; shipper · mass · distance; requirement and expiry with Dispatch. Tutorial cards show the good's name instead of the class. Tests: `contract-card.test.tsx` (good, class/tier chip, shipper, mass, requirement; Priority chip in game hours and real time on tap with the Priority name; Too slow with only a Bulk Hauler idle); `location-boards.test.tsx` updated to the new card.
- [x] **Step 10G.9 — Client: Priority in the dispatch sheet.** `explainProblems` adds "Too slow — 7h vs 5h window" (sim `contractTripGameHours` vs the window) so a slow pair is disabled with the numbers; `PairOption.priority` carries each pair's trip and the window, and eligible pairs show "Priority: 2.1h trip, 1.4h to spare in the 3.5h window". The sheet's job details now start with the good and shipper ("Mail & Parcels for Pacific Orbital Logistics · Standard · 6 t …") and Priority jobs show the window chip. Test: `dispatch-priority.test.tsx` (Courier enabled with its margin, Bulk Hauler disabled with "Too slow — …", numbers from the sim).
- [x] **Step 10G.10 — Client: goods in summaries.** Each delivery in "While you were away" says "Delivered 6 t Medical Supplies for Meridian Health to the Moon" (from the summary's `goodId`, `massTonnes`, `shipper`; new `toLocation` gives "to the Moon" / "to Mars"); deadheads keep their fuel line. Test: `away-summary.test.tsx` (the seeded delivery line; a deadhead shows no "Delivered").
- [x] **Step 10G.11 — Plan amendments and regression.** CR-007 §7 amendments added to plan §0.5.6 and §0.5.17 and steps 2.2, 2.4, 3.8, 3.9, 3.12, 9.4, 9.5 and 12.1, and to CR-001 Step 10A.3. Typecheck, lint, full suite with coverage (108 files, 753 tests; sim lines 100 %) and the web build are green. **Manual check:** a fresh owner after the deal with one Courier at Earth: every contract names a good and an Earth shipper (Mail & Parcels, Consumer Goods, Packaged Food; bulk Packaged Food lots flagged Too heavy), and a Priority job appeared on the first board (Mail & Parcels, 7.7 t, window 4.3 h; the Courier makes it in 2.3 h with 2.1 h to spare). The Priority chip keeps its unit in normal case ("within 4.3h"). Screenshots: `docs/screenshots/10g11-goods-contracts-solo-{desktop,phone}.png`, `10g11-priority-dispatch-solo-{desktop,phone}.png`. **Balance notes for Phase 12:** with "the band wins", bulk lots make Packaged Food and Electronics the usual big-band goods; shippers are random per origin, so e.g. Hollis & Crane Consumer can ship Mail. **Phase 10G complete — stopped for review.**