Skip to content

feat: add authoritative O.C.C. starting loadouts#66

Merged
StreamDemon merged 7 commits into
mainfrom
feat/structured-occ-loadouts
Jul 26, 2026
Merged

feat: add authoritative O.C.C. starting loadouts#66
StreamDemon merged 7 commits into
mainfrom
feat/structured-occ-loadouts

Conversation

@StreamDemon

@StreamDemon StreamDemon commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Summary

  • replace Ley Line Walker prose equipment/weapon fields with page-stamped structured starting-loadout content covering fixed grants, fixed and dice quantities, named exact-choice groups, catalog/category constraints, and checklist-only guidance
  • add strict content-load validation plus pure planning, choice validation, resolution, and provisioning rules, including independently rolled per-suit armor capacity
  • make character creation accept only player selections, then reload and provision the O.C.C. manifest in one authoritative backend transaction before full validation and insertion
  • add a dedicated builder loadout step and unrolled review summary; keep starting armor owned but unworn, clear selections when O.C.C. ownership changes, and preserve ordinary later inventory mutation
  • document the authority boundary and legacy behavior; pre-existing characters receive no migration or retroactive grants

Authoritative sources

Rendered Rifts Ultimate Edition pages were used for the full Ley Line Walker entry and every referenced catalog item:

  • pp. 113–116: concealed armor capacity and complete Ley Line Walker starting equipment
  • pp. 268–270: energy-pistol and energy-rifle options
  • pp. 326–329: hand axe, survival knife, automatic pistol, submachine-gun, and weapon constraints

Validation

  • packages/rules: vp check; 20 files / 417 tests passed
  • packages/backend: vp check; 3 files / 139 tests passed
  • apps/web: vp check; 4 files / 70 tests passed
  • root vp check: 134 formatted files; 106 lint/typechecked files
  • root vp test: 27 files / 626 tests passed
  • git diff --check passed
  • live browser: forged a Ley Line Walker with a 23-entry concrete manifest, four independently materialized Small Sacks, both selected weapons, and 38 M.D.C. armor initially unworn; reload preserved the roll; equipping produced 38/38 armor; an ordinary later discard reduced the manifest to 22 without retroactive validation
  • live compatibility: a pre-existing Ley Line Walker remained unchanged with zero inventory; browser console reported no errors or warnings, including at 390×844

Boundaries

No retroactive grants or migration, Coalition Grunt implementation, vehicle/wallet system, ammunition consumption, or unrelated inventory changes are included.

Closes #62


Summary by cubic

Add authoritative, structured starting loadouts for the Ley Line Walker and provision starting inventory on the server during character creation. Validation is tightened to reject illegal or oversized selections and any client-authored items; quantities and armor capacity roll per instance at forge.

  • New Features

    • @riftforge/rules: Structured O.C.C. starting-loadout schema and Ley Line Walker content (fixed grants, exact-choice groups, checklist). Added planning, choice validation, and provisioning with per-suit armor rolls, a 100-instance cap, and hardening against duplicates, unknown keys, and wrong-pool picks.
    • packages/backend: characters.create now accepts loadoutSelections, rejects client items, validates choices, and provisions concrete inventory atomically. Added a request validator for loadoutSelections.
    • apps/web: New “Loadout” step and shared summary; the review shows the unrolled plan and hides the manifest; switching O.C.C. clears only loadout choices when ownership changes.
    • Docs: Recorded the loadout authority boundary and source pages.
  • Migration

    • Existing characters are unchanged; no retroactive grants or migrations.
    • Clients should submit only loadoutSelections on create; do not send items.

Written for commit c41f0aa. Summary will update on new commits.

Review in cubic

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Structured O.C.C. starting loadouts now define validated grants, choices, and checklist guidance. The builder submits only selections, while character creation resolves and rolls inventory server-side before validation and storage. Review screens distinguish unrolled grants from equipment and preserve legacy-character behavior.

Changes

Structured loadout rules

Layer / File(s) Summary
Loadout schema and O.C.C. content
packages/rules/src/schema/*, packages/rules/src/content/occ/ley-line-walker.json
Structured grants, choice pools, quantities, source references, and checklist entries replace legacy equipment fields and are validated against catalog references.
Planning, resolution, and provisioning
packages/rules/src/engine/loadouts.ts, packages/rules/tests/loadouts.test.ts
The rules engine plans loadouts, validates selections, reports errors, rolls quantities, and creates unworn inventory instances with rolled armor capacity.

Authoritative creation

Layer / File(s) Summary
Server-side character creation
packages/backend/convex/characters.ts, packages/backend/convex/schema.ts, packages/backend/tests/*
The create mutation accepts selections, provisions items from authoritative O.C.C. data, validates the complete character, and stores no transient selections.
Builder selection and review flow
apps/web/src/builder/*, apps/web/src/pages/new-character.tsx, apps/web/src/components/sheet-view.tsx
A loadout step manages O.C.C.-specific choices, gates progression, and displays unrolled grants and checklist guidance separately from the equipment manifest.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Player
  participant BuilderStore
  participant CreateMutation
  participant LoadoutEngine
  participant CharacterStore
  Player->>BuilderStore: choose loadout items
  BuilderStore->>CreateMutation: submit loadoutSelections
  CreateMutation->>LoadoutEngine: resolve and provision loadout
  LoadoutEngine-->>CreateMutation: rolled CharacterItem[]
  CreateMutation->>CharacterStore: validate and insert character
Loading

Possibly related issues

  • StreamDemon/RiftForge#12: The changes implement structured O.C.C. starting-loadout content and authoritative provisioning for the Ley Line Walker.
  • StreamDemon/RiftForge#57: The changes add the generic starting-loadout planning, validation, provisioning, builder, and backend foundation required by the Coalition Grunt work.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes match #62: structured loadouts, validation, builder flow, backend provisioning, legacy preservation, and test coverage are all present.
Out of Scope Changes check ✅ Passed No clearly unrelated features are introduced; the code, docs, and tests stay within the stated loadout-provisioning scope.
Title check ✅ Passed The title accurately summarizes the main change: authoritative starting loadouts for O.C.C. character creation.
Description check ✅ Passed The description matches the implemented loadout, validation, backend provisioning, and builder UI changes.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@StreamDemon
StreamDemon marked this pull request as ready for review July 26, 2026 16:52

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/rules/tests/loadouts.test.ts (1)

296-303: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Make the grant expectation explicit per case.

The .toBe(...) argument recomputes the expected value from the same input the code under test consumes, so a bug that drops legal grants could still satisfy it. An explicit expectsEnergyGrant: boolean on each case entry states the intent directly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/rules/tests/loadouts.test.ts` around lines 296 - 303, Add an
explicit expectsEnergyGrant boolean to each case entry in the loadout test
cases, then update the assertion in the resolveStartingLoadout loop to compare
the energy-weapon grant presence against case.expectsEnergyGrant instead of
deriving it from selections.choices.
packages/rules/src/schema/loadouts.ts (1)

104-113: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Consider bounding the selections payload.

choices is an unbounded record of unbounded arrays. resolveStartingLoadout pushes one error string per unknown key, so a large client-submitted payload produces a proportionally large error array on the server path. A .max(...) on both the record entries and selectedItemIdsSchema keeps the request boundary cheap.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/rules/src/schema/loadouts.ts` around lines 104 - 113, Bound the
starting loadout payload by applying a reasonable maximum to both the selected
item ID array in selectedItemIdsSchema and the record entries in
startingLoadoutSelectionsSchema. Preserve the existing non-empty and uniqueness
validation while ensuring resolveStartingLoadout cannot receive unbounded
choices or selections.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/rules/src/engine/loadouts.ts`:
- Around line 230-234: Make the rng parameter required in
provisionStartingLoadout by removing its Math.random default, then update every
caller—including backend creation transactions and tests—to pass an explicit
deterministic random source. Preserve the function’s existing behavior while
ensuring no call site can silently use ambient randomness.

---

Nitpick comments:
In `@packages/rules/src/schema/loadouts.ts`:
- Around line 104-113: Bound the starting loadout payload by applying a
reasonable maximum to both the selected item ID array in selectedItemIdsSchema
and the record entries in startingLoadoutSelectionsSchema. Preserve the existing
non-empty and uniqueness validation while ensuring resolveStartingLoadout cannot
receive unbounded choices or selections.

In `@packages/rules/tests/loadouts.test.ts`:
- Around line 296-303: Add an explicit expectsEnergyGrant boolean to each case
entry in the loadout test cases, then update the assertion in the
resolveStartingLoadout loop to compare the energy-weapon grant presence against
case.expectsEnergyGrant instead of deriving it from selections.choices.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 66a39401-73db-4fc8-975a-d559a56778fc

📥 Commits

Reviewing files that changed from the base of the PR and between a00886c and 207f74f.

📒 Files selected for processing (25)
  • README.md
  • apps/web/src/builder/loadout-summary.tsx
  • apps/web/src/builder/steps/loadout.tsx
  • apps/web/src/builder/steps/occ.tsx
  • apps/web/src/builder/steps/review.tsx
  • apps/web/src/builder/store.ts
  • apps/web/src/components/sheet-view.tsx
  • apps/web/src/pages/new-character.tsx
  • apps/web/tests/builder.test.ts
  • apps/web/tests/character-sheet.test.ts
  • docs/rules/PAGE_MAP.md
  • packages/backend/convex/characters.ts
  • packages/backend/convex/schema.ts
  • packages/backend/tests/characters.test.ts
  • packages/backend/tests/combat.test.ts
  • packages/backend/tests/healing-cast.test.ts
  • packages/rules/src/content/occ/ley-line-walker.json
  • packages/rules/src/engine/loadouts.ts
  • packages/rules/src/engine/occ.ts
  • packages/rules/src/index.ts
  • packages/rules/src/schema/loadouts.ts
  • packages/rules/src/schema/occ.ts
  • packages/rules/tests/character.test.ts
  • packages/rules/tests/loadouts.test.ts
  • packages/rules/tests/occ.test.ts

Comment thread packages/rules/src/engine/loadouts.ts
@StreamDemon
StreamDemon merged commit 4fbdd53 into main Jul 26, 2026
3 checks passed
@StreamDemon
StreamDemon deleted the feat/structured-occ-loadouts branch July 26, 2026 17:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Structured O.C.C. starting loadouts and authoritative provisioning

1 participant