Special jobs: data-driven registry + priority status (ISS-073, v0.37.0) #75

Merged
kamilkrzywda merged 2 commits from feat/special-jobs into master 2026-09-21 12:17:42 +02:00
Owner

Fixes #73

Packages can now carry a special status from a data-driven registry — adding or removing a special is an edit of one entry in lib/game/specials.ts, no scattered branches.

  • Registry: flat SPECIALS record (house style, like PLANE_TYPES) with per-status modifiers: reward multiplier, deadline scale, reputation bonus. First status: priority — ×1.5 reward, ×0.5 deadline window, +0.5 rep on delivery.
  • Spawn: one appended RNG draw in generatePackage() (fixed order preserved); 15% chance of a special, uniform among registered statuses; forced override skips the draw.
  • State shape: nullable special column (3-sync: Drizzle schema + DDL + guarded migration — legacy rows stay NULL), SeedPackage, PackageState, row mapping.
  • UI: sky-blue "Priority" badge on open and on-board job rows (package-special-{id} testid).
  • Test hook: create-package accepts special (string or null); omitted → forced null so existing e2e expectations stay deterministic; expire-package passes null explicitly.
  • OpenAPI: optional PackageState.special + sorted-key pin updated.

Unit: +10 tests (registry application, pickSpecial distribution with fixed RNG, removed-entry cleanly disables a status, delivery rep bonus). E2E: new test forces a priority package and asserts the badge renders. Verified by CI against the isolated dind stack.

Fixes #73 Packages can now carry a **special status** from a data-driven registry — adding or removing a special is an edit of one entry in `lib/game/specials.ts`, no scattered branches. - **Registry**: flat `SPECIALS` record (house style, like `PLANE_TYPES`) with per-status modifiers: reward multiplier, deadline scale, reputation bonus. First status: **priority** — ×1.5 reward, ×0.5 deadline window, +0.5 rep on delivery. - **Spawn**: one appended RNG draw in `generatePackage()` (fixed order preserved); 15% chance of a special, uniform among registered statuses; forced override skips the draw. - **State shape**: nullable `special` column (3-sync: Drizzle schema + DDL + guarded migration — legacy rows stay NULL), `SeedPackage`, `PackageState`, row mapping. - **UI**: sky-blue "Priority" badge on open and on-board job rows (`package-special-{id}` testid). - **Test hook**: create-package accepts `special` (string or null); omitted → forced null so existing e2e expectations stay deterministic; expire-package passes null explicitly. - **OpenAPI**: optional `PackageState.special` + sorted-key pin updated. Unit: +10 tests (registry application, pickSpecial distribution with fixed RNG, removed-entry cleanly disables a status, delivery rep bonus). E2E: new test forces a priority package and asserts the badge renders. Verified by CI against the isolated dind stack.
kamilkrzywda added 1 commit 2026-09-21 11:31:53 +02:00
kamilkrzywda scheduled this pull request to auto merge when all checks succeed 2026-09-21 11:32:02 +02:00
kamilkrzywda added 1 commit 2026-09-21 12:08:36 +02:00
kamilkrzywda merged commit 0f5f3ae23e into master 2026-09-21 12:17:42 +02:00
Sign in to join this conversation.