Skip to content

Changelog

All notable changes to pomban are documented in this file.

Format follows Keep a Changelog; the project adheres to Semantic Versioning.

Unreleased

0.3.0 — 2026-06-12

Minor release. Onboarding + planning UX polish: the help overlay now explains how each screen works, sprint creation gets a real modal, and new users get a one-shot walkthrough on first launch plus a rotating tip overlay on subsequent launches.

Added

  • Context-aware ? help. Every AppScreen may declare a HELP_INTRO string explaining the screen's mental model (columns, modes, the gist of how to use it). The help overlay renders that intro above a "Keymap" heading and the per-screen bindings list; the title changes to pomban — <Screen> so it's clear which surface you're reading help for. Dashboard, Kanban, Stats, History, Today, Projects, and Sprints all ship intros.
  • SprintCreateModal — structured 4-field sprint creation (name, pomodoro target, duration days, goal). Replaces the inline-input parsing on the Sprints screen and the implicit 14-day shell that the Projects screen's s binding used to create. Ctrl+S or Enter on any field submits; Esc cancels. The engine helper PombanEngine.create_sprint_for_project gains pomodoro_target and goal kwargs to match.
  • First-launch WelcomeModal + rotating StartupTipModal. On the first launch after the DB has at least one project, a full-page walkthrough modal explains the platform model and the main keymap. On every subsequent launch a short tip overlay rotates through 12 tips. Both gated by the new [ui].show_startup_tips config flag (default true); set it to false to disable both surfaces.

Changed

  • The s binding on the Projects screen now opens the new SprintCreateModal instead of synchronously creating a 14-day shell sprint. The n binding on the Sprints screen does the same.

0.2.1 — 2026-06-12

Patch release. Two interaction bugs that made v0.2.0 hard to use on a fresh DB. v0.2.0 has been yanked from PyPI in favour of this release.

Fixed

  • Project picker swallowed Enter. Submitting a task with no @project opened the project picker modal, but pressing Enter dismissed it with None instead of selecting the highlighted row — the task was silently lost. The modal now listens for ListView.Selected (which is what Textual's ListView actually emits on Enter), focuses the list on mount, and seeds the highlighted index at 0 so the first keystroke isn't wasted.
  • Kanban task selection didn't work and the focused card never highlighted. The docked Input grabbed initial focus so j / k / h / l were typed into it instead of moving the cursor; and _paint_cursor() ran before body.mount(TaskCard...) had landed in the DOM so even after focus was fixed the first paint missed every card. The Input now stays out of the focus chain until you press n / / / g, and the cursor paints via call_after_refresh so the newly-mounted cards are visible to it.

0.2.0 — 2026-06-12

The "personal productivity platform" release. Tasks now live inside sprints inside projects, every screen carries that context, and the focus loop grows blocker capture, session notes, a Today digest, and quiet-hours-aware notifications. Exports gain CSV / JSON / grouped markdown for downstream review.

Changed

  • Renamed package from pomodoro to pomban. PyPI distribution, CLI binary, Python package, and XDG directories all migrate to the pomban name. On first launch, a one-shot migration shim renames the legacy ~/.local/share/pomodoro/, ~/.local/state/pomodoro/, and ~/.config/pomodoro/ directories (and the pomodoro.db / pomodoro.log files inside them) to their pomban equivalents. No-op when the new paths already exist.
  • Schema v10tasks.project_id becomes NOT NULL (legacy rows migrate to an auto-seeded "Inbox" project); tasks.sprint_id / sprints.project_id FKs added; "one active sprint per project" enforced in code (see ADR-0005).
  • README + docs site reframed around the platform model (Plan / Focus / Review / Integrate) rather than "Pomodoro TUI".
  • Notifications route through a single notifications.notify(...) funnel that consults the working-hours gate before firing desktop popup / sound channels.

Added

  • Project → sprint → task hierarchy as the platform's planning model. Inline @project / !sprint / #tag / ~N syntax for keyboard-driven assignment (ADR-0005).
  • Context header on every screen — active project + sprint chip
  • quiet-state chip, refreshed on every tick.
  • Dashboard + Kanban sprint panels — current sprint progress pinned to the planning screens.
  • PombanEngine facade (core/engine.py) owns timer + session orchestration end-to-end. app.py loses ~200 lines of lifecycle plumbing (ADR-0006).
  • FirstRunModal — empty-DB launches walk through creating the first project so the hierarchy is never empty.
  • SprintRunnerScreen (Shift+R) — overlay with the current sprint goal pinned regardless of which screen is active.
  • SprintCompleteScreen — fires when pomodoro_target is crossed; closes the sprint with a retro field.
  • Inline s binding on the Projects screen creates and activates a sprint for the focused project in one keystroke.
  • Blocker capture (b) — log a one-line blocker against the live focus session without breaking the timer.
  • Session notes — session-end modal field surfaces inline on the History screen.
  • Today digest (7) — daily recap screen with sessions, top tasks, interruptions, and blocker list bound to the 7 digit.
  • Per-tag analytics panel on the Stats screen (3), powered by minutes_per_tag.
  • Exportspomban export --format csv|json|markdown. The grouped-markdown format buckets sessions by project → sprint → task. pomban sprint export … for per-sprint reports.
  • Working-hours quiet[breaks].working_hours_start / working_hours_end ("HH:MM") suppress desktop popup + sound outside the window; the in-TUI bell still fires; header chip reflects the current quiet state (ADR-0004).
  • ROADMAP.md and RELEASE_PLAN.md at the repo root — forward-looking phase plan and the mechanics of cutting a release (tag-driven via release.yml).
  • CHANGELOG.md, CONTRIBUTING.md, SECURITY.md, and CLAUDE.md at the repo root — keep-a-changelog history, contributor onboarding, vulnerability-disclosure policy, and internal conventions spec.
  • mkdocs-material documentation site scaffolded under docs/site/ with index, install, quickstart, troubleshooting, ADR index, and changelog pages alongside the existing user-guide / keybindings / configuration / development pages. Auto-deployed via .github/workflows/docs.yml on every push to main that touches the docs.
  • Architecture Decision Records under docs/adr/. Seeded with three retrospective ADRs (stack choice, single-SQLite-connection policy, layered-screen architecture); v0.2.0 adds three more — ADR-0004 (working-hours quiet), ADR-0005 (PM hierarchy), and ADR-0006 (PombanEngine facade).
  • scripts/capture_screenshots.py — Textual pilot harness that drives PomodoroApp against an in-memory DB and emits hero SVGs for the dashboard, kanban, and stats screens.
  • docs/demo.tape — vhs script for an animated README hero. Render with vhs docs/demo.tape (requires vhs/ffmpeg/ttyd).
  • .pre-commit-config.yaml with ruff, mypy, and the standard pre-commit-hooks (end-of-file-fixer, trailing-whitespace, yaml, large-files).
  • requirements/base.in + requirements/dev.in mirroring the pyproject.toml dependency tables for pip-tools workflows.
  • docs and mypy extras under [project.optional-dependencies].
  • .github/workflows/release.yml and docs.yml — tag-driven PyPI publish via OIDC trusted publishing plus CHANGELOG-extracted GitHub Release notes; conditional docs deploy to GitHub Pages.

0.1.0 — 2026-06-11

Initial pre-release of the pomban dashboard TUI. Captures every feature shipped on main to date.

Added

  • Pomodoro timer engine (core/timer_engine.py) with focus, short-break, long-break, lunch-pause, and idle phases; configurable cycle counts; auto-advance toggle; extend, skip, and restore state transitions.
  • Dashboard screen — timer, focused-task chip, stats strip, task list, inline #tag/@project/!sprint/~N task syntax.
  • Kanban board (2) with priorities, due dates (overdue render red), per-column WIP limits ([kanban] config), board search (/), bulk visual-mode actions (v then Space/c/d/Shift+H,L), and a card detail screen (i).
  • Stats screen (3) — daily / weekly / monthly bucket views, top tasks, interruption stats.
  • History screen (4) — every session, paged, with planned vs. actual durations.
  • Projects screen (5) and Sprints screen (6) — full CRUD, archiving, completion states; tasks released back to backlog on sprint delete.
  • Resume prompt — quit mid-focus, get a "resume? y/n" overlay on next launch.
  • Lunch breakShift+L triggers a long pause anywhere; the session-end modal suggests it inside a configurable [breaks].lunch_window_*.
  • Presets[[preset]] blocks switchable via p; classic 25/5, deep-work 50/10, sprint 15/3 ship as defaults.
  • Themesnord, gruvbox, dracula, catppuccin-mocha, tokyo-night. Cycle with t; persisted to config.toml.
  • Auto-advance (Shift+T) — skip the end-of-phase modal and roll straight into the next phase, classic-Pomodoro style.
  • Hooks[hooks].on_focus_start / on_focus_end / on_break_start / on_break_end shell commands invoked with POMODORO_PHASE and POMODORO_TASK_TITLE env vars.
  • In-process plugins — Python entry points discovered at startup; exceptions are sandboxed and never crash the app.
  • git_sync plugin — commits the SQLite library on exit so it can sync across devices via a personal git remote.
  • btop-style panel hotkeyswidgets/panel.py + AppScreen.action_focus_pane give each pane a highlighted-letter selector (Dashboard: i Timer, a Tasks).
  • Structured logging via core/log.py — file-only writes to ~/.local/state/pomban/pomban.log; never touches stdout while the TUI owns the terminal.

Removed

  • Music / cliamp subsystem — the entire [music] config section, music controller, dashboard music panel, dedicated music screen, and --with-music CLI flag. No DB impact (music state was read live from the external player and never persisted).

Fixed

  • Six meaningful except Exception: pass sites in app.py now route to log.exception (four DB reads, two save_config calls). Cosmetic notify/bell/animate sites are intentionally left silent.

Resolved code-review issues (cumulative)

Tracked in .code_review/code_review_issues.md.

  • ISSUE-001 — DB writes on the tick path (won't-fix): mitigations stand (cached lunch SELECT, deferred modal push). A dedicated writer thread would conflict with the project's single-SQLite-connection design. Revisit only if real-world jank is observed. See ADR-0002.
  • ISSUE-005 — slim PomodoroApp (resolved): core/filter_state.py, core/session_coordinator.py, and core/task_input.py extractions all landed. Music removal trimmed the remaining UI-action surface.
  • ISSUE-012 — swallowed excepts (resolved): see Fixed above.