Skip to content

feat(pomodoro): Pomodoro timer app (spec + plan + ADR + implementation)#1

Open
TheBeege wants to merge 2 commits into
mainfrom
feat/pomodoro
Open

feat(pomodoro): Pomodoro timer app (spec + plan + ADR + implementation)#1
TheBeege wants to merge 2 commits into
mainfrom
feat/pomodoro

Conversation

@TheBeege
Copy link
Copy Markdown
Member

Summary

  • Implements the Pomodoro timer demo app per specs/2026-05-30-pomodoro-timer.md (spec is now Delivered).
  • Runs with a single command (python3 server.py) on stock Python — no packages, no build step, no database.
  • All timer logic is client-side vanilla JS with a wall-clock anchor so background-tab throttling cannot accumulate timing drift.

Files changed

File Purpose
index.html Single-page SPA shell; stable DOM contract (#time-remaining, #interval-type, #cycle-progress, #btn-*, #app[data-interval], aria-live regions)
app.js All state machine + timer logic; pure helpers (nextInterval, formatMMSS) exposed on window.Pomodoro for testability
styles.css Clean demo-presentable layout; per-interval colour theming via CSS attribute selectors; no external fonts/CDN
server.py ThreadingHTTPServer + SimpleHTTPRequestHandler subclass; directory-anchored; Cache-Control: no-store; respects PORT env; clean Ctrl+C
tests/test_cycle.html Self-running pure-logic test harness — 25 assertions: full cycle sequence, skip rules (FR-11), exactly-once transition, 5-minute background-jump clock test
adr/2026-05-30-client-side-timer-static-server.md ADR: client-side timer + Python static server
specs/2026-05-30-pomodoro-timer.md Spec (status: Ratified → Delivered)
plans/2026-05-30-pomodoro-timer.md Implementation plan
README.md Added "Pomodoro Timer — Quick Start" section with run instructions and controls table
adr/README.md ADR index updated

Intentional interface/contract changes

This is greenfield — no existing contracts are altered. The contracts introduced:

  • DOM IDs (#time-remaining, #interval-type, #cycle-progress, #btn-start/pause/skip/reset, #app[data-interval]) — stable; tests depend on them.
  • window.Pomodoro namespace exposing formatMMSS, nextInterval, getState, setNow, and control functions for the test harness.
  • server.py honours PORT env var (default 8000) and serves files from the script's directory.

ADRs added

  • adr/2026-05-30-client-side-timer-static-server.md (status: Proposed) — records the decision to keep all timer state client-side and reduce the Python backend to a stdlib static file server. Documents alternatives rejected (server-authoritative timer, frameworks, counter-decrement countdown, JSON persistence).

Verification results

Check Result
python3 -m py_compile server.py PASS
Server smoke: curl /, /app.js, /styles.css, /tests/test_cycle.html All HTTP 200
Cache-Control: no-store header present Confirmed
Pure-logic tests (Node.js headless): 25 assertions 25 passed, 0 failed
Background 5-minute clock jump within 1s tolerance PASS
Exactly-once transition (fake clock seam) PASS
Manual UI smoke (requires browser) Not verified programmatically — covered by unit tests

Spec / Plan

  • Spec: specs/2026-05-30-pomodoro-timer.md
  • Plan: plans/2026-05-30-pomodoro-timer.md

🤖 Generated with Claude Code

TheBeege and others added 2 commits May 30, 2026 01:41
…ntation

Implements specs/2026-05-30-pomodoro-timer.md (Ratified → Delivered).

The app runs with `python3 server.py` on a stock Python install; no external
packages, no build step, no database. All timer logic is client-side vanilla JS
using a wall-clock anchor (Date.now()) so background-tab throttling reduces UI
refresh rate without accumulating timing drift.

Files added:
- index.html / app.js / styles.css — single-page Pomodoro SPA
- server.py — Python stdlib ThreadingHTTPServer, directory-anchored, Cache-Control: no-store
- tests/test_cycle.html — self-running pure-logic test harness (25 tests, 0 failures)
- adr/2026-05-30-client-side-timer-static-server.md — records the client-side
  timer + static-server architecture decision (status: Proposed)
- specs/ and plans/ artifacts committed alongside the code

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…de, ADR status

P1: signalTransition() now captures the completed interval's label before
calling nextInterval(), so the aria-live announcement correctly reads
"<completed> — interval complete. <next> starting next." (was using the
next label for both sides). Added a test assertion that confirms the
completed and next labels differ for a Work → Short Break transition.

P3: Remove dead _skipInProgress flag from skip(); completeInterval() already
sets phase='idle' synchronously, making the flag unreachable. Remove unused
`import sys` and the no-op log_message override from server.py.

P2: Mark ADR 2026-05-30-client-side-timer-static-server as Accepted (this
branch implements and is merge-ready) in both the ADR file and the README
index, per adr/README.md lifecycle rules.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

1 participant