[Game Systems] Foundry alignment: one system identity + structured npc_to_actor #151

Open
opened 2026-07-15 22:03:27 +00:00 by claude-bot · 0 comments
Contributor

Motivation/Context

Issue #24 (Foundry bidirectional integration architecture) already commits Quest Board
to a per-campaign Foundry system identifier that selects an adapter: "Each campaign
stores a Foundry server URL, an API key, and a system identifier. The system identifier
selects an adapter." Issue #5 ("[Foundry P1] Per-campaign Foundry connection settings")
implements exactly that: URL, encrypted API key, and a system selector, scoped as
its own campaign settings fields.

If the game-aware GameSystem registry (#133) doesn't exist by the time #5 ships, #5
will invent its own, Foundry-only system field — a second source of truth for "what
system is this campaign" alongside the (then-nonexistent) registry, needing painful
reconciliation later. The registry's key (dnd5e, pf2e, generic) is designed to
be the Foundry adapter registry key, so a campaign should carry exactly one system
identity used by prompts (#137), stat schemas (#139), and Foundry alike.

Separately, issue #9 ("[Foundry P2] pf2e npc_to_actor + 'Send to Foundry' on NPC
generation," v4.1.0) pushes Quest Board-generated NPCs into Foundry's actor directory.
Today that would mean parsing markdown stat blocks. With the stats JSONB envelope
(#139) available, npc_to_actor can map structured data directly.

This issue is a small amendment, not new adapter work: it notes the dependency on
#5 and gives #9 a preference order for its data source.

Approach

(a) v4.0.0 / #5 amendment — one system identity. #5's "system selector" field
should read/write campaign.game_system_id → game_systems.key (from #133) rather than
introducing a separate Foundry-only system column. This makes registry issue #133 a
soft prerequisite for #5: land #133 before or alongside Foundry Phase 1, or add an
explicit note on #5 that its system selector must consume the registry once available.
game_systems.foundry_system_id (usually == key) exists precisely to decouple Quest
Board's internal key from Foundry's own system id string if they ever diverge
(dnd5e/pf2e today, so in practice they're the same string). No adapter code changes
here — this is a data-source amendment to #5's settings field, landing as either a
scope note on #5 itself or a small follow-up PR against it depending on timing.

(b) v4.1.0 / #9 amendment — structured npc_to_actor. When implementing #9's
pf2e adapter npc_to_actor(generated_npc), prefer the entry's structured stats
envelope ({system: "pf2e", schema_version, values}, from #139) over parsing the
markdown body when present: map stats.values → the Foundry actor's system block
using the schema's field naming (which should be kept in view of Foundry's own field
names — e.g. abilities as str/dex/con/int/wis/cha — specifically so this mapping stays
close to 1:1, per the report §3.3). Markdown parsing remains the fallback for entries
with no stats envelope (unlinked campaigns, or entries never run through #142's
schema-targeted generation or #145's conversion wizard). The generic adapter (#10)
is unaffected — it keeps working for unlinked/free-form campaigns regardless of this
issue.

Sequencing/overlap flag: a related Foundry-side issue about mapping #130's
sidebar_fields (specifically its infobox-row visibility model) into npc_to_actor is
expected to be filed separately under the Foundry live-push investigation. That issue
and this one both touch npc_to_actor's data source (sidebar_fields vs. the stats
envelope) — they need to be sequenced together when both exist so #9's implementation
doesn't get two conflicting "prefer X" instructions. Whoever picks up #9 should check
for that sibling issue and reconcile the two source-preference notes into one coherent
plan before implementing.

Dependencies

  • #133 (GameSystem registry + campaign linkage) — required for both halves: (a) needs
    game_systems.key/foundry_system_id to exist for #5 to consume, and (b) needs the
    registry to exist for a campaign to even have a pf2e-linked system in the first
    place.
  • #139 (Versioned stat schemas + stats storage + validation service) — required for
    the v4.1.0 half (b); npc_to_actor has nothing structured to prefer without it.
  • #24 (Foundry bidirectional integration — architecture reference) — the adapter
    registry and system-identifier design this issue aligns with.
  • #5 (Foundry P1 connection settings, v4.0.0) and #9 (Foundry P2 npc_to_actor, v4.1.0)
    — the issues this amendment applies to; not blocking, but the notes here should be
    read before implementing either.

Out of scope

  • Any new adapter methods, adapter scaffolding, or health-check work — all covered by
    #5/#6/#7/#8 in v4.0.0 and #9/#10 in v4.1.0 as already scoped.
  • The Foundry-side issue about sidebar_fieldsnpc_to_actor mapping — that's filed
    separately under the Foundry live-push work; this issue only flags the overlap so the
    two can be sequenced, it doesn't resolve or absorb that work.
  • Encrypted API key storage, connection health checks, or any other part of #5/#9's
    scope beyond the system-identity/data-source amendments described here.

Acceptance criteria

  • #5's system selector field is implemented against game_systems.key (via
    campaign.game_system_id), not a second Foundry-only system column — verified either
    by #133 landing before #5's implementation, or by an explicit amendment note left on
    #5 if #5 ships first.
  • #9's pf2e adapter npc_to_actor implementation checks for a stats envelope first
    and maps values → the Foundry actor system block when present; falls back to
    markdown parsing only when no stats envelope exists on the entry.
  • No regression to the generic adapter (#10) or to campaigns without a linked system.
  • The overlap with the Foundry-side sidebar_fields-mapping issue is explicitly noted
    in both issues (a comment or cross-link) so whoever implements #9 sees both notes
    before writing the adapter's data-source logic.
## Motivation/Context Issue #24 (Foundry bidirectional integration architecture) already commits Quest Board to a per-campaign Foundry **system identifier** that selects an adapter: "Each campaign stores a Foundry server URL, an API key, and a system identifier. The system identifier selects an adapter." Issue #5 ("[Foundry P1] Per-campaign Foundry connection settings") implements exactly that: URL, encrypted API key, **and a system selector**, scoped as its own campaign settings fields. If the game-aware `GameSystem` registry (#133) doesn't exist by the time #5 ships, #5 will invent its own, Foundry-only system field — a *second* source of truth for "what system is this campaign" alongside the (then-nonexistent) registry, needing painful reconciliation later. The registry's `key` (`dnd5e`, `pf2e`, `generic`) is designed to *be* the Foundry adapter registry key, so a campaign should carry exactly one system identity used by prompts (#137), stat schemas (#139), and Foundry alike. Separately, issue #9 ("[Foundry P2] pf2e npc_to_actor + 'Send to Foundry' on NPC generation," v4.1.0) pushes Quest Board-generated NPCs into Foundry's actor directory. Today that would mean parsing markdown stat blocks. With the `stats` JSONB envelope (#139) available, `npc_to_actor` can map structured data directly. This issue is a **small amendment**, not new adapter work: it notes the dependency on #5 and gives #9 a preference order for its data source. ## Approach **(a) v4.0.0 / #5 amendment — one system identity.** #5's "system selector" field should read/write `campaign.game_system_id → game_systems.key` (from #133) rather than introducing a separate Foundry-only system column. This makes registry issue #133 a **soft prerequisite** for #5: land #133 before or alongside Foundry Phase 1, or add an explicit note on #5 that its system selector must consume the registry once available. `game_systems.foundry_system_id` (usually == `key`) exists precisely to decouple Quest Board's internal key from Foundry's own system id string if they ever diverge (`dnd5e`/`pf2e` today, so in practice they're the same string). No adapter code changes here — this is a data-source amendment to #5's settings field, landing as either a scope note on #5 itself or a small follow-up PR against it depending on timing. **(b) v4.1.0 / #9 amendment — structured `npc_to_actor`.** When implementing #9's `pf2e` adapter `npc_to_actor(generated_npc)`, prefer the entry's structured `stats` envelope (`{system: "pf2e", schema_version, values}`, from #139) over parsing the markdown `body` when present: map `stats.values` → the Foundry actor's `system` block using the schema's field naming (which should be kept in view of Foundry's own field names — e.g. abilities as `str/dex/con/int/wis/cha` — specifically so this mapping stays close to 1:1, per the report §3.3). Markdown parsing remains the fallback for entries with no `stats` envelope (unlinked campaigns, or entries never run through #142's schema-targeted generation or #145's conversion wizard). The `generic` adapter (#10) is unaffected — it keeps working for unlinked/free-form campaigns regardless of this issue. **Sequencing/overlap flag:** a related Foundry-side issue about mapping #130's `sidebar_fields` (specifically its infobox-row visibility model) into `npc_to_actor` is expected to be filed separately under the Foundry live-push investigation. That issue and this one both touch `npc_to_actor`'s data source (`sidebar_fields` vs. the `stats` envelope) — they need to be sequenced together when both exist so #9's implementation doesn't get two conflicting "prefer X" instructions. Whoever picks up #9 should check for that sibling issue and reconcile the two source-preference notes into one coherent plan before implementing. ## Dependencies - #133 (GameSystem registry + campaign linkage) — required for both halves: (a) needs `game_systems.key`/`foundry_system_id` to exist for #5 to consume, and (b) needs the registry to exist for a campaign to even have a `pf2e`-linked system in the first place. - #139 (Versioned stat schemas + `stats` storage + validation service) — required for the v4.1.0 half (b); `npc_to_actor` has nothing structured to prefer without it. - #24 (Foundry bidirectional integration — architecture reference) — the adapter registry and system-identifier design this issue aligns with. - #5 (Foundry P1 connection settings, v4.0.0) and #9 (Foundry P2 npc_to_actor, v4.1.0) — the issues this amendment applies to; not blocking, but the notes here should be read before implementing either. ## Out of scope - Any new adapter methods, adapter scaffolding, or health-check work — all covered by #5/#6/#7/#8 in v4.0.0 and #9/#10 in v4.1.0 as already scoped. - The Foundry-side issue about `sidebar_fields` → `npc_to_actor` mapping — that's filed separately under the Foundry live-push work; this issue only flags the overlap so the two can be sequenced, it doesn't resolve or absorb that work. - Encrypted API key storage, connection health checks, or any other part of #5/#9's scope beyond the system-identity/data-source amendments described here. ## Acceptance criteria - #5's system selector field is implemented against `game_systems.key` (via `campaign.game_system_id`), not a second Foundry-only system column — verified either by #133 landing before #5's implementation, or by an explicit amendment note left on #5 if #5 ships first. - #9's `pf2e` adapter `npc_to_actor` implementation checks for a `stats` envelope first and maps `values` → the Foundry actor `system` block when present; falls back to markdown parsing only when no `stats` envelope exists on the entry. - No regression to the `generic` adapter (#10) or to campaigns without a linked system. - The overlap with the Foundry-side `sidebar_fields`-mapping issue is explicitly noted in both issues (a comment or cross-link) so whoever implements #9 sees both notes before writing the adapter's data-source logic.
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rbrooks/Quest-Board#151
No description provided.