From 533ce89cea29f0ff56d7bc103b940212f33d7db0 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Wed, 18 Feb 2026 14:19:42 -0700 Subject: [PATCH] backlog: add system clock heartbeat service task (TASK-47) Server-side clock broadcasting time signals via Event Bus for shapes to subscribe to periodic events (tick, hourly, daily). Co-Authored-By: Claude Opus 4.6 --- ...ock-heartbeat-service-for-rSpace-canvas.md | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 backlog/tasks/task-47 - Implement-System-Clock-heartbeat-service-for-rSpace-canvas.md diff --git a/backlog/tasks/task-47 - Implement-System-Clock-heartbeat-service-for-rSpace-canvas.md b/backlog/tasks/task-47 - Implement-System-Clock-heartbeat-service-for-rSpace-canvas.md new file mode 100644 index 0000000..f1c6324 --- /dev/null +++ b/backlog/tasks/task-47 - Implement-System-Clock-heartbeat-service-for-rSpace-canvas.md @@ -0,0 +1,91 @@ +--- +id: TASK-47 +title: 'Implement System Clock / Heartbeat Service for rSpace canvas' +status: To Do +assignee: [] +created_date: '2026-02-18 22:30' +labels: + - feature + - infrastructure + - ecosystem +milestone: m-1 +dependencies: + - TASK-43 +references: + - rspace-online/backlog/tasks/task-43 - Implement-Event-Broadcasting-canvas-wide-pub-sub-system.md + - rSpace-website/docs/R-ECOSYSTEM-ARCHITECTURE.md +priority: high +--- + +## Description + + +Add a server-side System Clock service that broadcasts consistent time signals across the rSpace canvas via the Event Bus (TASK-43). This provides a shared temporal heartbeat that all shapes, modules, and connected r-ecosystem apps can subscribe to. + +**Why**: Currently there is no shared sense of time passing in rSpace. Individual shapes have no way to trigger time-based behavior (recurring updates, countdowns, reminders, periodic recalculations). A system clock provides the foundational "pulse" that time-aware features depend on. + +### Architecture + +New file `server/clock-service.ts`: +- `SystemClock` class running server-side (not per-client) +- Emits events on the CanvasEventBus at configurable intervals: + - `clock:tick` — every 60 seconds (primary heartbeat) + - `clock:minute:5` — every 5 minutes + - `clock:hourly` — every hour + - `clock:daily` — at midnight UTC (configurable timezone) +- Payload includes: `{ timestamp, isoString, hour, minute, dayOfWeek, tickCount }` +- Single authoritative source — server emits, clients receive via CRDT sync +- Graceful degradation: if server is offline, clients can run a local fallback clock + +### Shape Integration + +Shapes opt in by subscribing to clock channels: +```typescript +// In a Budget shape +subscriptions: ['clock:hourly'] +onEventReceived(channel: 'clock:hourly', payload) { + this.recalculate(); +} + +// In a Countdown shape +subscriptions: ['clock:tick'] +onEventReceived(channel: 'clock:tick', payload) { + this.updateRemaining(payload.timestamp); +} +``` + +### Use Cases + +- **Timer/Countdown shapes**: Update display every tick +- **Budget/Finance shapes**: Recalculate on hourly boundaries +- **Calendar shapes**: Highlight "now" marker, trigger reminders +- **Presence decay**: Mark users idle after N missed ticks +- **Backlog surfacing**: External services can subscribe to clock events to trigger task reviews +- **rTime.space foundation**: This clock becomes the temporal primitive that rTime.space builds on +- **Workflow triggers**: "Run this workflow every day at 9am" + +### Configuration + +Server-level config in community settings: +- `clock.enabled: true` (default true) +- `clock.timezone: 'UTC'` (for daily boundary) +- `clock.tickInterval: 60` (seconds, minimum 10) +- `clock.channels: ['tick', 'minute:5', 'hourly', 'daily']` + +### Performance Considerations + +- Clock events should NOT flood the CRDT eventLog — use a separate lightweight channel or mark as ephemeral (not persisted in ring buffer) +- Server-side only emission prevents N clients from emitting N duplicate ticks +- Tick events are fire-and-forget, no ack required + + +## Acceptance Criteria + +- [ ] #1 SystemClock emits `clock:tick` every 60s via CanvasEventBus +- [ ] #2 Configurable intervals: tick, 5-min, hourly, daily +- [ ] #3 Server-authoritative — only one clock source per canvas +- [ ] #4 Shapes can subscribe to clock channels and receive time payloads +- [ ] #5 Clock events are ephemeral (not persisted in CRDT eventLog ring buffer) +- [ ] #6 Fallback local clock when server connection is lost +- [ ] #7 Clock can be enabled/disabled per community in settings +