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
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.
17
+
18
+
34.**Sprint F-4: Actor ↔ Entity Sync (DONE).**
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.
20
+
-**System adapters** — `adapters/dnd5e-adapter.mjs` maps 15 D&D 5e fields (ability scores, HP, AC, speed, level, class, race, alignment, proficiency_bonus). `adapters/pf2e-adapter.mjs` maps PF2e fields (ability mods, HP, AC, perception, ancestry, heritage); only pushes HP/name back to Foundry (PF2e derives most values from items/rules).
21
+
-**Dashboard Characters tab** — New tab in sync dashboard showing synced/unlinked actors with Push button for manual push. Empty states for no actors, disabled sync, no system match.
22
+
-**module.mjs** — Registered `ActorSync` as sync module.
23
+
-**TESTING.md** — Added 30+ character sync test items covering both directions, dashboard, adapters, edge cases.
33.**Sprint F-3: System detection & character field templates (DONE).**
27
+
-**Server: Manifest expansion** — dnd5e character preset expanded from 4 to 15 fields (added ability scores, HP, AC, speed, proficiency_bonus). New pf2e character preset with 15 PF2e-specific fields (ancestry, heritage, ability mods, perception, etc). Added `CharacterPreset()` method on `SystemManifest`.
28
+
-**Server: Systems API** — New `GET /api/v1/campaigns/:id/systems` endpoint returning all registered systems with `enabled` flag per campaign (via `AddonChecker`). `addonChecker` injected into `APIHandler` via `SetAddonChecker()`.
29
+
-**Foundry: System detection** — `SYSTEM_MAP` maps Foundry `game.system.id` → Chronicle system IDs (`dnd5e`, `pf2e`, `drawsteel`). `SyncManager._detectSystem()` queries systems API on start, stores matched system in `detectedSystem` setting. New `syncCharacters` boolean setting (gated on system match).
30
+
-**Foundry: Dashboard** — Status tab shows Foundry system, Chronicle system match (green check/red X), and character sync availability.
31
+
-**Next:** F-4 (Actor ↔ Entity Sync) — new `actor-sync.mjs` with system-specific adapters.
-**Planning:** Captured Phase F roadmap (F-1 through F-7) in `.ai/todo.md` and `foundry-module/.ai.md`.
35
+
-**F-1: Journal sync fidelity (DONE):** Multi-page sync — entity content with h1/h2 headings splits into separate Foundry pages via `_splitByHeadings()`. Multiple Foundry pages concatenate back into single Chronicle entry via `_collectTextPages()`. `_syncPagesToJournal()` adds/updates/removes pages incrementally. Ownership change hook now pushes `is_private` on every update.
36
+
-**F-2: Granular permission mapping (DONE):** New syncapi endpoints `GET/PUT /entities/:eid/permissions` wrapping existing `EntityService.GetEntityPermissions` / `SetEntityPermissions`. Foundry module: `_buildOwnership()` fetches Chronicle permissions and maps role grants to Foundry default ownership levels (custom visibility player view→OBSERVER, player edit→OWNER, no player grant→NONE). `_pushPermissions()` reverse-maps Foundry ownership changes to Chronicle visibility/permission updates. User-specific grants stored but not mapped (needs user ID mapping table — deferred). TESTING.md updated with multi-page and permission test items.
-[x]**Sprint R-4: Plugin SDK & Developer Tools** — Example WASM plugins (Rust auto-tagger, Go session-logger). Go SDK with MockHost test harness (9 tests). Plugin development guide. 7 new manifest tests. **Phase R complete.**
281
281
282
+
### Phase F: Foundry Sync Enhancements & Character Integration
-[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
+
-[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
+
-[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. **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.**
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).
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.
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.
294
+
282
295
### Deferred to Phase S+ (or community contributions)
283
296
284
297
-[ ]**Module Builder UI** — Guided wizard that helps users create custom game system modules through the web UI. Step-by-step: name/metadata → define categories → define fields per category → paste/upload reference data → preview tooltips → export as module directory. Eliminates need to hand-write manifest.json + data files.
-**Single scene**: Only the active Foundry scene syncs (no multi-scene)
94
100
-**GM only**: Full sync runs only for GM users; players get passive updates via Foundry
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.
104
+
105
+
## Planned Features (Phase F)
106
+
107
+
See `.ai/todo.md` Phase F for full sprint breakdown.
108
+
109
+
### F-1: Journal Sync Fidelity (DONE)
110
+
- Split entity `entry_html` by `<h1>`/`<h2>` headings into multiple Foundry pages
111
+
- Concatenate all text pages back into single `entry` for Foundry→Chronicle
112
+
- Track page mapping via `chronicle-sync.pageMap` flag
113
+
- Detect ownership changes in `updateJournalEntry` hook, push to Chronicle
-`SyncManager._detectSystem()` queries `GET /api/v1/campaigns/:id/systems` on start
124
+
- Matches Foundry `game.system.id` to Chronicle system, stores in `detectedSystem` setting
125
+
-`syncCharacters` boolean setting (gated on system match)
126
+
- Dashboard Status tab shows system match info and character sync availability
127
+
- Server: Expanded dnd5e character preset (15 fields), added pf2e character preset (15 fields)
128
+
- Server: `CharacterPreset()` helper on `SystemManifest`
129
+
- Server: New `GET /systems` API endpoint with `enabled` flag per campaign
130
+
131
+
### F-4: Actor ↔ Entity Sync (DONE)
132
+
-`actor-sync.mjs`: Bidirectional sync between Foundry Actors and Chronicle character entities
133
+
- System adapters: `adapters/dnd5e-adapter.mjs` (15 fields), `adapters/pf2e-adapter.mjs` (HP/name back only)
134
+
- Hooks: `createActor`, `updateActor`, `deleteActor` with `_syncing` guard
135
+
- WS: `entity.created/updated/deleted` filtered by character type (via type_slug, type_name, or type_id)
136
+
- Dashboard "Characters" tab: synced/unlinked actors, Push button, empty states
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.
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
152
+
153
+
### F-6: Armory / Inventory System
154
+
- Items with game-mechanic fields, character "Inventory" tab via relations
155
+
- Foundry sync: Actor inventory ↔ Chronicle inventory relations
0 commit comments