diff --git a/DECISIONS.md b/DECISIONS.md index 69bfb4b..36a766b 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -818,3 +818,8 @@ Implementation decisions not spelled out in `memory-bank/implementation-plan.md` - **The summary gives the wake time as the device's local clock time** (like the dispatch sheet's real ETA), since the player reads it on returning; HQ gives a live countdown instead. - **The HQ rest card is always shown after the tutorial**, with "Everyone is ready to fly." when nobody rests, so the player learns the mechanic exists before it first bites. + +## Step 10D.10 + +- **The CR's manual check was scripted** against a live dev server with the test clock (scratchpad `cr004-smoke.mjs`): mandatory rest after the sixth Earth↔Moon trip, `pilot-resting` while resting, and a different board on waking. The user's own check on a device is still the review gate. +- **Observed for Phase 12 balance (not changed here):** a board's only guaranteed Courier job is used by the first trip from that location in a period, so later trips in the same period are usually deadheads. Resting, which wakes the pilot to a new board, is now the natural answer, which is what the CR intends; the size of that effect is for the balance pass. diff --git a/memory-bank/implementation-plan.md b/memory-bank/implementation-plan.md index e56b55f..b7b035f 100644 --- a/memory-bank/implementation-plan.md +++ b/memory-bank/implementation-plan.md @@ -145,6 +145,7 @@ These answer the pre-build review. Log each one in `DECISIONS.md` as it is imple - Skill fields: id, display name, max level, description. - GameConfig fields: time compression factor; game epoch as two fields (real start timestamp and the in-game ephemeris date it maps to); starting credits; tutorial payout share; contract board size; contract board period (real minutes — contracts expire at the end of their period); first-contact chance; first-contact payout multiplier; contract mass range; Long Haul distance cut-offs (one per level); XP per delivery formula inputs; XP needed per pilot level; skill points per level; hire cost per pilot; pilot pay per delivery (flat fee). - **Test:** Unit tests confirm each schema accepts a valid example and rejects an object missing a required field. +- **Amended by CR-004:** GameConfig gains `dutyLimitGameHours`, `longHaulDutyBonusGameHours` and `restGameHours` (Step 10D.1). ### Step 2.2 — Add the five locations - Add data for Earth, Moon, Mars, Ceres Station, and Jupiter Cloud Platform following the destinations table in the GDD. @@ -233,6 +234,7 @@ These answer the pre-build review. Log each one in `DECISIONS.md` as it is imple - Add a function that validates a proposed dispatch: ship is idle at the contract's origin, pilot is idle and assigned to that ship (or the tutorial loaner case), cargo mass fits ship capacity, route passes range and landing checks, pilot is eligible, contract has not expired, player can afford fuel (skipped for tutorial dispatches, where the company pays). - 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). ### 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. @@ -254,6 +256,7 @@ These answer the pre-build review. Log each one in `DECISIONS.md` as it is imple ### Step 3.17 — Dispatch resolution - Add a function that, given a dispatch and current real time, returns either "still in flight" or a Resolution: credits to add (payout minus pilot pay, with the avatar exempt from pilot pay; for tutorial runs, exactly the tutorial share), XP to add to the pilot, ship's new location, and whether the destination becomes discovered. - **Test:** Before arrival → in flight. At or after arrival → Resolution. A delivery to an undiscovered location marks it discovered. A delivery flown by the avatar deducts no pilot pay; one flown by a hired pilot does. A reposition gives no credits or XP. Resolving the same dispatch twice with the same inputs returns identical results. +- **Amended by CR-004:** Resolution returns the pilot's new duty hours and, on mandatory rest, rest-ends-at from the arrival time (Step 10D.3). ### Step 3.18 — Sim package public API and coverage - Export only the public functions from a single entry point. Configure coverage reporting for `packages/sim`. @@ -290,6 +293,7 @@ These answer the pre-build review. Log each one in `DECISIONS.md` as it is imple - Add a migration command. - **Test:** Running migrations against the empty test database succeeds; running them a second time is a no-op. - **Amended by CR-002:** `contract_boards` is keyed by player, kind (`location` / `tutorial`), location and period (plus tutorial run); one board per player, location and period (Step 10B.3). +- **Amended by CR-004:** The pilots table gains `duty_hours` and `rest_ends_at` (Step 10D.4). ### Step 5.4 — Test database harness - Add a test helper that resets the test database between integration tests and can seed a player in a given state (tutorial, owner with one ship, etc.). @@ -444,6 +448,7 @@ These answer the pre-build review. Log each one in `DECISIONS.md` as it is imple - 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). ### 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. @@ -453,6 +458,7 @@ These answer the pre-build review. Log each one in `DECISIONS.md` as it is imple ### Step 9.7 — Pilots screen - List pilots: name, level, XP progress to next level, skill levels, available skill points, assignment, status. Actions: hire pilot (shows cost), assign to ship, spend skill point. - **Test:** Component test: spending a point calls the endpoint and the UI updates; hire is disabled with insufficient credits; assign lists only idle ships at the pilot's location. +- **Amended by CR-004:** Pilot cards show a duty bar or a rest countdown, and "Rest now" with a confirmation (Step 10D.6). ### Step 9.8 — Market screen - List the three ship models with stats (speed, capacity, range, landing class, price). "Buy" is disabled with insufficient credits. @@ -535,6 +541,7 @@ Steps 10D.1–10D.10 are specified in `memory-bank/change-requests/CR-004-pilot- - **Test:** Running the script with a fixed seed produces identical output twice. With default content, tutorial completion falls between 45 and 120 real minutes of active play. (Adjust content values, not the test thresholds, if it fails; record changes in `DECISIONS.md`.) - **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. ### 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. @@ -560,6 +567,7 @@ Steps 10D.1–10D.10 are specified in `memory-bank/change-requests/CR-004-pilot- - **Test:** The contract's ship/pilot pair changes from disabled ("skill too low") to enabled. --- +- **Amended by CR-004:** After leveling Long Haul, confirm the pilot's duty limit increased. ## Phase 13 — Deployment (Base Game) diff --git a/memory-bank/progress.md b/memory-bank/progress.md index 36d5caa..387e3d5 100644 --- a/memory-bank/progress.md +++ b/memory-bank/progress.md @@ -173,4 +173,4 @@ Spec: `memory-bank/change-requests/CR-004-pilot-duty-rest.md`. New decisions rec - [x] **Step 10D.7 — Client: duty in the dispatch flow.** The dispatch sheet disables a resting pilot's pair with "Resting — mm:ss" (new `formatClock`). Eligible pairs show "Duty after" (sim `tripGameHours` + `dutyAfterTrip`) and "Will need rest on arrival" when `needsRest`. Client validation now passes the pilot's real `restEndsAt` (dispatch sheet and deadhead picker, which shows "Pilot is resting"). Test: `dispatch-duty.test.tsx`. - [x] **Step 10D.8 — Client: board refresh and the "nothing here" case.** Every location board shows "New contracts in mm:ss" to `periodEndsAt` and refetches itself just after it. For each idle, crewed, non-resting ship at the location with no contract it can take (by the sim, via `pairOptions`), a prompt offers "Rest [pilot] — wakes to a new board" (`restPilot`) and "Deadhead (fly empty)" (opens the Fleet's deadhead picker, now exported). Test: `board-refresh.test.tsx`. - [x] **Step 10D.9 — Client: rest in summaries and on HQ.** The "While you were away" entry for a trip that ended in mandatory rest says "[Pilot] is resting until [local time]". HQ (after the tutorial) has a "Pilot rest" card: "Pilots resting: N" and the soonest to wake with a countdown, or "Everyone is ready to fly." Test: `rest-summary-hq.test.tsx`. -- [ ] Step 10D.10 — Plan amendments and regression +- [x] **Step 10D.10 — Plan amendments and regression.** CR-004 §6 amendments added to plan steps 2.1, 3.12, 3.17, 5.3, 9.5, 9.7, 12.1 and 12.6 (§0.5.42–46 were added with the CR). Full suite, coverage, lint and web build green. Scripted manual check against a live server: guest → 4 runs → deal → the avatar chains Earth↔Moon trips (2.1–2.5 game h each) and rests on arrival after the sixth (12 h limit); dispatch while resting is refused with `pilot-resting`; on waking, Earth's board is a new set. **Balance note for Phase 12:** each board has one guaranteed Courier-sized job per period, so after the first trip from a location in a period the Courier often has to deadhead or rest. **Phase 10D complete — stopped for review.**