diff --git a/docs/superpowers/specs/2026-05-16-timeago-shared-display-design.md b/docs/superpowers/specs/2026-05-16-timeago-shared-display-design.md new file mode 100644 index 0000000..ffc60e4 --- /dev/null +++ b/docs/superpowers/specs/2026-05-16-timeago-shared-display-design.md @@ -0,0 +1,248 @@ +# Shared relative-time display helper (spec) + +> Brainstorm scratch artifact. On approval, copy to +> `docs/superpowers/specs/2026-05-16-timeago-shared-display-design.md` +> and commit (per `AGENTS.md` planning-artifact convention). + +## Context + +`left4me`'s web UI renders datetimes inconsistently. Three styles coexist: + +1. **Raw Python `datetime` repr** in admin/blueprint/job tables + (`admin_users.html`, `blueprints.html`, `_job_table.html`, + `job_detail.html`) — unfriendly for users. +2. **Bespoke inline math** in `templates/_live_state.html` — three + expressions of the form `((now - x).total_seconds() // 60) | int }}m ago` + with their own vocabulary (`12s ago`, `0m ago` inside the first minute, + no singular handling). +3. **Centralised but Python-side** `humanize_delta` (in + `l4d2web/l4d2web/services/timeago.py`) called from `page_routes.py` for + `latest_job_when` and `latest_build_when`. Correct output but only + reachable by route-side precomputation, so adoption is friction-heavy. + +The existing `humanize_delta` also has three design gaps that make it +unsuitable as the single source of truth: + +- No sub-minute precision (under 45s it returns `just now`, hiding the + detail `_live_state.html` cares about). +- Future timestamps are clamped to `just now` (latent bug). +- Falls back to a bare ISO date (`2025-04-21`) after 7 days, which + reads awkwardly next to relative siblings. + +This spec unifies the three styles behind one Jinja filter, fixes the +ladder, and leaves a known follow-up. + +## Goal + +Every user-facing datetime in `l4d2web` templates flows through one +filter, `{{ ts | timeago }}`, producing a self-describing HTML `