Skip to content

Sky Clock: a snow-globe look for the built-in calendar - #209

Merged
keyxmakerx merged 2 commits into
mainfrom
claude/foundry-sky-clock-85vdwl
Oct 12, 2026
Merged

keyxmakerx merged 2 commits into
mainfrom
claude/foundry-sky-clock-85vdwl

Conversation

@keyxmakerx

@keyxmakerx keyxmakerx commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

Fixes #208
Security implication: the players' calendar snapshot gains moons, hemisphere, weather presets and event sky types. All of it is copied field by field from the ?audience=players reads it was already built from. Hidden moons are dropped before copying, and GM-only events are still left out. There are no new routes, and the API key is untouched.
Consumer-verified: Chronicle static/js/widgets/sky_pane.js:781 (SkyPane.Scene, what the globe draws through), sky_events.js:52 (parseDayEvents: an event's payload is a JSON string {type, moons}), sky_world.js:126 (makeSkym(cal)), sky_looks.js L.resolve/L.spec (each weather's recipe, which the stone marks are read from). These were read at Chronicle main 80dc1f0, and the vendored copies match it byte for byte (CHRONICLE_DIR=../Chronicle node --test tools/test-sky-clock.mjs).
Foundry compatibility: not yet run in a real Foundry world. It was checked in Chromium against a stub page with Foundry-style panels. The live checks are in TESTING.md under "Built-in calendar (Sky Clock)" and in #210.
Mockup: signed on Chronicle Sign-offs, card foundry-timepiece-208 (https://claude.ai/artifact/CCAHNue2kR39QpYGJnLbu8). The stone weather is back on the card for one more yes.

What this changes

Before: the only built-in calendar was a thin strip, which could shrink to a round clock icon.

After: each person picks the strip or the Sky Clock in Configure Settings → Calendar look.

  • The globe. A small glass globe sits in a corner of the screen.
    • Inside is Chronicle's own sky for the hour: sun, stars, moons and phases, weather, blood moons and eclipses.
    • The day of the month stands on the hill as a dark, weathered stone number, lit by the globe's sun or moon.
  • The day change. When the day changes, the stone crumbles and rebuilds as the next number.
  • Moving and shrinking. Dragging swirls the globe, then it snaps to the nearest corner clear of Foundry's panels. It can be locked or shrunk, and the small still globe replaces the strip's old round clock.
  • GM controls. The GM's click slides out a cradle with −1d, −1h, +1h and +1d, which step Chronicle's time through CalendarSync. On real-time calendars the buttons are disabled.
  • Weather on the stone. Every one of Chronicle's 42 weathers marks the stone. A campaign's own weathers draw like the nearest built-in. The marks are read from the sky's own recipe for each weather:
    • Rain darkens the stone, makes it shine and runs down it in drops, tinted green in acid rain and red in blood rain.
    • Snow settles on top, deeper in a blizzard. Hail rests in pellets, and frost rimes the edges in ice storms.
    • Fog and mist bead it with dew.
    • Sand and ash dust its tops, smoke blackens it and heat bleaches it. Leaves and petals come to rest on it.
    • Magic weathers glow from its cracks, and dead static drains its colour.
    • Rain, snow, hail and fog fall in front of the stone, read from the same recipe.
    • When the weather changes, the old marks fade out as the new ones roll in.

Why

Key Maker asked for a timepiece like Calendaria's. The design was signed off on the Sign-offs card: the Sky Clock name, date only, every sky effect, the GM cradle, the campaign's calendar only, a per-person look, snapping to corners, and the stone figure.

On approval, Key Maker noted that the weather on the rocks "seems to get stuck" and asked for every weather to be accounted for. The stuck look had a cause in the code. The stone's chipped edges were cut through the figure (destination-out), so the sky showed through them as pale spots that read as snow that never melted, and pale lichen added to it. Meanwhile only snow ever touched the stone. Chips are now shadowed hollows with a small nick through the outline, and the lichen is darker.

This PR targets the release after 2.2.0. T-B3 drove the motion levels and the fallback states.

Load-bearing lines

  • scripts/sky-clock.mjs: the globe.

    • loadSky falls back to a plain gradient if the sky scripts fail.
    • still() paints once below Full motion.
    • setView runs the crumble, the time glide and the weather roll.
    • weatherOf reads a weather from SkyLooks.resolve, or from plainRecipe before the sky loads.
    • stoneMarks and restingOnTops draw the weather on the stone.
    • crumble makes chips into hollows.
    • step warns and leaves the date alone on a refused write.
  • scripts/_sky-clock.mjs: the pure decisions.

    • Corners: clearOf and cradleLayout.
    • What the sky is given: skyCalendar and skyEvents.
    • Weather: stoneWeather, frontOf, mixWeather and plainRecipe.
    • framesPerSecond: 0 when hidden, still, shrunk or resting.
    • figureLight.
  • scripts/_calendar-view-model.mjs: buildPlayerSnapshot gains:

    • skyMoons (hidden moons filtered out before mapping)
    • hemisphere
    • preset_id and precipitation
    • the event's sky

    A null value stays null and never becomes 0 (given()).

  • scripts/vendor-chronicle.mjs: one shared Chronicle page stand-in for the shop room and the sky. It throws rather than replace one another script made.

  • vendor/chronicle/sky_*.js: 8 files copied unchanged from Chronicle.

  • fonts/AlfaSlabOne-Regular.ttf: OFL, with its licence alongside. Chronicle's package scan allows .ttf.

Honest deviations from the mockup

  • The mockup's separate "Still sky" control is covered by the existing Motion setting: anything below Full is still.
  • The weather roll-in uses Chronicle's own 6-second fade (SkyLooks.FADE_S) rather than the mockup's 2 seconds.
  • Chronicle's motion_rest.js is not vendored. The globe rests after its own 20 seconds without input, like the strip.
  • The mockup's sky is a simple stand-in fed by the same weather recipes. The stone marks use the same rules as the build.

Test plan

  • node --test tools/test-*.mjs: 1394 pass, 0 fail, 3 skipped. This includes tools/test-sky-clock.mjs with 16 tests. With CHRONICLE_DIR set it runs 17, the extra one comparing the vendored files with Chronicle byte for byte. Four of its tests are new:

    • all 42 weathers mark the stone in range, and clear leaves it dry
    • each kind of weather leaves its own mark
    • the plain fallback weathers
    • a weather change rolling across

    tools/test-calendar-view-model.mjs has 3 new snapshot tests, and tools/test-settings-form.mjs lists calendarLook as a personal setting.

  • CHRONICLE_DIR=../Chronicle node --test tools/test-sky-clock.mjs: 17 pass

  • node tools/check-package-descriptor.mjs: OK (0 warnings)

  • ./tools/check-comment-clutter.sh: OK

  • node tools/check-error-catalog.mjs: matches

  • Rendered in Chromium on a stub Foundry page with no page errors:

    • the stone in 20 weathers
    • day, shrunk, calm and the GM cradle stepping +1d
  • Manual verification in Foundry v14: the TESTING.md "Built-in calendar (Sky Clock)" checks (Check: the Sky Clock globe in a real Foundry v14 world #210)

  • CI passes

Tenet self-check

  • T-B1 security: the players' snapshot stays players-audience only, with hidden moons dropped.
  • T-B2 plugin isolation: changes stay within the module, and Chronicle code is vendored unchanged.
  • T-B3 production UI: the sky has a fallback gradient, refused steps get a warning, reduced motion is respected, and the weather marks are drawn once when still.
  • T-B4 docs: .ai.md, CLAUDE.md and TESTING.md are updated.

Each person can pick the strip or the Sky Clock (new client setting
calendarLook). The globe draws Chronicle's own sky code, vendored
unchanged, with the day as a weathered stone figure that crumbles into
the next number on a day change. It snaps to the nearest free corner,
shrinks to a small still globe (replacing the strip's old round clock),
and gives the GM a cradle that steps a day or an hour through
CalendarSync. The players' snapshot gains the visible moons, hemisphere,
weather presets and event sky types the globe needs, still built only
from players-audience reads. The shop room and the sky now share one
Chronicle page stand-in (vendor-chronicle.mjs).

Fixes #208

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GabHbsRZxjJVzRxVEsurj7
The stone figure's chips were cut through it, so the sky showed through
as pale spots that read as snow that never melted, and only snow ever
touched the stone. Chips are now shadowed hollows with a small nick in
the outline, the lichen is darker, and each weather's marks come from
the sky's own recipe for it (SkyLooks.resolve): wet stone with running
drops (tinted in acid and blood rain), snow and hail on the tops, frost,
dew, dust, soot, resting leaves or petals, magic glowing from the cracks,
heat bleaching, drained colour. Rain, snow, hail and fog in front of the
figure come from the same recipe, and a change of weather fades the old
marks out as the new ones roll in.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GabHbsRZxjJVzRxVEsurj7
@keyxmakerx
keyxmakerx marked this pull request as ready for review October 12, 2026 14:19
@keyxmakerx
keyxmakerx merged commit 6a67fe9 into main Oct 12, 2026
4 checks passed
@keyxmakerx
keyxmakerx deleted the claude/foundry-sky-clock-85vdwl branch October 12, 2026 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Timepiece: a small sky clock for the calendar

2 participants