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
- foundry-module/.ai.md: Mark F-4.5/F-QoL/F-5 as DONE, add missing files
(generic-adapter, sync-dashboard), update known limitations to reflect
API-driven system matching and generic adapter
- foundry-module/TESTING.md: Add generic adapter and sync dashboard test
sections, update character sync prerequisites
- .ai/status.md: Mark Phase 1 (Foundry Completion) as COMPLETE, update
current phase and next session priorities
- Renumber NPC addon migration from 000007 to 000009 to resolve conflict
with campaign_invites (000007) after merge from main
https://claude.ai/code/session_01WJEjfBqjZaGatHiXXXDupo
-**Fixed migration 060**: Removed incorrect first ALTER that tried to drop 'module' from ENUM directly, causing Error 1265. Kept correct 3-step approach.
@@ -686,9 +686,9 @@ Created `.ai/audit.md` — comprehensive feature parity and completeness audit c
686
686
- Updated architecture.md directory structure to reflect systems/ path
687
687
688
688
## Next Session Should
689
-
-**Sprint F-4.5: Generic System Adapter** — Remove hardcoded SYSTEM_MAP, dynamic matching via API
@@ -52,6 +54,9 @@ All sync modules use a `_syncing` boolean flag to prevent infinite loops:
52
54
|`scripts/actor-sync.mjs`| Actor ↔ character entity bidirectional sync. System adapter loading, hook registration |
53
55
|`scripts/adapters/dnd5e-adapter.mjs`| D&D 5e field mapping: 15 fields (ability scores, HP, AC, speed, level, class, race, alignment, proficiency_bonus) |
54
56
|`scripts/adapters/pf2e-adapter.mjs`| PF2e field mapping: ability mods, HP, AC, perception, speed, level, class, ancestry, heritage. Only HP/name sync back |
57
+
|`scripts/adapters/generic-adapter.mjs`| Data-driven adapter: fetches field defs from `/systems/:id/character-fields` API, auto-generates mappings from `foundry_path` annotations. Fallback for systems without a hand-written adapter |
58
+
|`scripts/sync-dashboard.mjs`| 6-tab ApplicationV2 dashboard (Entities, Shops, Maps, Characters, Calendar, Status). Pull/push actions, health metrics, error log, search/filter |
59
+
|`templates/sync-dashboard.hbs`| Handlebars template for the sync dashboard tabs and content |
55
60
|`templates/shop-window.hbs`| Handlebars template for shop inventory display |
56
61
|`styles/chronicle-sync.css`| Status indicator + shop window styles |
57
62
|`lang/en.json`| English localization for all UI strings |
@@ -99,10 +104,10 @@ All sync modules use a `_syncing` boolean flag to prevent infinite loops:
99
104
-**Single scene**: Only the active Foundry scene syncs (no multi-scene)
100
105
-**GM only**: Full sync runs only for GM users; players get passive updates via Foundry
101
106
-**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.
107
+
-**Character sync: custom system requirements**: Custom game systems must include `foundry_path` annotations on their character preset fields for bidirectional sync. Systems without annotations get no character sync (the generic adapter returns null). dnd5e and pf2e have hand-written adapters that handle edge cases.
108
+
-**System matching fallback**: `SYSTEM_MAP_FALLBACK` (3 entries: dnd5e, pf2e, drawsteel) in sync-manager.mjs is used only when the `/systems` API call fails or the system lacks a `foundry_system_id` in its manifest. Normal operation queries the API and matches dynamically.
104
109
105
-
## Planned Features (Phase F)
110
+
## Features (Phase F)
106
111
107
112
See `.ai/todo.md` Phase F for full sprint breakdown.
108
113
@@ -135,20 +140,31 @@ See `.ai/todo.md` Phase F for full sprint breakdown.
135
140
- WS: `entity.created/updated/deleted` filtered by character type (via type_slug, type_name, or type_id)
136
141
- Dashboard "Characters" tab: synced/unlinked actors, Push button, empty states
137
142
- 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.
148
-
149
-
### F-5: NPC Viewer / Hall (website feature)
150
-
- Campaign route `/campaigns/:id/npcs` — gallery of revealed NPCs
151
-
- Foundry integration: ownership change on NPC journal → auto-reveal on Chronicle
143
+
- dnd5e/pf2e adapters remain as overrides; generic adapter handles all other systems (see F-4.5).
- Retry queue for failed write operations (processes on reconnect, max 3 retries, cap 50 items)
150
+
- Dashboard Status tab: diagnostics grid, error log, field mapping debug info, activity log
151
+
- Templ component shows capability badges + warnings after system upload
152
+
153
+
### F-4.5: Generic System Adapter & Dynamic System Matching (DONE)
154
+
-`generic-adapter.mjs`: Fetches field definitions from `/systems/:id/character-fields` API. Auto-generates `toChronicleFields()`/`fromChronicleFields()` mappings from `foundry_path` annotations. Respects `foundry_writable` flag. Type casting for numbers.
155
+
-`_detectSystem()` in sync-manager.mjs now API-driven: queries `/systems`, matches by `foundry_system_id`. Falls back to `SYSTEM_MAP_FALLBACK` for legacy support.
156
+
-`_loadAdapter()` in actor-sync.mjs tries built-in adapters (dnd5e, pf2e) first, then falls back to generic adapter via `createGenericAdapter()`.
157
+
- Server: `foundry_system_id` on `SystemManifest`, `foundry_path`/`foundry_writable` on `FieldDef`. `IsFoundryWritable()` helper. New `GET /systems/:id/character-fields` API. dnd5e (15 fields), pf2e (15 fields, most read-only), drawsteel annotated.
158
+
- Custom system workflow: Upload ZIP with manifest including `foundry_system_id` and `foundry_path` annotations → Foundry module auto-detects, reads field defs from API, syncs characters without adapter code.
159
+
-**Limitation**: Systems without `foundry_path` on their fields get no character sync.
160
+
161
+
### F-5: NPC Viewer / Hall (DONE)
162
+
- NPC plugin at `internal/plugins/npcs/` with model/repo/service/handler/templates/routes
163
+
- Campaign route `/campaigns/:id/npcs` — gallery/grid of revealed NPCs (non-private character entities)
164
+
- Portrait, name, type label, tags. Search/sort/pagination. Reveal toggle via eye icon
165
+
-`npc_gallery` layout block type for entity pages and dashboards
0 commit comments