calv4 fix: the mismatch banner printed a remedy nobody could follow - #84
Merged
Merged
Conversation
All three places this module reports a calendar-structure mismatch — the permanent ui.notifications.warn from _pauseCalendarSyncForMismatch, and the dashboard's paused and incompatible banners — told the operator to "Import or author the matching calendar in Chronicle." NEITHER HALF IS REACHABLE, measured against Chronicle's source rather than guessed: IMPORT. POST /api/v1/campaigns/:cid/calendar (api_handler.go CreateCalendar) answers a structured 409 `calendar_already_exists` whenever GetCalendar(campaignID) returns anything, and that repo query is `... WHERE campaign_id = ? ORDER BY is_default DESC, sort_order ASC LIMIT 1` — ANY calendar. A campaign showing this banner HAS one by construction: the mismatch was computed by comparing against it. The import door is closed 100% of the time this advice is on screen. AUTHOR. calendarService.CreateCalendar sets `IsDefault: isFirst`, so only the first calendar a campaign ever gets is the default; this module is served the default by that same ordering; and Chronicle's SetDefaultCalendar exists on the service interface with NO route, NO handler and NO control on any page. An authored calendar therefore never reaches the wire, and there is nothing the operator can click to change that. THE REMEDY IS AN EDIT, and that one is genuinely one page away: make the two structures agree by editing a calendar that already exists. Chronicle's Calendar Settings owns months and weekdays — exactly the facts this guard compares — and Calendaria / Simple Calendar own the Foundry side. All three prints now say so, and say the same thing as each other. WHAT IS STILL IMPOSSIBLE IS BOOKED, NOT PRINTED. "Point the module at a different Chronicle calendar" needs Chronicle to wire SetDefaultCalendar to a route and a control, and/or honour a ?calId= on the syncapi reads. That is recorded in CLAUDE.md → Blocked on Chronicle with the source facts to re-verify it, and in Chronicle's own .ai/todo.md and .ai/status.md. Advice that cannot be followed is worse than no advice: the operator spends the session believing the fix is theirs to make. tools/test-calendar-mismatch-remedy.mjs reads all three strings from where they ship — the toast by invoking the pause path against a stub, the banners out of sync-dashboard.hbs — and holds each to the same verdict: never recommend an import or a new calendar, always name a reachable action, and do not lose the three facts the old toast got right (sync is paused, a reload clears it, journals/characters/maps still sync). RED (before): 2 of 3 subtests fail — the toast and both banner hints GREEN (after): 3/3, and the full module suite is 782 pass / 0 fail Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Aa645128uaFxbQyvabMizq
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.
The module half of item 6 in
keyxmakerx/Chronicle#589
("calv4 fixes: the six confirmed defects from the operator's first look"). The
Chronicle half of this one is a booking, because the thing this banner asked for
genuinely cannot be done over there yet.
The defect
All three places this module reports a calendar-structure mismatch — the
permanent
ui.notifications.warnfrom_pauseCalendarSyncForMismatch, and thedashboard's paused and incompatible Calendar-tab banners — told the
operator to
Neither half is reachable, and both were measured against Chronicle's source
rather than guessed:
POST /api/v1/campaigns/:cid/calendar(api_handler.goCreateCalendar) answers a structured 409calendar_already_existswheneverGetCalendar(campaignID)returns anything, and that repo query is… WHERE campaign_id = ? ORDER BY is_default DESC, sort_order ASC LIMIT 1—any calendar. A campaign showing this banner has one by construction: the
mismatch was computed by comparing against it. The import door is closed 100%
of the time this advice is on screen.
calendarService.CreateCalendarsetsIsDefault: isFirst, so onlythe first calendar a campaign ever gets is the default; this module is served
the default by that same ordering; and Chronicle's
SetDefaultCalendarexistson the service interface with no route, no handler and no control on any
page. An authored calendar therefore never reaches the wire, and there is
nothing the operator can click to change that.
The fix
The remedy is an edit, and that one is genuinely one page away: make the two
structures agree by editing a calendar that already exists. Chronicle's Calendar
Settings owns months and weekdays — exactly the facts this guard compares — and
Calendaria / Simple Calendar own the Foundry side. All three prints now say so,
and say the same thing as each other.
What is still impossible is booked, not printed
Pointing this module at a different Chronicle calendar needs Chronicle to wire
SetDefaultCalendarto a route and a control, and/or to honour a?calId=onthe syncapi reads. That is recorded in
CLAUDE.md→ Blocked on Chronicle,with the source facts to re-verify it, and mirrored in Chronicle's
.ai/todo.mdand
.ai/status.md.Advice that cannot be followed is worse than no advice: the operator spends the
session believing the fix is theirs to make.
The guard
tools/test-calendar-mismatch-remedy.mjsreads all three strings from where theyship — the toast by invoking the pause path against a stub, the banners out of
sync-dashboard.hbs— and holds each to the same verdict:Chronicle source fact that closes it, so a future reader can re-verify rather
than trust the file);
clears it, journals/characters/maps still sync.
It also asserts the template still carries exactly two mismatch hints, so a third
banner cannot be added below this standard.
Verification
node --test tools/test-calendar-mismatch-remedy.mjs— 3 pass / 0 fail.node --test tools/test-*.mjs(the whole suite, which is what CI runs) —782 pass / 0 fail, 0 skipped.
node tools/check-package-descriptor.mjs— OK, 0 warnings.🤖 Generated with Claude Code
https://claude.ai/code/session_01Aa645128uaFxbQyvabMizq
Generated by Claude Code