You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: plan F-4.5 generic adapter for dynamic system matching
Current F-4 implementation hardcodes SYSTEM_MAP and adapter loading
for only dnd5e/pf2e. F-4.5 will add foundry_system_id and
foundry_path annotations to system manifests, a generic adapter that
reads field definitions from the API, and dynamic system matching —
enabling any user-uploaded custom game system to get automatic
character sync.
https://claude.ai/code/session_01XMwxFR8BCi5XvgaSVMSBZB
35.**F-4.5 planning: Generic System Adapter & Dynamic Matching.**
14
+
- Identified that F-4's `SYSTEM_MAP` and `_loadAdapter()` switch are hardcoded to only dnd5e/pf2e/drawsteel. Custom-uploaded game systems can't participate in character sync despite having the server infrastructure (entity presets, `CharacterPreset()` helper, campaign system upload).
15
+
- Planned F-4.5 sprint: add `foundry_system_id` to system manifest, add `foundry_path` + `foundry_writable` annotations on character preset field definitions, new `GET /systems/:id/character-fields` API endpoint, new `generic-adapter.mjs` that reads field definitions from API and auto-generates field mappings. dnd5e/pf2e remain as overrides.
16
+
- Updated `.ai/todo.md`, `foundry-module/.ai.md` (known limitations + F-4.5 plan), and Phase F master plan with full F-4.5 sprint spec.
12
17
13
18
34.**Sprint F-4: Actor ↔ Entity Sync (DONE).**
14
19
-**actor-sync.mjs** — New `ActorSync` module class. Bidirectional sync between Foundry Actors (type: character) and Chronicle character entities. Registers `createActor`/`updateActor`/`deleteActor` hooks. Handles `entity.created/updated/deleted` WS messages filtered by character type. Uses `_syncing` guard. `_onCharacterDeleted()` unlinks (unsets flags) rather than deleting Actor.
-[x]**Sprint F-1: Journal Sync Fidelity** — Multi-page journal sync (split entity `entry_html` by headings into Foundry pages, concatenate pages back on Foundry→Chronicle). Ownership change hook (detect ownership changes in `updateJournalEntry` hook, push to Chronicle). Helpers: `_splitByHeadings`, `_collectTextPages`, `_syncPagesToJournal`.
287
287
-[x]**Sprint F-2: Granular Permission Mapping** — Map Chronicle `visibility: 'custom'` + `entity_permissions` to Foundry per-user ownership levels (view→OBSERVER, edit→OWNER). New syncapi endpoints: `GET /entities/:eid/permissions`, `PUT /entities/:eid/permissions`. Reverse-map Foundry ownership changes back to Chronicle. Helpers: `_buildOwnership`, `_pushPermissions`. User-specific grants stored in flags but not mapped to Foundry users (requires user ID mapping table — deferred).
288
288
-[x]**Sprint F-3: System Detection & Character Field Templates** — Expanded dnd5e character preset (15 fields: class, level, race, alignment + 6 ability scores + HP/AC/speed/proficiency). Added pf2e character preset (15 fields: class, level, ancestry, heritage + 6 ability mods + HP/AC/perception/speed). `CharacterPreset()` helper on `SystemManifest`. New `GET /api/v1/campaigns/:id/systems` endpoint returns available systems with enabled flag. Foundry module: `syncCharacters` + `detectedSystem` settings, `SYSTEM_MAP` table, `_detectSystem()` on start, `getMatchedSystem()` accessor. Dashboard Status tab shows system match info and character sync availability.
289
-
-[x]**Sprint F-4: Actor ↔ Entity Sync** — `actor-sync.mjs` with bidirectional Actor ↔ entity sync. System adapters: `dnd5e-adapter.mjs` (15 fields), `pf2e-adapter.mjs` (HP/name back only). Dashboard Characters tab with Push button. Registered in module.mjs. TESTING.md updated.
289
+
-[x]**Sprint F-4: Actor ↔ Entity Sync** — `actor-sync.mjs` with bidirectional Actor ↔ entity sync. System adapters: `dnd5e-adapter.mjs` (15 fields), `pf2e-adapter.mjs` (HP/name back only). Dashboard Characters tab with Push button. Registered in module.mjs. TESTING.md updated. **Note: adapters and SYSTEM_MAP are hardcoded — see F-4.5.**
290
+
-[ ]**Sprint F-4.5: Generic System Adapter & Dynamic Matching** — Remove hardcoded `SYSTEM_MAP` and adapter switch. Instead: (1) Add `foundry_system_id` field to system manifest schema so custom-uploaded systems can declare Foundry compatibility. (2) `_detectSystem()` queries API and matches by `foundry_system_id` instead of static JS map. (3) Add `foundry_path` annotation on character preset field definitions (e.g., `"foundry_path": "system.abilities.str.value"`). (4) New `generic-adapter.mjs` reads character preset fields from API, auto-generates `toChronicleFields()`/`fromChronicleFields()` using `foundry_path` annotations. Fields without `foundry_path` are read-only (pushed to Chronicle but not written back to Foundry). (5) dnd5e/pf2e adapters remain as overrides for edge cases. **Result: any user-uploaded custom game system with a character preset and foundry_path annotations gets automatic character sync.**
290
291
-[ ]**Sprint F-5: NPC Viewer / Hall** — Campaign route `/campaigns/:id/npcs`. Gallery/grid of revealed NPCs (non-private character entities). Portrait, name, description, location, faction. Filters by location/organization/relation. "Reveal" = DM toggles `is_private`. Foundry integration: ownership change on NPC journal → auto-reveal on Chronicle. Long-term: NPC relationship map (filtered relation graph).
291
292
-[ ]**Sprint F-6: Armory / Inventory System** — Items as entities with game-mechanic fields (weight, cost, rarity, damage, properties). Character "Inventory" tab/block via entity relations. Relation metadata: equipped, quantity, attunement. System-specific item templates (dnd5e ≠ pf2e). Foundry sync: Actor inventory ↔ Chronicle inventory relations. "Armory" campaign page showing all catalogued items.
292
293
-[ ]**Sprint F-7: Shop / Marketplace Enhancement** — Transaction logging (who bought what, when). Currency tracking per character. Stock management (auto-deplete on purchase). Foundry: purchase from shop window → update character inventory on both sides.
Copy file name to clipboardExpand all lines: foundry-module/.ai.md
+12Lines changed: 12 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -99,6 +99,8 @@ All sync modules use a `_syncing` boolean flag to prevent infinite loops:
99
99
-**Single scene**: Only the active Foundry scene syncs (no multi-scene)
100
100
-**GM only**: Full sync runs only for GM users; players get passive updates via Foundry
101
101
-**Character sync: limited fields back from PF2e**: Only HP and name sync from Chronicle to PF2e actors (most values are derived from items/rules)
102
+
-**Character sync: hardcoded adapters**: `_loadAdapter()` in actor-sync.mjs uses a switch statement that only loads dnd5e and pf2e adapters. Custom/uploaded game systems won't get character sync until F-4.5 (generic adapter) is implemented. The server infrastructure already supports it — custom systems can define `entity_presets` with a `-character` slug and field definitions. F-4.5 will replace the hardcoded switch with a generic adapter that reads field mappings from the Chronicle API.
103
+
-**System ID mapping hardcoded**: `SYSTEM_MAP` in sync-manager.mjs only maps 3 Foundry system IDs. F-4.5 will query available systems from the API and match dynamically.
102
104
103
105
## Planned Features (Phase F)
104
106
@@ -133,6 +135,16 @@ See `.ai/todo.md` Phase F for full sprint breakdown.
133
135
- WS: `entity.created/updated/deleted` filtered by character type (via type_slug, type_name, or type_id)
134
136
- Dashboard "Characters" tab: synced/unlinked actors, Push button, empty states
135
137
- Delete from Chronicle unlinks Actor (preserves data); delete from Foundry deletes Chronicle entity
138
+
-**Limitation**: Adapters are hardcoded per system. See F-4.5 for generic/dynamic adapter plan.
139
+
140
+
### F-4.5: Generic System Adapter & Dynamic System Matching (PLANNED)
141
+
-**Goal**: Any game system (built-in or user-uploaded custom) works with character sync out of the box, with no Foundry module code changes required.
142
+
-**Remove `SYSTEM_MAP` hardcoding**: Instead of mapping Foundry `game.system.id` → Chronicle system ID via a static JS object, query `GET /systems` and match by `foundry_system_id` field on the system manifest. Systems API already returns all registered systems. Add `foundry_system_id` to system manifest schema so custom uploads can declare their Foundry compatibility.
143
+
-**Generic adapter**: New `adapters/generic-adapter.mjs` that reads character field definitions from the Chronicle API (`GET /systems/:id/character-fields` or from the character preset in the entity types response). For each field in the preset, it generates `toChronicleFields()` mappings (Foundry `system.*` → Chronicle `fields_data.*`) and `fromChronicleFields()` reverse mappings.
144
+
-**Field mapping convention**: The generic adapter uses a convention-based approach: Chronicle field keys map to Foundry `system.<path>` using a `foundry_path` property on each field definition. Systems that declare `foundry_path` on their character preset fields get automatic bidirectional sync. Fields without `foundry_path` are pushed to Chronicle (read from Foundry's flat actor data) but not written back.
145
+
-**Fallback to specific adapters**: dnd5e and pf2e adapters remain as overrides for known systems (they handle edge cases like PF2e's derived values). Generic adapter is the fallback for any system not in the override list.
146
+
-**Server changes**: Add optional `foundry_system_id` and `foundry_path` fields to system manifest `entity_presets[].fields[]`. Expose character preset fields via API so the Foundry module can read them. Custom system upload already validates manifests, so these fields would be available on upload.
147
+
-**Custom system workflow**: User uploads a custom game system ZIP to Chronicle with a manifest that includes `foundry_system_id: "my-system"` and character preset fields with `foundry_path` annotations. Foundry module auto-detects the system, reads field definitions from API, and syncs characters without any adapter code.
136
148
137
149
### F-5: NPC Viewer / Hall (website feature)
138
150
- Campaign route `/campaigns/:id/npcs` — gallery of revealed NPCs
0 commit comments