adapter: normalize Foundry Sets & pseudo-doc collections to JSON (Phase C)#75
Merged
Merged
Conversation
…+ maps The Overview's quick-action button only ran a journal resync, so after a manifest/path change a GM's character field data (and inventory/notes) stayed stale — the button implied a full sync but wasn't one. Replace it with 'Sync Everything Now' (new resync-everything action): one confirm, then resync all journals, re-push every LINKED character via ActorSync.repushActor (Foundry is source of truth for characters), and resync all maps. Failures are isolated per item so one bad actor can't abort the sweep. Unlinked actors stay on the Characters tab's 'Push All Actors' (that one creates entities — deliberately not bundled into a routine refresh). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LaDDiXB5GTVurEzJwYYopf
The generic adapter read live Foundry values straight into fields_data, but
several Draw Steel fields are structures JSON.stringify renders as {}:
- Sets (ability keywords, skills, power-roll characteristics, actor.statuses)
- a CollectionField of pseudo-documents (an ability's system.power.effects
tier ladder)
Add normalizeFoundryValue(): Set→array, Collection/Map→array of member
toObject(), recursive (catches nested Sets, e.g. a damage tier's types), and
depth-guarded/defensive. Wire it into every scalar read and projected
sub-field; a Set/array/object scalar on a string/json field is JSON-stringified
so it arrives as parseable JSON (mirrors collection fields). +9 unit tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LaDDiXB5GTVurEzJwYYopf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Cites: Draw Steel sheet sync-expansion arc (Phase C) —
Chronicle-Draw-Steel#25manifest consumes thisSecurity implication: none — read-side field extraction; no new trust boundary, no token/URL handling
Consumer-verified:
Chronicle-Draw-Steel/manifest.jsonhero preset projects Set-valued sub-fields (system.keywords,system.power.roll.characteristics,system.skills.value,actor.statuses) and thesystem.power.effectspseudo-document collection — all of which serialized to{}before thisFoundry compatibility: read-only actor traversal via the generic adapter; not version-gated (no v12/13/14-specific API)
Mockup: n/a
What this changes
The generic adapter read live Foundry values straight into
fields_data, but several Draw Steel fields are structuresJSON.stringifyrenders as{}: Sets (ability keywords, skills, power-roll characteristics,actor.statuses) and a CollectionField of pseudo-documents (an ability'ssystem.power.effectstier ladder). NewnormalizeFoundryValue()walks these — Set → array, Collection/Map → array of membertoObject(), recursive (catches nested Sets like a damage tier'stypes), depth-guarded and defensive — and is wired into every scalar read and projected sub-field. A Set/array/object scalar on astring/jsonfield is JSON-stringified so it arrives as parseable JSON (mirrors collection fields).Why
Phase C of the Draw Steel sheet needs ability keywords, the tier ladder, skills, and conditions — every one of which is a Foundry Set or pseudo-doc collection. Without normalization they reach Chronicle as
{}, so the manifest projections are inert. This is the adapter half; the manifest half isChronicle-Draw-Steel#25.Test plan
node --test tools/test-generic-adapter.mjs— passes (15 tests; +9 new for the normalizer: primitives pass-through, Set→array, nested Sets, Collection-via-.contents+toObject, projected Set sub-field, Set scalar → JSON string,actor.statuses)node -c scripts/adapters/generic-adapter.mjsnode tools/check-package-descriptor.mjs— n/a (descriptor unchanged)abilities_jsonkeywords/tiers,skills_json, andconditions_jsonarrive as arrays (not{}) via Sync Dashboard ▸ Diagnostics; and "Sync Everything Now" refreshes a linked character's stale fieldsTenet self-check
normalizeFoundryValuenever executes data, only restructures it; no token/URL/auth changesStop-and-flag
Flag any tenet violation by number during review.
🤖 Generated with Claude Code
https://claude.ai/code/session_01LaDDiXB5GTVurEzJwYYopf