Record CR-027: service bookings and auto-repair (Phase 27)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
fireshaper 2026-10-18 12:49:00 -04:00
parent dbae91c2cb
commit 49e7cca67a
4 changed files with 193 additions and 0 deletions

View File

@ -1989,3 +1989,9 @@ Implementation decisions not spelled out in `memory-bank/implementation-plan.md`
- **The refuel button is priced with the sim's own \`refuel\`**, for exactly what the button will buy: a full tank when the credits cover it, else the leg's fuel (Step 15.7's rule). When even the leg's fuel is too dear, the button is disabled and says why, instead of failing on tap. - **The refuel button is priced with the sim's own \`refuel\`**, for exactly what the button will buy: a full tank when the credits cover it, else the leg's fuel (Step 15.7's rule). When even the leg's fuel is too dear, the button is disabled and says why, instead of failing on tap.
- **Every sheet opens below the top bar**, rather than drawing a backdrop over it, so the credits and the clock stay in view and change as the player spends. The sheet's backdrop covers the rest, the bottom navigation included. The bar's height (3.5rem) is written in the sheet, since sheets render outside the layout that sets \`--header-h\`. - **Every sheet opens below the top bar**, rather than drawing a backdrop over it, so the credits and the clock stay in view and change as the player spends. The sheet's backdrop covers the rest, the bottom navigation included. The bar's height (3.5rem) is written in the sheet, since sheets render outside the layout that sets \`--header-h\`.
## CR-027 recorded (Service Bookings and Auto-Repair)
- **Numbering:** received as "CR-025 — Service Bookings and Auto-Repair" for "Phase 25"; stored as **CR-027**, built as **Phase 27** (its 25.n = 27.n), since CR-025 (Short Away Summary) and CR-026 (Random Events) exist. Its decisions CR-025.D1–D7 are **0.5.153–0.5.159**. Its references: CR-006 → CR-009, CR-011 → CR-014, CR-014 → CR-015, CR-019 → CR-021, CR-021 → CR-023, CR-022 → CR-024, CR-023 → CR-025, CR-024 → CR-026.
- **All seven decisions are recorded**: §8 says "Add CR-025.D1–D6", but §6 lists D7 (no double waiting) too.
- **No double waiting, with short repairs:** CR-023 counts the shop as rest only when it lasts a full rest; a repair can take 5 minutes, shorter than a 10-minute rest. Then the rest simply runs on to its end, which is still "the later of the two", so the CR's rule holds without changing CR-023's.

View File

@ -0,0 +1,162 @@
# Change Request CR-027 — Service Bookings and Auto-Repair
> **Numbering note (added when recorded):** this request arrived titled "CR-025 — Service Bookings and Auto-Repair" for "Phase 25". CR-025 (Short Away Summary) and CR-026 (Random Events), and Phases 25 and 26, already existed, so it is stored as **CR-027** and done as **Phase 27**: every "25.n" below means **27.n**. Its references map to this repo as: "Phase 13 and CR-001 through CR-024" = Phase 13 and **CR-001 to CR-026**; "CR-006 ship upgrades" = **CR-009**; "CR-011 local-first" = **CR-014**; "CR-014 fixed map and fuel tanks" = **CR-015**; "CR-019 independent pilots" = **CR-021**; "CR-021 shop rest" = **CR-023**; "CR-022 fleet sleep" = **CR-024**; "CR-023 away summary" = **CR-025**; "CR-024 random events" = **CR-026**. Its decisions CR-025.D1–D7 are recorded as **0.5.153–0.5.159** (D1 = 0.5.153 … D7 = 0.5.159); §8's "Add CR-025.D1–D6" is read as all seven.
>
> **On recording:** "HQ" here means one of the player's bays (an HQ location), as elsewhere; "ship detail" is the ship's Upgrades sheet (CR-026 Step 26.7).
**Project:** Deadhead: Space Freight Tycoon
**Applies to:** a build with Phase 13 and CR-001 through CR-024 complete
**Do this:** as **Phase 25**
**Related docs:** `change-request-ship-upgrades.md` (CR-006), `change-request-local-first.md` (CR-011), `change-request-fixed-map-and-fuel-tanks.md` (CR-014), `change-request-independent-pilots.md` (CR-019), `change-request-shop-rest.md` (CR-021), `change-request-fleet-sleep.md` (CR-022), `change-request-away-summary.md` (CR-023), `change-request-random-events.md` (CR-024), `DECISIONS.md`
This change request is written for the local-first engine (CR-011).
---
## 1. Why
Upgrades and repairs need the ship idle at an HQ (CR-006, CR-024), but Independent pilots (CR-019) take a new job almost as soon as they land, so their ships never sit still long enough. The only workaround is switching the pilot to Manual and flying the ship in by hand.
This change lets the player **book service** from anywhere. The pilot works their way to the chosen HQ, the work starts on arrival, and the pilot goes back to work afterward. If the pilot also needs rest, the rest and the service overlap, so the pilot never waits twice. **Auto-repair** books a repair on its own when the hull drops below a threshold: on by default at 40%, adjustable or off per ship.
## 2. Service bookings
| Rule | Detail |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Booking | From a ship's detail screen, anywhere: choose one or more service items (one repair and/or one upgrade level) and an HQ. Default HQ: the nearest one the ship can reach under the fuel rules. |
| Order of work | Repair first, then the upgrade. Shop times add up. |
| Cost estimate | Shown when booking; the actual charge is taken when the work starts. |
| Changing or canceling | Anytime before work starts. |
| Already at the HQ and idle | Work starts immediately (same as today). |
| Manual decision | Booking, changing, and canceling are manual decisions (CR-022). Automatic bookings (§3) are not. |
### Rest and service never stack
Service doesn't wait for rest, and rest doesn't wait for service. When they coincide, they run at the same time.
| Situation | What happens |
| --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| Pilot arrives at the booked HQ and needs mandatory rest | Service starts and the rest runs alongside it. The pilot is free when the **later** of the two ends, never the sum. |
| Pilot is already resting at the HQ when service starts (booking made, or funds arrive) | Same: they overlap; the pilot is free when the later one ends. |
| Service ends | The pilot's duty hours reset and any remaining rest ends (CR-021), since shop times are at least as long as a rest. |
| Pilot doesn't need rest | Service runs on its own; the pilot is free when it ends, with duty hours reset (CR-021). |
### What the pilot does (Independent pilots)
1. Finishes the current trip (and any mandatory rest that falls somewhere other than the booked HQ).
2. Only considers jobs whose destination is the booked HQ, scored as usual (CR-019), so the trip in still earns money. Other orders (cargo classes, minimum profit) still apply.
3. If no such job is on the board, **deadheads straight to the HQ** (fuel rules per CR-019).
4. On arrival, the service starts automatically, overlapping any rest that's due.
5. When it's done, the booking clears and the pilot resumes normal Independent work.
### Manual pilots
A booking on a Manual pilot's ship is a reminder: the tag shows on the ship and in the dispatch sheet ("Service booked at Ceres"), and the work starts automatically when the ship is next idle at that HQ, overlapping any rest that's due. The pilot doesn't route there on their own.
### Paying for it
| Booking type | When it can be charged |
| -------------------------- | -------------------------------------------------------------------------------------- |
| Booked by the player | Whenever credits cover the cost |
| Booked automatically (§3) | Only if credits stay at or above the NPC spending floor (CR-019) after paying |
If the work can't be paid for on arrival, the ship waits at the HQ with status "Waiting for funds: Repair at Ceres", the Logbook records it, and it's a "while you were away" problem highlight (CR-023). The engine retries at each board period start and whenever credits increase. The player can cancel the booking to release the ship.
### Can't reach the HQ
If the booked HQ is out of reach from where the ship is (even with refueling), the booking shows "Can't reach [HQ] from here" and the pilot keeps working normally. The booking stays and becomes active as soon as the HQ is reachable. The player can pick a different HQ.
### Fleet sleep
While the fleet is asleep (CR-022), Independent pilots with a booking still fly to the HQ and get the work done. Service trips are allowed during sleep; afterward the pilot waits for orders like the rest of the fleet.
## 3. Auto-repair
| Rule | Detail |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Setting | Per ship: **Auto-repair on/off** and a **threshold** (10% to 90%, in steps of 5). |
| Default | **On, 40%**, for every ship, new and existing. |
| When it acts | Only while the ship is crewed by an **Independent** pilot. When the hull drops below the threshold (after an event or any other damage), a repair booking is added automatically at the nearest reachable HQ, or added to an existing booking. |
| Manual crews | If the ship's pilot is Manual, crossing the threshold shows a "Repair recommended" tag instead of booking. |
| Turning it off | No new automatic bookings; an existing automatic booking stays until the player cancels it. |
## 4. UI
- **Ship detail → Service section:** current booking (items, HQ, cost estimate, status), **Book service** (item picker, HQ picker defaulting to nearest reachable), **Change**, **Cancel**, and the auto-repair toggle and threshold slider.
- **Fleet card tag:** "Service booked: Engine Tuning 2 at Ceres", or "Repair recommended" for Manual crews below the threshold.
- **Pilot status lines:** "Heading to Ceres for service", "In the shop at Ceres (resting)", "Waiting for funds: Repair at Ceres".
- **Logbook and summaries:** bookings made automatically, service started, service finished, waiting for funds.
## 5. Rules for this change
- All rules in `implementation-plan.md` §0.1 apply: steps in order, one commit per step, each step's test must pass, `packages/sim` stays pure, all numbers live in `packages/content`.
- The booked-HQ job filter and the auto-booking trigger are pure functions in `packages/sim`.
- Save migration: every ship gets auto-repair on at 40% and no booking.
- Catch-up stays deterministic: automatic bookings, service trips, and service starts happen at the same game times however catch-up is split.
- Update `architecture.md` and `progress.md` as you go. Stop for the user's review at the end of Phase 25.
## 6. Decisions
Record these in `DECISIONS.md` and `implementation-plan.md` §0.5, using the next free numbers (labeled CR-025.D1–D7 here; note the mapping).
- **CR-025.D1 Service bookings** per §2: book from anywhere; repair before upgrade; charged when work starts.
- **CR-025.D2 Independent routing:** finish the trip, take only jobs to the booked HQ, otherwise deadhead there; resume after service.
- **CR-025.D7 No double waiting:** when rest and service coincide they run at the same time; the pilot is free when the later one ends, and service ending resets duty and ends any remaining rest.
- **CR-025.D3 Manual crews:** bookings act as reminders and start automatically when the ship is idle at the HQ.
- **CR-025.D4 Payment:** player bookings charge whenever credits cover them; automatic bookings respect the NPC spending floor; unpaid ships wait at the HQ and retry.
- **CR-025.D5 Auto-repair:** per ship, default on at 40%, active only with an Independent crew; Manual crews get a "Repair recommended" tag.
- **CR-025.D6 Sleep exception:** service trips continue while the fleet is asleep.
## 7. Steps — Phase 25
### Step 25.1 — Content and save
- Config: default auto-repair threshold (40%), allowed range (10–90%, step 5). Save: per-ship booking (items, HQ, created by player or auto) and auto-repair settings. Save migration per §5.
- **Test:** Config validates. A new ship has auto-repair on at 40% and no booking. An older save migrates as described.
### Step 25.2 — Sim: routing and triggers
- Pure functions: nearest reachable HQ for a ship; whether a job's destination matches the booking; whether the pilot should deadhead to the HQ; whether an automatic repair booking should be added after a hull change.
- **Test:** With a booking at Ceres, an Independent pilot's eligible jobs all end at Ceres; with none on the board, the action is "deadhead to Ceres". A hull drop from 45% to 35% with auto-repair on at 40% and an Independent crew adds a repair booking; with a Manual crew it doesn't; with auto-repair off it doesn't. An existing upgrade booking gets the repair added rather than a second booking.
### Step 25.3 — Engine: booking commands and service start
- Commands: book service, change booking, cancel booking, set auto-repair (all manual decisions). On arrival at the booked HQ, or when a ship becomes idle there, start the work (repair, then upgrade) through the existing shop commands; charge per §2; clear the booking when done.
- **Overlap:** if the pilot is due mandatory rest on arrival, or is already resting there, the rest and the service run at the same time; the pilot is free at the later end time, and service ending resets duty and ends any remaining rest (CR-021).
- **Test:** Booking an upgrade for an idle ship already at that HQ starts it immediately. A booked ship arriving at the HQ starts service and is charged correctly. A pilot who arrives needing mandatory rest is free at the later of the rest end and the shop end, never their sum, with zero duty hours. A pilot already resting at the HQ when service starts is likewise free at the later end time. A player booking with too few credits makes the ship wait, then starts when credits rise. An automatic booking that would take credits below the spending floor waits. Canceling releases the ship.
### Step 25.4 — Engine: Independent pilots and catch-up
- Independent decision logic uses the booking filter and deadhead rule. Service trips are allowed during fleet sleep. Unreachable HQs leave the pilot working normally with the booking flagged.
- **Test:** From the same save, catching up in one go and in pieces gives identical results, including automatic bookings, service trips, and shop times. A pilot with a booking during fleet sleep still flies to the HQ and gets serviced, then waits for orders. A booking at an unreachable HQ doesn't stop the pilot from working and activates when the HQ becomes reachable.
### Step 25.5 — Client: Service section and tags
- Build the Service section, Fleet card tags, and pilot status lines from §4.
- **Test:** Component tests: booking shows the estimate and the default nearest HQ; change and cancel call the engine; the slider saves the threshold in steps of 5; tags and status lines render for each state (heading in, in the shop, waiting for funds, can't reach, repair recommended).
### Step 25.6 — Client: Logbook and summaries
- Add service entries to the Logbook and "waiting for funds" and "can't reach" as problem highlights in the "while you were away" pop-up (CR-023).
- **Test:** Component tests: entries appear for automatic bookings, service start, and service finish; the problem highlights appear when applicable.
### Step 25.7 — Balance and regression
- Run the full suite. Extend the Phase 12 balance script: Independent fleets with events on (CR-024) and auto-repair at 40%.
- **Test:** CI is green. In the balance run, no ship stays below 25% hull for more than one trip while its crew is Independent and credits allow repairs, and the CR-019 away-income target still holds. Manual check: book an upgrade for an Independent pilot's ship far from an HQ, close the app, and confirm in the Logbook that they flew to the HQ, got the upgrade, and went back to work.
## 8. Amendments
| Where | Change |
| -------- | ------------------------------------------------------------------------------------------ |
| Plan 0.5 | Add CR-025.D1–D6. |
| CR-006 | Upgrades can be booked from anywhere and start on arrival. |
| CR-019 | Independent decision logic honors bookings. |
| CR-021 | Rest and service overlap; the pilot is free at the later end time. |
| CR-022 | Service trips are allowed during fleet sleep; booking commands are manual decisions. |
| CR-023 | Service problems become highlights. |
| CR-024 | Hull damage can trigger automatic repair bookings. |
## 9. Out of scope
Mobile repair crews or field repairs, booking at locations without an HQ, booking more than one upgrade level per visit, and anything else in `implementation-plan.md` §0.3.

View File

@ -208,6 +208,13 @@ These answer the pre-build review. Log each one in `DECISIONS.md` as it is imple
150. **Radio-call notifications** (CR-026). On iOS and Android, one local notification at each radio call's fire time on trips the player sent, with the Notifications toggle. 150. **Radio-call notifications** (CR-026). On iOS and Android, one local notification at each radio call's fire time on trips the player sent, with the Notifications toggle.
151. **Independent pilots and events** (CR-026). Independent pilots' trips get the same events, radio calls and defaults; the player can answer their calls too. 151. **Independent pilots and events** (CR-026). Independent pilots' trips get the same events, radio calls and defaults; the player can answer their calls too.
152. **Hull wear** (CR-026, the user's choice in Step 26.9). Every hull loses 0.35 condition points per game hour flown, applied when a trip lands (never below 5%), so every fleet repairs now and then; with it, repairs cost 1% of the model's price per missing point (CR-026 §4 said 0.5%; tuned in Step 26.9). 152. **Hull wear** (CR-026, the user's choice in Step 26.9). Every hull loses 0.35 condition points per game hour flown, applied when a trip lands (never below 5%), so every fleet repairs now and then; with it, repairs cost 1% of the model's price per missing point (CR-026 §4 said 0.5%; tuned in Step 26.9).
153. **Service bookings** (CR-027). From a ship's detail, anywhere, the player books service at one of their HQs (the nearest reachable by default): a repair and/or one upgrade level; repair first, shop times added; an estimate when booking, charged when the work starts; changeable or cancellable until then; started at once if the ship is already idle there.
154. **Independent routing** (CR-027). An Independent pilot with a booking finishes the trip, takes only jobs ending at the booked HQ (scored and filtered as usual), otherwise deadheads there; service starts on arrival; afterwards normal work resumes. An HQ out of reach leaves the pilot working normally, the booking flagged.
155. **Manual crews** (CR-027). A booking on a Manual pilot's ship is a reminder (tags on the ship and in the dispatch sheet); the work starts when the ship is next idle at that HQ.
156. **Payment** (CR-027). Player bookings are charged whenever credits cover them; automatic ones only if credits stay at or above the NPC spending floor; a ship that can't pay waits at the HQ ("Waiting for funds"), logged and highlighted, and starts as soon as it can.
157. **Auto-repair** (CR-027). Per ship, on at 40% by default (10–90% in steps of 5): with an Independent crew, a hull dropping below it adds a repair booking at the nearest reachable HQ (or to the ship's booking); with a Manual crew it shows "Repair recommended" instead.
158. **Sleep exception** (CR-027). Service trips continue while the fleet is asleep; afterwards the pilot waits for orders.
159. **No double waiting** (CR-027). Rest and service run at the same time when they coincide; the pilot is free when the later ends, and a service long enough to count as rest (decision 0.5.135) resets duty and ends any remaining rest.
### 0.6 Translating change requests written for the server (CR-014 §7) ### 0.6 Translating change requests written for the server (CR-014 §7)
@ -929,6 +936,12 @@ Steps 26.1–26.10 are specified in `memory-bank/change-requests/CR-026-random-e
--- ---
## Phase 27 — Service Bookings and Auto-Repair (CR-027)
Steps 27.1–27.7 are specified in `memory-bank/change-requests/CR-027-service-bookings.md` §7 (written there as 25.1–25.7). Stop for review at the end.
---
## Definition of Done (Base Game) ## Definition of Done (Base Game)
- All step tests pass in CI. - All step tests pass in CI.

View File

@ -564,3 +564,15 @@ Spec: `memory-bank/change-requests/CR-026-random-events-hull.md` (received as "C
- [x] **Job length on the board.** Location board cards show how long the job takes in game hours beside the weight and distance ("Atlas Heavy Industries · 6 t · 0.38M km · 2.2 h"), for the fastest of the player's crewed ships that could take it, preferring one at the job's origin (`jobGameHours` in `apps/web/src/game.ts`); none is shown if no ship could. The tutorial board already showed its trip time. Tests: `apps/web/test/job-hours.test.tsx`. Screenshots: `docs/screenshots/fix-job-hours-{phone,desktop}.png`. - [x] **Job length on the board.** Location board cards show how long the job takes in game hours beside the weight and distance ("Atlas Heavy Industries · 6 t · 0.38M km · 2.2 h"), for the fastest of the player's crewed ships that could take it, preferring one at the job's origin (`jobGameHours` in `apps/web/src/game.ts`); none is shown if no ship could. The tutorial board already showed its trip time. Tests: `apps/web/test/job-hours.test.tsx`. Screenshots: `docs/screenshots/fix-job-hours-{phone,desktop}.png`.
- [x] **Refuel cost, and credits always in view.** "Refuel here first" in the dispatch sheet says what it buys and costs ("Refuel here first · 36 fu for 198 cr", from `refuelQuote` in `apps/web/src/components/Fuel.tsx`, priced with the sim's `refuel` as the engine charges), and is disabled with "Not enough credits for the fuel this trip needs." when the credits can't cover the leg. Sheets now open below the top bar (`top-14` in `apps/web/src/ui/Sheet.tsx`), so the credits stay visible, and update, while one is open. Tests: `apps/web/test/fuel-ui.test.tsx`. Screenshots: `docs/screenshots/fix-refuel-cost-{phone,desktop}.png`. - [x] **Refuel cost, and credits always in view.** "Refuel here first" in the dispatch sheet says what it buys and costs ("Refuel here first · 36 fu for 198 cr", from `refuelQuote` in `apps/web/src/components/Fuel.tsx`, priced with the sim's `refuel` as the engine charges), and is disabled with "Not enough credits for the fuel this trip needs." when the credits can't cover the leg. Sheets now open below the top bar (`top-14` in `apps/web/src/ui/Sheet.tsx`), so the credits stay visible, and update, while one is open. Tests: `apps/web/test/fuel-ui.test.tsx`. Screenshots: `docs/screenshots/fix-refuel-cost-{phone,desktop}.png`.
## Phase 27 — Service Bookings and Auto-Repair (CR-027)
Spec: `memory-bank/change-requests/CR-027-service-bookings.md` (received as "CR-025 … Phase 25"). New decisions recorded as plan §0.5.153–0.5.159.
- [ ] Step 27.1 — Content and save
- [ ] Step 27.2 — Sim: routing and triggers
- [ ] Step 27.3 — Engine: booking commands and service start
- [ ] Step 27.4 — Engine: Independent pilots and catch-up
- [ ] Step 27.5 — Client: Service section and tags
- [ ] Step 27.6 — Client: Logbook and summaries
- [ ] Step 27.7 — Balance and regression