Skip to content

Add Stopwatch and Countdown facades over the elapsed anchor#7

Merged
boatmeme merged 2 commits into
mainfrom
implement-stopwatch-countdown
Jun 28, 2026
Merged

Add Stopwatch and Countdown facades over the elapsed anchor#7
boatmeme merged 2 commits into
mainfrom
implement-stopwatch-countdown

Conversation

@boatmeme

Copy link
Copy Markdown
Owner

What & why

Adds the two presentation clocks from issue #4 (step 3), built on the run-relative
elapsed anchor landed in #6: Stopwatch (counts up) and Countdown (counts down
to a real deadline). Both are thin views over a Clock.

API

  • new Stopwatch(distortions?)elapsedInMillis (warped), referenceElapsedInMillis (real).
  • new Countdown(target: Duration, distortions?)remainingInMillis (warped, clamped at
    0
    ), isComplete, elapsedInMillis, targetInMillis.
  • Both build their Clock internally and expose it via .clock.
  • Clock gains runStartInMillis (the run anchor / t=0).

The headline behavior: because the offset is cumulative — a dilation repaid by a later
compression — a countdown can crawl early and sprint late yet still reach zero exactly on
the real deadline
(covered by a test).

Housekeeping

  • Extracted Duration + durationToMillis into src/duration.ts (was private to
    RelativeTimeDistortion), reused by Countdown; RelativeTimeDistortion re-exports
    Duration so existing imports are unaffected.
  • Exports Stopwatch, Countdown, and the Duration type.

Tests / docs

  • New Stopwatch and Countdown suites — 61 tests total, tsc --noEmit and eslint clean.
  • README "Stopwatch & Countdown" section with worked examples.

Not in this PR

The absolute anchor + true multi-day spans (step 4), daily recurrence, and eased
distortions. No version bump (0.2.0 isn't shipped yet).

Refs #4

🤖 Generated with Claude Code

Thin presentation clocks built on the run-relative (elapsed) anchor. Both
take the same distortions array a Clock does and start their run at
construction.

- Stopwatch counts up in warped time: elapsedInMillis (warped) and
  referenceElapsedInMillis (real), via relativeTimeInMillis - runStart.
- Countdown counts down to a real-time target: remainingInMillis (clamped
  at zero), isComplete, elapsedInMillis, targetInMillis. Because the
  offset is cumulative (a dilation repaid by a later compression), it can
  crawl early and sprint late yet still reach zero on the real deadline.
- Clock exposes runStartInMillis (the run anchor) so the facades measure
  warped time since start.
- Extract the shared Duration interface and durationToMillis helper into
  src/duration.ts; RelativeTimeDistortion re-exports Duration for compat.
- Export Stopwatch, Countdown, and the Duration type.

Adds Stopwatch and Countdown tests (including the crawl-early/sprint-late
countdown that lands on zero at the real deadline) and a README section.
Full suite green (61 tests), tsc and eslint clean. No version bump.

Refs #4

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@boatmeme boatmeme merged commit 6ea1209 into main Jun 28, 2026
4 checks passed
@boatmeme boatmeme deleted the implement-stopwatch-countdown branch June 28, 2026 05:30
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.

Generalize the distortion window anchor (unlocks multi-day, stopwatch, and countdown modes)

1 participant