Lane 11 PR 6: content with structured fields, and a small character pack per system (#737) #968

Merged
claude-bot merged 10 commits from build/lane11-6-content into main 2026-09-30 11:47:06 +00:00
Collaborator

Lane 11 (#737) PR 6 (IS-401 content; D203; owner answers L1 and L8). Reference entries now carry the per-kind fields the sheet definitions read (#962, #963). It adds no migration: the column and the kinds came with #964.

Pipeline:

  • app/reference/fields.py: checks the shapes the definitions read.
    • PF2e damage die is written "d6"; 5e hit_die is written as sides.
    • Action costs, lower-case 5e properties, and penalties ≤ 0.
    • A 32 KiB cap. Unknown keys pass through.
  • Bad fields never reject a record. They're kept in extra.unvalidated_fields with a warning, as stats are.
  • Export writes fields, so they survive a round trip.

Adapters:

  • PF2e (foundry.py, foundry_maps/pf2e.py):
    • Covers: items, weapons, armour, shields, ammunition, feats, actions, spells, classes (levels in the definition's choose shape), ancestries, heritages, backgrounds and conditions.
    • Shapes as the fixtures have them: bulk L = 0.1 with bulk_per, {dice, die, type} damage, thrown weapons with range: null.
    • Conditions: modifiers come from Foundry's FlatModifier rules.
  • 5e (open5e.py):
    • Covers: items, spells, feats, classes, species (as ancestry), backgrounds and conditions from SRD 5.2.1 records.
    • Upstream quirks handled: Open5e files the Shield as heavy armour, and its Fighter saving throws disagree with its own table.
  • .qbpack records may carry fields directly.

Starter scripts (D203):

  • PF2e: build_pf2e_starter.py adds Player Core's (and Player Core 2's) classes, ancestries, heritages, backgrounds, feats and equipment. Setting prose is stripped: ancestry, background and class descriptions are always dropped, and any description naming a reserved setting term is too.
  • 5e: build_5e_starter.py takes srd-2024 only, with the single SRD 5.2.1 notice.
  • Publishing: STARTERS stays empty. Publishing the full starters is a release step for the owner (L1). docs/OPERATIONS.md gains "Building the starter packs".

Mini character packs (one source, webapp/backend/tests/fixtures/packs/; the demo and e2e seeds read from here):

  • Contents: pf2e-characters (68 entries, ORC) and dnd5e-characters (63 entries, SRD 5.2.1 CC BY): 3 classes, 3 ancestries, 3 heritages or species, 3 backgrounds, 15–17 feats, 20–21 items, 10 spells and the conditions.
  • Every weapon and armour the definitions' fixtures name carries the fixtures' numbers.
  • No setting proper nouns; the text is paraphrased mechanics.

Tests:

  • New: test_reference_fields.py and tests/sheets/test_sheet_content_packs.py.
    • Each adapter maps a sample record to its exact fields.
    • Bad fields are demoted, and export round-trips.
    • Both packs import with no warnings.
  • Evaluator: putting the imported rows on sheets reproduces the definitions' own fixtures (Ossian's AC 23, bulk 4.9 and strikes; Tam's AC 18, HP 31 and longsword).
  • Server: the same through #964's routes.
  • Run: every module that touches the adapters, the import service, ReferenceEntry, KINDS, packs or starters, plus tests/sheets: 1205 pass.
  • Lint and changelog: ruff is clean (including alembic/), and changelog.py check passes.

What the adapters can't fill from upstream (it stays in extra):

  • PF2e consumables' action cost and triggers, which are prose only;
  • feat and heritage rule elements beyond flat condition modifiers;
  • creature fields, which is PR 7's.

Changelog: changelog.d/737-lane11-content-fields.added.md.

🤖 Generated with Claude Code

Lane 11 (#737) PR 6 (IS-401 content; D203; owner answers L1 and L8). Reference entries now carry the per-kind `fields` the sheet definitions read (#962, #963). It adds no migration: the column and the kinds came with #964. **Pipeline:** - **`app/reference/fields.py`:** checks the shapes the definitions read. - PF2e damage `die` is written "d6"; 5e `hit_die` is written as sides. - Action costs, lower-case 5e properties, and penalties ≤ 0. - A 32 KiB cap. Unknown keys pass through. - **Bad fields never reject a record.** They're kept in `extra.unvalidated_fields` with a warning, as stats are. - **Export** writes `fields`, so they survive a round trip. **Adapters:** - **PF2e** (`foundry.py`, `foundry_maps/pf2e.py`): - **Covers:** items, weapons, armour, shields, ammunition, feats, actions, spells, classes (levels in the definition's `choose` shape), ancestries, heritages, backgrounds and conditions. - **Shapes as the fixtures have them:** bulk L = 0.1 with `bulk_per`, `{dice, die, type}` damage, thrown weapons with `range: null`. - **Conditions:** modifiers come from Foundry's `FlatModifier` rules. - **5e** (`open5e.py`): - **Covers:** items, spells, feats, classes, species (as `ancestry`), backgrounds and conditions from **SRD 5.2.1** records. - **Upstream quirks handled:** Open5e files the Shield as heavy armour, and its Fighter saving throws disagree with its own table. - **`.qbpack`** records may carry `fields` directly. **Starter scripts (D203):** - **PF2e:** `build_pf2e_starter.py` adds Player Core's (and Player Core 2's) classes, ancestries, heritages, backgrounds, feats and equipment. Setting prose is stripped: ancestry, background and class descriptions are always dropped, and any description naming a reserved setting term is too. - **5e:** `build_5e_starter.py` takes **srd-2024 only**, with the single SRD 5.2.1 notice. - **Publishing:** `STARTERS` stays empty. Publishing the full starters is a release step for the owner (L1). `docs/OPERATIONS.md` gains "Building the starter packs". **Mini character packs** (one source, `webapp/backend/tests/fixtures/packs/`; the demo and e2e seeds read from here): - **Contents:** `pf2e-characters` (68 entries, ORC) and `dnd5e-characters` (63 entries, SRD 5.2.1 CC BY): 3 classes, 3 ancestries, 3 heritages or species, 3 backgrounds, 15–17 feats, 20–21 items, 10 spells and the conditions. - **Every weapon and armour** the definitions' fixtures name carries the fixtures' numbers. - **No setting proper nouns**; the text is paraphrased mechanics. **Tests:** - **New:** `test_reference_fields.py` and `tests/sheets/test_sheet_content_packs.py`. - Each adapter maps a sample record to its exact `fields`. - Bad fields are demoted, and export round-trips. - **Both packs import with no warnings.** - **Evaluator:** putting the imported rows on sheets reproduces the definitions' own fixtures (Ossian's AC 23, bulk 4.9 and strikes; Tam's AC 18, HP 31 and longsword). - **Server:** the same through #964's routes. - **Run:** every module that touches the adapters, the import service, `ReferenceEntry`, `KINDS`, packs or starters, plus `tests/sheets`: **1205 pass**. - **Lint and changelog:** ruff is clean (including `alembic/`), and `changelog.py check` passes. **What the adapters can't fill from upstream** (it stays in `extra`): - PF2e consumables' action cost and triggers, which are prose only; - feat and heritage rule elements beyond flat condition modifiers; - creature `fields`, which is PR 7's. Changelog: `changelog.d/737-lane11-content-fields.added.md`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Reference entries carry per-kind fields (contract 3.3) filled by the Foundry
pf2e and Open5e adapters and passed through from native packs, checked per
kind; ancestry/heritage kinds; the starter scripts build Player Core character
content (ORC, setting prose stripped) and SRD 5.2.1 only; a mechanics-only
mini character pack per system under tests/fixtures/packs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Merge remote-tracking branch 'origin/main' into build/lane11-6-content
Some checks failed
CI / Backend lint (ruff) (pull_request) Successful in 1m14s
CI / Bot/backend version sync (pull_request) Successful in 1m0s
CI / Docker image build (pull_request) Successful in 39s
CI / Does this change touch the recording path? (pull_request) Successful in 40s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Feedback site tests (pull_request) Successful in 5m38s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 5m47s
CI / Bot tests and audit (pull_request) Successful in 6m20s
CI / Frontend (shard 1/2) (pull_request) Successful in 11m5s
CI / End-to-end journeys (desktop) (pull_request) Failing after 5m32s
CI / Frontend (shard 2/2) (pull_request) Successful in 15m3s
CI / Backend migration, tests, and audit (pull_request) Successful in 18m55s
CI / End-to-end journeys (phone) (pull_request) Failing after 23m33s
CI / End-to-end journeys (keyboard) (pull_request) Failing after 23m35s
286c84dcaf
Merge remote-tracking branch 'origin/main' into build/lane11-6-content
All checks were successful
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 2m41s
CI / Frontend (shard 2/2) (pull_request) Successful in 15m41s
CI / Backend lint (ruff) (pull_request) Successful in 1m18s
CI / Docker image build (pull_request) Successful in 43s
CI / Bot/backend version sync (pull_request) Successful in 1m5s
CI / Does this change touch the recording path? (pull_request) Successful in 40s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Bot tests and audit (pull_request) Successful in 5m4s
CI / Feedback site tests (pull_request) Successful in 2m1s
CI / Frontend (shard 1/2) (pull_request) Successful in 22m11s
CI / Backend migration, tests, and audit (pull_request) Successful in 51m37s
CI / End-to-end journeys (phone) (pull_request) Successful in 15m21s
CI / End-to-end journeys (keyboard) (pull_request) Successful in 17m19s
CI / End-to-end journeys (desktop) (pull_request) Successful in 17m34s
7836f20df5
Sign in to join this conversation.
No description provided.