Repository navigation
Catch up characters from Chronicle's change feed - #128
Merged
Merged
Conversation
Linked actors now refresh on connect from the change feed instead of listing every character, and skip any actor already at the entity's version (the full walk too), so a reconnect with nothing new writes nothing. A removed character unlinks its actor; a stale copy never rolls an actor back; failures throw so the cursor stays. The bench gains character scenarios and shares its checks through bench/scenario.mjs. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018uKa2E5HNdeubwBSD9Jn4n
keyxmakerx
marked this pull request as ready for review
October 3, 2026 15:27
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.
Fixes: none
Security implication: none. It uses the same feed route and API key as the journal catch-up (
GET /sync/changes, which needs an owner key). Nothing is deleted: a removed character only unlinks its actor.Consumer-verified: Chronicle
internal/plugins/syncapichange feed (/sync/changes, merged in #957 and earlier) andGET /entities/:id; the bench exercises both against Chronicle main at 82578dd.Foundry compatibility: n/a. No new Foundry API is used; it runs through the same actor
update/flag calls as before. Not live-checked in a Foundry world (#94).Mockup: n/a, nothing on screen changes.
What this changes
Before: every time Foundry connected, it listed every character in Chronicle and rewrote each linked actor, even when nothing had changed.
After: on connect, linked actors catch up only on the characters the change feed says changed. An actor already at Chronicle's version is left alone, including on the full walk. Reopening a world with nothing new writes nothing. A character deleted in Chronicle unlinks its actor and keeps it. An older copy never rolls an actor back.
Why
This is step 3 of the agreed Foundry sync rebuild, characters after journals (module #125). The hard requirements were no duplicate copies, changes that are safe to repeat, and a passing two-sided bench before anything is called ready.
scripts/actor-sync.mjs:feedArea = 'actors'andfeedActive();onInitialSync({feed})calls_catchUpFromFeed;_atVersionand_olderThanRecordedguard every apply;_notifySyncIssues({quick})counts unlinked actors locally on a delta connect instead of listing all of Chronicle. That listing was the remaining full walk on reopen.bench/scenario.mjsholds the shared bench helpers.assertHealthynow also fails on duplicate actors, and on a character that exists as both an actor and a journal.Deviation: an untouched character listed in the feed is still fetched once, by design: the feed carries ids, not versions. The bench asserts data writes only, because Chronicle publishes a stale
updated_atafter a fields update, which can cause a harmless flag-only rewrite. That is filed on keyxmakerx/Chronicle#985.Test plan
node --test tools/test-*.mjs: 1023 tests, 1023 pass, 0 fail, with module main (Player notebook and Jot notes tab in Foundry #126) merged in (5 new intools/test-actor-feed.mjs)node tools/check-package-descriptor.mjs: n/a, the descriptor is unchangedCHRONICLE_DIR=../Chronicle bench/run.shagainst Chronicle main (82578dd), rerun after merging module main: 16 of 16 scenarios pass, 4 of them new for characters:Tenet self-check
.ai.md,CLAUDE.mdandbench/README.mdnow say journals and characters use the feedGenerated by Claude Code