# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.8.0] - 2026-06-09

### ✨ Features

- feat(system): emit PixelArt sprites for monitor_cpu ([c488add](https://github.com/unhappychoice/splashboard/commit/c488add))
- feat(system): emit PixelArt sprites for monitor_battery ([6cfbcd6](https://github.com/unhappychoice/splashboard/commit/6cfbcd6))
- feat(system): pixel-art sprite catalog for the monitor family ([f051c72](https://github.com/unhappychoice/splashboard/commit/f051c72))
- feat(clock): PixelArt sprites for moon_phase and season ([9e48fa3](https://github.com/unhappychoice/splashboard/commit/9e48fa3))
- feat(read_store): support PixelArt shape ([792cdbd](https://github.com/unhappychoice/splashboard/commit/792cdbd))
- feat(weather): emit PixelArt sprites for current conditions ([ca78384](https://github.com/unhappychoice/splashboard/commit/ca78384))
- feat(render): add PixelArt shape + media_pixel renderer ([b275bde](https://github.com/unhappychoice/splashboard/commit/b275bde))

### 🐛 Bug Fixes

- fix(weather): thicken fog sprite bands for half-block readability ([f14bd32](https://github.com/unhappychoice/splashboard/commit/f14bd32))

### 📝 Other Changes

- chore: bump version to v2.8.0 ([93ea391](https://github.com/unhappychoice/splashboard/commit/93ea391))
- chore(deps)(deps): bump ratatui-image from 11.0.2 to 11.0.3 ([ef93a3f](https://github.com/unhappychoice/splashboard/commit/ef93a3f))
- chore(deps)(deps): bump netdev from 0.43.0 to 0.44.0 ([b314eae](https://github.com/unhappychoice/splashboard/commit/b314eae))
- chore(deps)(deps): bump chrono from 0.4.44 to 0.4.45 ([8add2a5](https://github.com/unhappychoice/splashboard/commit/8add2a5))
- chore(ci)(deps): bump codecov/codecov-action from 6 to 7 ([505b58d](https://github.com/unhappychoice/splashboard/commit/505b58d))
- test(render): cover media_pixel in registry / shape / snapshot lists ([22251b1](https://github.com/unhappychoice/splashboard/commit/22251b1))
- chore(deps)(deps): bump gix from 0.83.0 to 0.84.0 ([5fe5a50](https://github.com/unhappychoice/splashboard/commit/5fe5a50))
- chore(deps)(deps): bump sysinfo from 0.39.2 to 0.39.3 ([0431c78](https://github.com/unhappychoice/splashboard/commit/0431c78))
- chore: sync llm pricing from LiteLLM ([641adcb](https://github.com/unhappychoice/splashboard/commit/641adcb))
- test(fetcher/codex_usage): compute fixture path from today's date ([ac64f2f](https://github.com/unhappychoice/splashboard/commit/ac64f2f))
- chore(deps)(deps): bump serde_json from 1.0.149 to 1.0.150 ([80f0ab6](https://github.com/unhappychoice/splashboard/commit/80f0ab6))
- chore(ci)(deps): bump peter-evans/create-pull-request from 7 to 8 ([b985319](https://github.com/unhappychoice/splashboard/commit/b985319))
- chore: update flake.nix hashes for v2.7.0 ([e2b8b74](https://github.com/unhappychoice/splashboard/commit/e2b8b74))


## [2.7.0] - 2026-05-24

### ✨ Features

- feat(fetcher): add shared llm_pricing helper ([cf40ec1](https://github.com/unhappychoice/splashboard/commit/cf40ec1))
- feat(fetcher): add codex_subscription — rate-limit utilisation from local JSONL ([1b5d7b2](https://github.com/unhappychoice/splashboard/commit/1b5d7b2))
- feat(fetcher): add codex_usage — local Codex CLI session rollup ([ebb7760](https://github.com/unhappychoice/splashboard/commit/ebb7760))
- feat(fetcher/codex): scaffold module + shared session helpers ([b8c1be2](https://github.com/unhappychoice/splashboard/commit/b8c1be2))
- feat(fetcher): add claude_subscription — Max-plan utilisation via oauth/usage ([59e3fdc](https://github.com/unhappychoice/splashboard/commit/59e3fdc))
- feat(fetcher): add claude_code_usage — local Claude Code session rollup ([9a0111d](https://github.com/unhappychoice/splashboard/commit/9a0111d))

### 🐛 Bug Fixes

- fix(fetcher/codex): address coderabbit review findings ([aad0c6e](https://github.com/unhappychoice/splashboard/commit/aad0c6e))
- fix(fetcher/claude_code_usage): address coderabbit review findings ([73f6808](https://github.com/unhappychoice/splashboard/commit/73f6808))

### 📝 Other Changes

- chore: bump version to v2.7.0 ([5e822fc](https://github.com/unhappychoice/splashboard/commit/5e822fc))
- perf(fetcher/claude_code_usage): skip stale JSONL files by mtime ([6d09272](https://github.com/unhappychoice/splashboard/commit/6d09272))
- perf(fetcher/codex_usage): skip JSONL files outside the since window by filename ([bfc728f](https://github.com/unhappychoice/splashboard/commit/bfc728f))
- test(fetcher/codex): cover render_body branches for each shape ([a01d64f](https://github.com/unhappychoice/splashboard/commit/a01d64f))
- refactor(fetcher/claude_code_usage): use shared llm_pricing helper ([07939bb](https://github.com/unhappychoice/splashboard/commit/07939bb))
- refactor(fetcher/codex_usage): use shared llm_pricing helper ([c55aa0c](https://github.com/unhappychoice/splashboard/commit/c55aa0c))
- chore: sync llm pricing daily via Actions ([ad0978a](https://github.com/unhappychoice/splashboard/commit/ad0978a))
- test(fetcher): restore SPLASHBOARD_HOME via RAII guard for panic safety ([8bfd057](https://github.com/unhappychoice/splashboard/commit/8bfd057))
- test(fetcher/gitlab/common): assert structural project path instead of hard-coded slug ([2d18654](https://github.com/unhappychoice/splashboard/commit/2d18654))
- test(render/media_image): cover draw_thumbnail's zero-sized area guard returning `Ok` before any image load, so a degenerate zero-width or zero-height layout slot can't surface a spurious `[image: …]` error — only reachable by calling `draw_thumbnail` directly, since the public render path never hands a renderer a zero-sized area ([7f16c4c](https://github.com/unhappychoice/splashboard/commit/7f16c4c))
- test(fetcher/git/repo_name): cover fetch's `"project"` literal fallback when the cwd is the filesystem root, where there is no directory basename and no git repo above it so both arms of `detect_name` come up empty ([b46b452](https://github.com/unhappychoice/splashboard/commit/b46b452))
- test(xtask/themes): cover pretty_name's `None` arm for empty underscore segments rendering as blank words, theme_for's `unwrap_or_default` fallback materialising the default theme for an unknown slug, and render_one's happy path plus both failure contexts: a missing demo config failing `render_config_html_with_theme`'s `read_to_string`, and an output path pre-created as a directory surfacing the `write` context after a successful render ([582a811](https://github.com/unhappychoice/splashboard/commit/582a811))
- test(render/animated_splitflap): cover apply_flap's guard and continue arms — bailing out on a zero-sized area, taking the `elapsed_ms >= settle_at` continue so a fully settled cell keeps its original glyph past the animation window, and the `else { continue }` arm resolving out-of-range cells to no cell instead of panicking when the area overflows the buffer ([545d511](https://github.com/unhappychoice/splashboard/commit/545d511))
- test(render/chart_histogram): cover render_histogram's own empty-series guard (only reachable by calling it directly, since render_payload short-circuits empty bodies upstream) leaving the buffer blank, and boost_to_visible passing an all-zero count slice straight through when the zero peak leaves nothing to lift ([dc72516](https://github.com/unhappychoice/splashboard/commit/dc72516))
- test(render/grid_table): cover the inline layout honouring right alignment so content sits flush against the right edge with leading padding, and render's defence-in-depth guard drawing nothing instead of panicking when handed a non-Entries body directly ([fbbb28a](https://github.com/unhappychoice/splashboard/commit/fbbb28a))
- test(xtask/preset_index): cover run's create and write failure paths — surfacing the `create` context when a directory component is a regular file and the `write` context when the index path is pre-created as a directory, with a shared unique_temp_dir helper tagging each case ([ebfe8ee](https://github.com/unhappychoice/splashboard/commit/ebfe8ee))
- test(render/chart_sparkline): cover render leaving the slot untouched when handed a non-NumberSeries body, the line style emitting a blank chart for an empty value window, and draw_line_series/draw_zero_baseline's defence-in-depth guards for a zero-sized area, an over-long value slice, and mid/bottom rows past the buffer ([037092b](https://github.com/unhappychoice/splashboard/commit/037092b))
- test(render/list_ranking): cover fit_label's zero-width, pad, and truncate-with-ellipsis branches, pad_left prepending spaces only when shorter than the target width, and align_rect offsetting for center/right while passing the area through unchanged for no hint, zero content width, or content wider than the area ([8a0b507](https://github.com/unhappychoice/splashboard/commit/8a0b507))
- test(render/text_ascii): cover figlet_wrapped's raw-input fallback when the font renders nothing (empty string and all-control-code input), blocks_width and pixel_name taking the conservative defaults on an unrecognised PixelSize, and render's defence-in-depth Body::Text guard drawing a blank cell instead of panicking when handed a non-Text body ([0d78814](https://github.com/unhappychoice/splashboard/commit/0d78814))
- test(fetcher/code/scan): cover the tracked walkers' early-continue branches — `for_each_tracked_path` and `for_each_tracked_file` skipping a symlink that fails `is_regular_file` and (Linux-only) a non-UTF-8 path that fails the `str::from_utf8` decode, asserting only the regular `keep.rs` entry is ever visited ([531bcca](https://github.com/unhappychoice/splashboard/commit/531bcca))
- test(cli/cache): cover run_cache subcommand dispatch — Path resolving the cache dir under SPLASHBOARD_HOME, List treating a missing cache dir as empty in both plain and json modes, Clear removing seeded .json/.lock entry files, and Clear with a widget_id dispatching through run_cache_clear to clear_one's no-entry diagnostic ([5dd4af4](https://github.com/unhappychoice/splashboard/commit/5dd4af4))
- test(xtask/html_snapshot): cover color_hex mapping every ANSI-16 named color to its exact hex value, exercising all sixteen Color enum arms from Black through White including the dim and Light* bright variants ([28f00b2](https://github.com/unhappychoice/splashboard/commit/28f00b2))
- test(fetcher/deal/free_games): cover Platform's config_value tokens and url_slug codes for all nine storefronts, feed_url slug embedding for every non-aggregate platform, and parse_platform/parse_kind case-insensitive matching of every known storefront and the explicit game keyword ([ccf0365](https://github.com/unhappychoice/splashboard/commit/ccf0365))
- test(runtime): cover finalize_splash restoring cursor visibility so the post-splash shell prompt gets a visible cursor, asserting an explicit hide is flipped back to shown via TestBackend's cursor-visibility debug output ([9b98aa6](https://github.com/unhappychoice/splashboard/commit/9b98aa6))
- test(render/list_links): cover render_links's zero-dimension area early return, write_row's no-op arm when set_stringn draws zero cells, and the OSC 8 suppression paths skipping the hyperlink wrap in both write_row and wrap_osc8 ([90f5abc](https://github.com/unhappychoice/splashboard/commit/90f5abc))
- test(fetcher/gitlab/common): cover payload's metadata-unset wrapping, project_from_url's https-userinfo bail when the credential chunk embeds a slash, and resolve_project's cwd-git-remote fallback recovering the project path from the origin URL ([eb4eba3](https://github.com/unhappychoice/splashboard/commit/eb4eba3))
- test(fetcher/huggingface_trending): cover render_sync TextBlock shape emitting one rank-prefixed line per entry, with the heart count and the optional download count formatted and the latter omitted when absent ([1e9c943](https://github.com/unhappychoice/splashboard/commit/1e9c943))
- test(fetcher/github/action_status): cover render_body Entries shape for the classified status/branch/conclusion rows and the conclusion `?` fallback when a still-running workflow has no conclusion ([804d95b](https://github.com/unhappychoice/splashboard/commit/804d95b))
- test(render/list_cards): cover natural_height's non-ImageLinkedList fallback arm, render_cards and draw_text zero-dimension no-op guards, and the draw_thumbnail path via a missing-file card whose image-load error is swallowed ([128d0d6](https://github.com/unhappychoice/splashboard/commit/128d0d6))
- test(render/animated_figlet_morph): park until process uptime clears the 260ms fade window so render_morph deterministically takes the crossfade-out branch instead of the fade-in path a fast suite would otherwise hit ([dfe38fd](https://github.com/unhappychoice/splashboard/commit/dfe38fd))
- test(fetcher/steam/games): cover text_block_body and entries_body empty-input placeholder arms, plus image_linked_body and image_body cached-thumbnail resolution via pre-seeded cache files without network I/O ([d588376](https://github.com/unhappychoice/splashboard/commit/d588376))
- test(fetcher/steam/player_summary): cover avatar download and thumbnail-cache resolution for ImageLinkedList and Image bodies over a local HTTP server, asserting the cached .png path is reused without a second request ([5f9a47d](https://github.com/unhappychoice/splashboard/commit/5f9a47d))
- test(fetcher/wikipedia/trending): cover ImageLinkedList thumbnail resolution over a local HTTP server for fetch_thumbnail_url source extraction, missing-thumbnail and request-failure None arms, plus the empty-article chain entry ([71e32d1](https://github.com/unhappychoice/splashboard/commit/71e32d1))
- test(fetcher/news): cover fetch shape dispatch over a local HTTP server for default/text-block/image/image-linked bodies, the count clamp, and parse/status error surfacing ([3bc0b7b](https://github.com/unhappychoice/splashboard/commit/3bc0b7b))
- test(cache): cover warm_from None-disk arm, is_lock_stale missing-file bail, ensure_parent parentless path, io_err Other-kind wrapping, and try_acquire_with lock-dir creation failure ([ab3c2a8](https://github.com/unhappychoice/splashboard/commit/ab3c2a8))
- test(cache/clear): cover clear_one missing-widget and realtime-fetcher errors, empty-cache diagnostic, and entry/lock removal in plain and json modes ([1bba315](https://github.com/unhappychoice/splashboard/commit/1bba315))
- test(fetcher/lastfm): cover render_body shape dispatch for charts and every top_* fetcher, including the text_body fallback arm ([871d30b](https://github.com/unhappychoice/splashboard/commit/871d30b))
- test(runtime): cover cache_keys_for realtime/unknown filtering, distinct per-widget keys, and load_entries key parity ([9f17ddd](https://github.com/unhappychoice/splashboard/commit/9f17ddd))
- test(fetcher/forge_items): cover dispatch_rows_async ImageLinkedList thumbnail resolution for missing, unsupported-scheme, and cache-hit avatars ([3a527a8](https://github.com/unhappychoice/splashboard/commit/3a527a8))
- test(fetcher/deal/free_games): cover fetch validation rejections and entry_to_row store split, free-offer marking, and timestamp fallbacks ([f12c144](https://github.com/unhappychoice/splashboard/commit/f12c144))
- test(fetcher/lastfm/scrobbles_today): cover render_body shape dispatch, text fallback, and every body builder ([c507212](https://github.com/unhappychoice/splashboard/commit/c507212))
- test(fetcher/deal/games): cover store_name id mapping and fetch_deals success, status, parse, request, and oversized-body paths ([04c099f](https://github.com/unhappychoice/splashboard/commit/04c099f))
- test(fetcher/gitlab/pipeline_status): cover sample_body shapes, metadata, cache_key variation, and fetch validation paths ([9b02747](https://github.com/unhappychoice/splashboard/commit/9b02747))
- test(fetcher/crypto_trending): cover render_sync text_block, render_for_shape image/non-image paths, and shared http client ([2c4319f](https://github.com/unhappychoice/splashboard/commit/2c4319f))
- test(fetcher/wikipedia/trending): cover render_sync text_block, build_summary_url encoding, and render_for_shape non-image path ([eced2fb](https://github.com/unhappychoice/splashboard/commit/eced2fb))
- test(fetcher/lastfm/top): cover Period deserialisation and body builders for every shape ([ad60121](https://github.com/unhappychoice/splashboard/commit/ad60121))
- test(fetcher/deal/steam_daily): cover entry_to_row parsing, fallbacks, and cache_key ([f870941](https://github.com/unhappychoice/splashboard/commit/f870941))
- test(fetcher/huggingface_trending): cover get_json status/parse/size/request paths and render_for_shape image branches ([2bb8dc7](https://github.com/unhappychoice/splashboard/commit/2bb8dc7))
- test(fetcher/gitlab): cover repo_stars sample_body, metadata, cache_key, and fetch validation paths ([aa16985](https://github.com/unhappychoice/splashboard/commit/aa16985))
- test(fetcher/steam): cover owned_games render_body shapes, cache_key, and fetch validation ([7373b81](https://github.com/unhappychoice/splashboard/commit/7373b81))
- test(fetcher/steam): cover recently_played render_body shapes, cache_key, and fetch validation ([f17d963](https://github.com/unhappychoice/splashboard/commit/f17d963))
- test(fetcher/deal): cover common label, body_for_shape, and image_linked paths ([4612d0a](https://github.com/unhappychoice/splashboard/commit/4612d0a))
- test(fetcher/lastfm): cover parse_json status, envelope, and size paths ([c592945](https://github.com/unhappychoice/splashboard/commit/c592945))
- test(fetcher/gitlab): cover repo_issues metadata, cache_key, and fetch validation paths ([85bc788](https://github.com/unhappychoice/splashboard/commit/85bc788))
- test(runtime): cover next_refresh_secs countdown logic and fmt_duration_compact ([618d441](https://github.com/unhappychoice/splashboard/commit/618d441))
- test(fetcher/steam): cover client request_json and get_json error paths ([ffa48c5](https://github.com/unhappychoice/splashboard/commit/ffa48c5))
- test(fetcher/steam): cover player_summary render_body shapes, parsing, and fallbacks ([b86e921](https://github.com/unhappychoice/splashboard/commit/b86e921))
- test(fetcher/steam): cover charts render_body shapes and response parsing ([32fdeeb](https://github.com/unhappychoice/splashboard/commit/32fdeeb))
- chore: update flake.nix hashes for v2.6.0 ([c53f6da](https://github.com/unhappychoice/splashboard/commit/c53f6da))


## [2.6.0] - 2026-05-20

### ✨ Features

- feat(fetcher): add steam_charts ([81f14d7](https://github.com/unhappychoice/splashboard/commit/81f14d7))
- feat(fetcher): add steam_owned_games ([503f2c0](https://github.com/unhappychoice/splashboard/commit/503f2c0))
- feat(fetcher): add steam_recently_played ([710fc19](https://github.com/unhappychoice/splashboard/commit/710fc19))
- feat(fetcher): add steam_player_summary ([a53592b](https://github.com/unhappychoice/splashboard/commit/a53592b))
- feat(render): add Bar.value_label for fetcher-formatted value columns ([d743d4c](https://github.com/unhappychoice/splashboard/commit/d743d4c))
- feat(fetcher): add lastfm_charts ([fe189e4](https://github.com/unhappychoice/splashboard/commit/fe189e4))
- feat(fetcher): add lastfm_top_albums ([ecb519b](https://github.com/unhappychoice/splashboard/commit/ecb519b))
- feat(fetcher): add lastfm_top_tracks ([407e13b](https://github.com/unhappychoice/splashboard/commit/407e13b))
- feat(fetcher): add lastfm_top_artists ([9d8dd2b](https://github.com/unhappychoice/splashboard/commit/9d8dd2b))
- feat(fetcher): scaffold lastfm/top shared rendering for the top_* siblings ([db5bacc](https://github.com/unhappychoice/splashboard/commit/db5bacc))
- feat(fetcher): add lastfm_scrobbles_today + lastfm family scaffold ([07cfad2](https://github.com/unhappychoice/splashboard/commit/07cfad2))

### 🐛 Bug Fixes

- fix(fetcher/lastfm): sort lastfm_charts rows by playcount desc ([5f9f350](https://github.com/unhappychoice/splashboard/commit/5f9f350))

### 📝 Other Changes

- chore: bump version to v2.6.0 ([0f3a262](https://github.com/unhappychoice/splashboard/commit/0f3a262))
- chore(fetcher): drop dead helpers reference check in lastfm_top_artists ([0e1611e](https://github.com/unhappychoice/splashboard/commit/0e1611e))
- chore: update flake.nix hashes for v2.5.0 ([04d8ce5](https://github.com/unhappychoice/splashboard/commit/04d8ce5))


## [2.5.0] - 2026-05-18

### ✨ Features

- feat(install): include nushell in shell-not-detected error ([3ebf18c](https://github.com/unhappychoice/splashboard/commit/3ebf18c))
- feat(shell): add Nushell init snippet + variant ([305465e](https://github.com/unhappychoice/splashboard/commit/305465e))

### 🐛 Bug Fixes

- fix(install/rc): handle CRLF in source_line trim for Windows CI ([b9760a0](https://github.com/unhappychoice/splashboard/commit/b9760a0))
- fix(install/rc): trim trailing newline when embedding source_line ([c7a8051](https://github.com/unhappychoice/splashboard/commit/c7a8051))

### 📝 Other Changes

- chore: bump version to v2.5.0 ([29abd3a](https://github.com/unhappychoice/splashboard/commit/29abd3a))
- docs: document Nushell in manual rc-edit examples ([280fa76](https://github.com/unhappychoice/splashboard/commit/280fa76))
- test(install/rc): verify Nushell inline-snippet embedding ([9a91371](https://github.com/unhappychoice/splashboard/commit/9a91371))
- test(shell): cover Nushell across the shell module test suite ([ec6987b](https://github.com/unhappychoice/splashboard/commit/ec6987b))
- chore(deps)(deps): bump sysinfo from 0.39.0 to 0.39.2 ([4761da0](https://github.com/unhappychoice/splashboard/commit/4761da0))
- chore(deps)(deps): bump ratatui-image from 11.0.1 to 11.0.2 ([678cb62](https://github.com/unhappychoice/splashboard/commit/678cb62))
- chore: update flake.nix hashes for v2.4.0 ([a40cd99](https://github.com/unhappychoice/splashboard/commit/a40cd99))


## [2.4.0] - 2026-05-17

### ✨ Features

- feat(fetcher): add gitlab_pipeline_status ([ad1ae8d](https://github.com/unhappychoice/splashboard/commit/ad1ae8d))
- feat(fetcher): add gitlab_repo_stars ([8eb8d2a](https://github.com/unhappychoice/splashboard/commit/8eb8d2a))
- feat(fetcher): add gitlab_repo_issues ([26c51fb](https://github.com/unhappychoice/splashboard/commit/26c51fb))
- feat(fetcher): add gitlab_repo_mrs ([d08dbd1](https://github.com/unhappychoice/splashboard/commit/d08dbd1))
- feat(fetcher): add gitlab_review_requests ([d8fdc3e](https://github.com/unhappychoice/splashboard/commit/d8fdc3e))
- feat(fetcher): add gitlab_my_mrs ([cec71a7](https://github.com/unhappychoice/splashboard/commit/cec71a7))
- feat(fetcher): add gitlab/ family scaffolding (client + common + items) ([174360f](https://github.com/unhappychoice/splashboard/commit/174360f))
- feat(fetcher): add forge_items shared row model + dispatcher ([2400717](https://github.com/unhappychoice/splashboard/commit/2400717))

### 🐛 Bug Fixes

- fix(fetcher): escape markdown metacharacters in forge_items::render_markdown ([b0aa0ca](https://github.com/unhappychoice/splashboard/commit/b0aa0ca))
- fix(fetcher): percent-encode branch in gitlab_pipeline_status URL ([49c1d43](https://github.com/unhappychoice/splashboard/commit/49c1d43))
- fix(fetcher): preserve requested shape in gitlab_pipeline_status no-runs path ([97a493a](https://github.com/unhappychoice/splashboard/commit/97a493a))
- fix(fetcher): preserve requested shape in github_action_status no-runs path ([e2bc30a](https://github.com/unhappychoice/splashboard/commit/e2bc30a))
- fix(fetcher): pin github::items::render_items as sync-only ([9ede219](https://github.com/unhappychoice/splashboard/commit/9ede219))

### 📝 Other Changes

- chore: bump version to v2.4.0 ([2a37900](https://github.com/unhappychoice/splashboard/commit/2a37900))
- refactor(github): add Entries shape to action_status ([a15b6dd](https://github.com/unhappychoice/splashboard/commit/a15b6dd))
- refactor(github): extend repo_stars to 6 shapes ([17c687f](https://github.com/unhappychoice/splashboard/commit/17c687f))
- refactor(github): extend repo_issues to 9 shapes via forge_items dispatch ([7eed488](https://github.com/unhappychoice/splashboard/commit/7eed488))
- refactor(github): extend repo_prs to 9 shapes via forge_items dispatch ([a7f6c17](https://github.com/unhappychoice/splashboard/commit/a7f6c17))
- refactor(github): extend assigned_issues to 9 shapes via forge_items dispatch ([e6c4a47](https://github.com/unhappychoice/splashboard/commit/e6c4a47))
- refactor(github): extend review_requests to 9 shapes via forge_items dispatch ([ca17be7](https://github.com/unhappychoice/splashboard/commit/ca17be7))
- refactor(github): extend my_prs to 9 shapes via forge_items dispatch ([0543473](https://github.com/unhappychoice/splashboard/commit/0543473))
- refactor(github): route items.rs through forge_items shared pipeline ([d87ecf1](https://github.com/unhappychoice/splashboard/commit/d87ecf1))
- chore: update flake.nix hashes for v2.3.0 ([07f093b](https://github.com/unhappychoice/splashboard/commit/07f093b))


## [2.3.0] - 2026-05-16

### 💥 BREAKING CHANGES

- test(fetcher/crypto_watchlist): replace let-else/unwrap_or_else panic arms with matches! assertions across entries_body volatility status rows, number_series baseline-deviation centi-units and NaN-zeroed sparkline, point_series MAX_SERIES_COINS cap and hour-indexed x-axis, bars_body basis-points value and ▲/▼/· direction arrow, linked_text_block coingecko coin-page URL, markdown_block bold-symbol bullet, and text_block per-coin lines, plus split sample_body unwrap_or_else into is_some presence assertion + unwrap so the panic branch stops registering as an uncovered region per [[feedback_coverage_test_panic_arms]] ([e0ee972](https://github.com/unhappychoice/splashboard/commit/e0ee972))
- test(fetcher/basic/links): add metadata_methods_have_content asserting description mentions every LinkedTextBlock/ImageLinkedList/Text/TextBlock/MarkdownTextBlock/Entries dispatch shape and option_schemas exposes the single non-required `links` entry, and sample_body_covers_every_declared_shape pinning `Some` for every shape in `SHAPES` plus the wildcard `_ => return None` arm via Ratio/Image, and replace let-else panic arms with matches! assertions across linked_text_block default rows with optional URLs, markdown_text_block bullet+url joined output, text_block per-row title lines, entries name-url pairs with optional value, missing-options empty LinkedTextBlock fallback, unknown-key placeholder TextBlock, and image_linked_list title/thumbnail/subtitle shape coverage ([857ed47](https://github.com/unhappychoice/splashboard/commit/857ed47))
- test(fetcher/weather/forecast): replace let-else/match panic arms with matches! assertions across text_block per-day-line, text arrow-joined summary, entries weekday-keyed rows, ratio max-precip-probability label, number_series tenths-mm precipitation, point_series high/low unit labels and negative-temperature preservation, bars per-day probability, badge thunderstorm-error and clear-ahead-ok, timeline midnight-UTC timestamps, imperial-units point_series/text_block °F suffix, single-day-window text_block/text/bars collapse, and empty-forecast ratio zero-value no-label shape coverage ([499f630](https://github.com/unhappychoice/splashboard/commit/499f630))
- test(fetcher/nasa_apod): cover sample_body `_ => return None` arm via Bars/Ratio shapes outside the Image+text-shape `SHAPES` set, and restore_env `Some(value) =>` arm by pre-setting `SPLASHBOARD_NASA_APOD_RESTORE_TEST` before capturing the prior value (the standard save→mutate→restore flow always observes None and only fires the None arm), plus replace let-else panic arms with matches! assertions across entries_body copyright present/absent/blank, text_body Text/TextBlock/MarkdownTextBlock/LinkedTextBlock shape coverage, and linked_block malformed-date URL-drop arm ([0d0e237](https://github.com/unhappychoice/splashboard/commit/0d0e237))
- test(fetcher/github/contributors_monthly): replace let-else/if-let panic arms with matches! assertions across sample_body Bars/Entries/LinkedTextBlock/TextBlock/MarkdownTextBlock/Text shape coverage and render_body Text headline, MarkdownTextBlock numbered list, TextBlock per-contributor lines, Entries name-count pairs, LinkedTextBlock profile-URL, and Bars label/value shape coverage ([f01d6bb](https://github.com/unhappychoice/splashboard/commit/f01d6bb))
- test(fetcher/reddit/user_posts): cover render_for_shape ImageLinkedList iterator+collect closure with non-empty posts whose `"self"`/empty thumbnails filter to None so `download_many` short-circuits without network, and replace let-else panic arms with matches! assertions across render_for_shape ImageLinkedList empty and TextBlock sync-dispatch shape coverage ([742a5f3](https://github.com/unhappychoice/splashboard/commit/742a5f3))
- test(fetcher/code/comments): cover render_body `Shape::Ratio` dispatch arm via direct call that delegates to render_ratio (the dedicated render_ratio tests bypass the arm), and replace let-else/match panic arms with matches! assertions across render_text whole-repo ratio/empty, render_ratio total-comments-over-code-plus-comments/empty, render_body TextBlock/MarkdownTextBlock/Entries percent+loc/Bars percent+loc/Badge empty/Text headline shape coverage, and to_payload Text/Badge/Entries body shape coverage ([e421836](https://github.com/unhappychoice/splashboard/commit/e421836))
- test(fetcher/deariary/on_this_day): replace let-else panic arms with matches! assertions across render_body TextBlock/LinkedTextBlock/Text/Timeline/Badge/Entries/MarkdownTextBlock shape coverage plus empty-hits TextBlock/Text/Badge/Timeline fallbacks and Heatmap unsupported-shape TextBlock fallback ([c324e05](https://github.com/unhappychoice/splashboard/commit/c324e05))
- test(fetcher/stock_watchlist): replace let-else panic arms with matches! assertions across entries_body status/value, number_series_body baseline-deviation and large-value scaling, point_series_body MAX_SERIES_STOCKS cap, bars_body basis-points/direction arrows, linked_text_block_body Yahoo quote URL percent-encoding, markdown_block_body bold-symbol prefix, and to_payload Text body shape coverage ([8a3f0be](https://github.com/unhappychoice/splashboard/commit/8a3f0be))
- test(fetcher/todoist): cover cmp_views third `.then_with` content-tiebreaker arm and dual `unwrap_or(i64::MAX)` fallback when both views miss `due_sort_key`, plus to_task_view `created_at` None `unwrap_or_else(|| now.timestamp())` arm, and replace let-else panic arms with matches! assertions across render_body Badge/Text/Entries/Timeline/TextBlock/LinkedTextBlock shape coverage ([8bdef9e](https://github.com/unhappychoice/splashboard/commit/8bdef9e))
- test(fetcher/calendar/holidays): cover upcoming_lines and month_calendar parse_date `?`/filter_map short-circuit arms via malformed-date entries that drop out while valid rows remain, and replace let-else panic arms with matches! assertions across render_body Text today-match/empty, TextBlock upcoming, and Calendar default-branch shape coverage ([b4e6b2e](https://github.com/unhappychoice/splashboard/commit/b4e6b2e))
- test(fetcher/rss): replace let-else/match panic arms with matches! assertions across validated_url scheme/missing-url, render_body LinkedTextBlock/TextBlock shape coverage, atom alternate-vs-self link preference, count-cap, empty-entries, missing/whitespace title fallback, and fetch end-to-end body assertions ([45dbb6c](https://github.com/unhappychoice/splashboard/commit/45dbb6c))
- test(fetcher): replace let-else/if-let panic arms with matches! assertions in net/speedtest and system/monitor_battery, and cover net_speedtest shapes/refresh_interval/description metadata ([7a94e43](https://github.com/unhappychoice/splashboard/commit/7a94e43))
- test(fetcher): replace let-else/match panic arms with matches! assertions across system info_* tests and add badge_data text-shape None guard in weather/now ([0a31607](https://github.com/unhappychoice/splashboard/commit/0a31607))

### ✨ Features

- feat(fetcher): add *_trending batch — reddit / wikipedia / crypto / huggingface ([5b3515b](https://github.com/unhappychoice/splashboard/commit/5b3515b))
- feat(fetcher): add deal_* family for gaming deal aggregators ([e174ceb](https://github.com/unhappychoice/splashboard/commit/e174ceb))

### 📝 Other Changes

- chore: bump version to v2.3.0 ([9047781](https://github.com/unhappychoice/splashboard/commit/9047781))
- test(fetcher/feed): cover `render_image_body` `Some(url) => …` `Ok(Some(path))` arm and `render_image_linked` `path.map(|p| …)` Some/None row shapes by pre-seeding `$SPLASHBOARD_HOME/cache/thumbnails/<sha256(url)>.png` so `thumbnails::download_to_cache` short-circuits to `existing_cached` without touching the network per [[project_thumbnail_cache_preseed_trick]], plus restore_splashboard_home `Some(value) => set_var` arm via pre-seeding SPLASHBOARD_HOME before capture so the save→mutate→restore flow observes `Some(...)` instead of the default-unset None arm per [[feedback_coverage_test_panic_arms]] ([65b3b04](https://github.com/unhappychoice/splashboard/commit/65b3b04))
- test(fetcher/random_dog): cover fetch_image_url `send().await.map_err` arm via raw-space-in-authority URL that fails synchronously at `reqwest::Url::parse` without touching random.dog, mirroring the sibling `fetch_bytes_rejects_malformed_url` trick for the image-download leg so the "dog API request failed:" branch stops registering as an uncovered region per [[feedback_coverage_test_panic_arms]] ([1cba773](https://github.com/unhappychoice/splashboard/commit/1cba773))
- test(fetcher/random_cat,random_dog): cover restore_home `Some(value) => set_var` arm by pre-seeding SPLASHBOARD_HOME before capturing the prior value so the save→mutate→restore flow observes `Some(...)` instead of the default-unset None arm, asserting the captured path is reapplied after a mutation ([5cce5f8](https://github.com/unhappychoice/splashboard/commit/5cce5f8))
- test(fetcher/linear/client): cover graphql_query send_with_retry `map_err` arm and `?`-propagation in-process via newline-in-bearer-token trick that fails synchronously at `.send().await`, attaching coverage to the parent report unlike the existing child-process proxy test ([a87dfd6](https://github.com/unhappychoice/splashboard/commit/a87dfd6))
- test(fetcher/github/client): cover rest_get/graphql `send().await.map_err` arms via newline-in-bearer-token trick that fails synchronously at builder time without touching api.github.com, and resolve_authenticated_user `?`-propagation arm on cache miss when rest_get errors before the `if let Some(cached)` Some-arm can short-circuit ([5dd4360](https://github.com/unhappychoice/splashboard/commit/5dd4360))
- test(fetcher/deariary/client): cover send_with_retry `http().get(...).send().await.map_err` arm via newline-in-token invalid bearer header that fails synchronously at send time, plus cached_get_entry/cached_get_entries `Instant::now() < cached.expires` false arms reached only by seeding expired CacheSlots manually (production callers hit it via wall-clock drift across refresh cycles), and get_optional/get_required `?`-propagation arms before the FetchOutcome match or JSON parser run ([50df488](https://github.com/unhappychoice/splashboard/commit/50df488))
- test(fetcher/code/comments): cover scan_repo sort_by closure primary partial_cmp arm via Rust 50%/Python 0% ratio ordering and secondary `then_with` name-ascending tiebreaker via two 0%-ratio languages, plus ratio_of `if denom == 0` zero-denominator arm that production callers can't reach because `scan_repo`'s `code + comments > 0` filter drops empty entries before they hit `by_language` ([0482b2f](https://github.com/unhappychoice/splashboard/commit/0482b2f))
- docs(perf): fix realtime fetcher claims ([9bda7ad](https://github.com/unhappychoice/splashboard/commit/9bda7ad))
- docs(perf): tighten inaccurate claims after code audit ([da806f2](https://github.com/unhappychoice/splashboard/commit/da806f2))
- docs: add Performance guide for cache and refresh model ([fac85cc](https://github.com/unhappychoice/splashboard/commit/fac85cc))
- test(fetcher/reddit/client): cover get_with_profile `reqwest::send` `map_err` arm via a malformed authority that fails URL parse before hitting the wire, and fetch_listing's `get_with_retry?` propagation when both Minimal/Browserish profiles fail on a space-containing path that trips `SITE_BASE` concatenation parse ([e247747](https://github.com/unhappychoice/splashboard/commit/e247747))
- test(fetcher/net/ip): cover text_value `IpKind::V6` fall-back when the default interface has no IPv6 and `IpKind::Primary` terminal `unwrap_or_else` "no address" arm when the default carries neither v4 nor v6, plus ip_badge IPv6-only arm distinct from the IPv4-only and dual-stack cases, and assert NetIp description mentions both Text and Badge shape roles ([66533a3](https://github.com/unhappychoice/splashboard/commit/66533a3))
- test(fetcher/stock_watchlist): cover format_price EUR/KRW glyph arms, number_series_body all-non-finite baseline `else` fallback that pins to 0.0 instead of INFINITY, and StockPoint::from_api currency `unwrap_or_else` default to "usd" when the API omits the field ([27fcf10](https://github.com/unhappychoice/splashboard/commit/27fcf10))
- test(fetcher): cover random_cat/random_dog build_url digit-segment encode arms, random_dog enforce_allowed_host http-scheme accept and missing/non-http(s) scheme reject paths, plus image_extension GIF87a legacy magic alongside GIF89a ([3a26009](https://github.com/unhappychoice/splashboard/commit/3a26009))
- test(fetcher/linear/notifications): cover Fetcher metadata trait methods, sample_body declared-shape round-trip plus Image/Ratio None fallback, markdown_line_for identifier/actor/title arms with snippet fallback, and entry_value actor/type/title separator joining with snippet fallback ([a8c028c](https://github.com/unhappychoice/splashboard/commit/a8c028c))
- test(fetcher/github/action_history): cover sample_body Shape::Bars passed/failed arm, render_body bars success-vs-non-success conclusion bucketing and empty-runs zero-counts, and cache_key no-options fallback through resolve_repo(None) to the workspace git remote ([9fa6301](https://github.com/unhappychoice/splashboard/commit/9fa6301))
- test(fetcher/stock_watchlist): cover fetch_snapshot empty-input no-data fallback via direct call with an empty slice that bypasses resolve_symbols' public-entrypoint guard ([6d87d52](https://github.com/unhappychoice/splashboard/commit/6d87d52))
- test(fetcher/news): cover fetch malformed-bundled-url early-return arm via a synthetic NewsSource whose hardcoded url fails Url::parse before network I/O ([de9186e](https://github.com/unhappychoice/splashboard/commit/de9186e))
- test(fetcher/news): cover fetch early-return arms for invalid options deny_unknown_fields and unknown feed key before network I/O ([cd5b09f](https://github.com/unhappychoice/splashboard/commit/cd5b09f))
- test(fetcher/system): cover env_basename file_name-less path trimmed fallback and detect_terminal hyper TERM_PROGRAM arm ([996a3c3](https://github.com/unhappychoice/splashboard/commit/996a3c3))
- test(fetcher/net/gateway): cover description/refresh_interval metadata, cache_key name-prefix and options partitioning, fetch unsupported-shape text fallback, plus mod-level default_gateway snapshot stability and gateway_ip ipv4-first/ipv6-fallback/empty preference order ([586781e](https://github.com/unhappychoice/splashboard/commit/586781e))
- test(fetcher/net/mac): cover description/refresh_interval metadata, cache_key options partitioning, named-interface no-mac n/a fallback, unparseable-mac badge warn surfacing, and fetch unsupported-shape text_value fallback ([e065a36](https://github.com/unhappychoice/splashboard/commit/e065a36))
- test(fetcher/weather/forecast): cover weekday_short labels for all seven weekday variants and ratio empty-forecast zero-value no-label fallback ([8c252eb](https://github.com/unhappychoice/splashboard/commit/8c252eb))
- test(fetcher/git): cover commits_activity text-shape empty-grid body and number-series flatten wrapping, plus mod-level fail display wrapping, payload/text_body/text_block_body shapes, and open_repo/discover_root/repo_cache_key shape-variance against the splashboard workspace ([62ab7c4](https://github.com/unhappychoice/splashboard/commit/62ab7c4))
- test(fetcher/git/age): cover sample_for shape gating, fetcher metadata, cache_key shape/format variance, structural-shape build dispatch, empty-repo markdown/calendar placeholders, january previous-december day borrow, zero-age today label, and fetch text payload inside a real repo ([2bb1846](https://github.com/unhappychoice/splashboard/commit/2bb1846))
- test(fetcher/youtube): cover fetch_and_merge no-channels-yielded-entries fallback on empty input ([0561698](https://github.com/unhappychoice/splashboard/commit/0561698))
- test(fetcher/crypto_watchlist): cover empty-snapshot text fallback, top-mover arrow/change formatting, per-coin text block lines, eur/gbp currency glyphs, integer-only thousands grouping, payload chrome stripping, http singleton reuse, and non-finite sparkline baseline collapse ([ac2c5eb](https://github.com/unhappychoice/splashboard/commit/ac2c5eb))
- test(fetcher/reddit): cover subreddit/user_posts description sibling references and render_for_shape image-list vs sync dispatch on empty input ([5269c71](https://github.com/unhappychoice/splashboard/commit/5269c71))
- test(fetcher/net/speedtest): cover http singleton reuse and measure_download/latency/upload plus download_chunk request-failure paths ([5491e69](https://github.com/unhappychoice/splashboard/commit/5491e69))
- test(fetcher/system): cover detect_timezone fallback, desktop/window-manager env precedence, and init-system platform paths ([eed88ee](https://github.com/unhappychoice/splashboard/commit/eed88ee))
- test(fetcher/stock_watchlist): cover empty-snapshot text fallback, integer-only thousands grouping, zero-price change_pct, payload chrome stripping, and http singleton ([f68a831](https://github.com/unhappychoice/splashboard/commit/f68a831))
- test(fetcher/thumbnails): cover download_to_cache cache hits, fresh writes, HTTP/oversize errors, and download_many failure collapsing ([d9d2171](https://github.com/unhappychoice/splashboard/commit/d9d2171))
- test(fetcher/system): cover info_host kind variants and monitor_disk text-shape dispatch ([0e0e707](https://github.com/unhappychoice/splashboard/commit/0e0e707))
- test(fetcher/basic): cover metadata, sample_body shape gating, and invalid-options placeholders across the basic family ([f45e612](https://github.com/unhappychoice/splashboard/commit/f45e612))
- test(fetcher/weather/common): cover unit labels, WMO description/badge/severity tables, http singleton, parse_options errors, and payload wrapper ([520870a](https://github.com/unhappychoice/splashboard/commit/520870a))
- test(fetcher/system): cover info_* kind dispatch defaults, known variants, and unknown-kind placeholder ([8095e97](https://github.com/unhappychoice/splashboard/commit/8095e97))
- test(fetcher/feed): cover render_body shapes, link/thumbnail fallbacks, and parse_feed errors ([a25b836](https://github.com/unhappychoice/splashboard/commit/a25b836))
- test(fetcher/news): cover category labels, default_feed, and find_feed lookup ([c4a3e51](https://github.com/unhappychoice/splashboard/commit/c4a3e51))
- test(system/dmi): cover full chassis label table + reader smoke test ([5205a03](https://github.com/unhappychoice/splashboard/commit/5205a03))
- chore: update flake.nix hashes for v2.2.0 ([8ad5aa3](https://github.com/unhappychoice/splashboard/commit/8ad5aa3))


## [2.2.0] - 2026-05-15

### ✨ Features

- feat(runtime): make watch footer a status bar with refresh meta ([17cdd99](https://github.com/unhappychoice/splashboard/commit/17cdd99))
- feat(runtime): add key-binding footer to watch mode ([0d9d3a1](https://github.com/unhappychoice/splashboard/commit/0d9d3a1))
- feat(runtime): add persistent watch mode (splashboard watch) ([7df31cb](https://github.com/unhappychoice/splashboard/commit/7df31cb))

### 🐛 Bug Fixes

- fix(watch): always run teardown + tighten WatchTerminal::enter ([10520c7](https://github.com/unhappychoice/splashboard/commit/10520c7))
- fix(runtime): draw watch dashboard at natural height, not stretched ([8dd8091](https://github.com/unhappychoice/splashboard/commit/8dd8091))

### 📝 Other Changes

- chore: bump version to v2.2.0 ([ec51139](https://github.com/unhappychoice/splashboard/commit/ec51139))
- docs: cover `splashboard watch` in guides + README ([44527b3](https://github.com/unhappychoice/splashboard/commit/44527b3))
- perf(watch): cut per-frame clones via generation-tracked cache reads ([5ccd828](https://github.com/unhappychoice/splashboard/commit/5ccd828))
- perf(watch): swap disk cache for in-memory backend during watch mode ([5df3ae1](https://github.com/unhappychoice/splashboard/commit/5df3ae1))
- chore: update flake.nix hashes for v2.1.0 ([612d765](https://github.com/unhappychoice/splashboard/commit/612d765))


## [2.1.0] - 2026-05-14

### ✨ Features

- feat(fetcher): declare refresh_interval for the net_* family ([1c08d6f](https://github.com/unhappychoice/splashboard/commit/1c08d6f))
- feat(fetcher): per-fetcher refresh interval, drop global 60s default ([560a529](https://github.com/unhappychoice/splashboard/commit/560a529))
- feat(fetcher): add net_* family — interfaces / ip / mac / gateway / proxy / speedtest ([133305c](https://github.com/unhappychoice/splashboard/commit/133305c))
- feat(fetcher): add nasa_apod — NASA Astronomy Picture of the Day ([4e98f71](https://github.com/unhappychoice/splashboard/commit/4e98f71))
- feat(fetcher): add basic_heatmap ([bff4bcb](https://github.com/unhappychoice/splashboard/commit/bff4bcb))
- feat(fetcher): add basic_calendar ([7feab05](https://github.com/unhappychoice/splashboard/commit/7feab05))
- feat(fetcher): add basic_timeline ([e1329b6](https://github.com/unhappychoice/splashboard/commit/e1329b6))
- feat(fetcher): add basic_points ([70ba363](https://github.com/unhappychoice/splashboard/commit/70ba363))
- feat(fetcher): add basic_numbers ([52d43c0](https://github.com/unhappychoice/splashboard/commit/52d43c0))
- feat(fetcher): add basic_entries ([4e23043](https://github.com/unhappychoice/splashboard/commit/4e23043))
- feat(fetcher): add basic_bars ([956a60b](https://github.com/unhappychoice/splashboard/commit/956a60b))
- feat(fetcher): add basic_ratio ([c4d573f](https://github.com/unhappychoice/splashboard/commit/c4d573f))
- feat(fetcher): add basic_badge ([bb0b77a](https://github.com/unhappychoice/splashboard/commit/bb0b77a))
- feat(fetcher): add basic_image ([9e00689](https://github.com/unhappychoice/splashboard/commit/9e00689))
- feat(fetcher): add basic_links ([cc65861](https://github.com/unhappychoice/splashboard/commit/cc65861))

### 🐛 Bug Fixes

- fix(fetcher): gate net_proxy lowercase-precedence test to non-Windows ([54caacd](https://github.com/unhappychoice/splashboard/commit/54caacd))
- fix(fetcher): make LinearTokenGuard lock-free so token tests stay in one critical section ([4ef7a09](https://github.com/unhappychoice/splashboard/commit/4ef7a09))
- fix(fetcher): close LINEAR_TOKEN race in linear_token_guard_set_restores_outer_previous_value ([4ebab29](https://github.com/unhappychoice/splashboard/commit/4ebab29))

### 📝 Other Changes

- chore: bump version to v2.1.0 ([2ec08cd](https://github.com/unhappychoice/splashboard/commit/2ec08cd))
- docs: refresh README hero screenshot ([ed4457f](https://github.com/unhappychoice/splashboard/commit/ed4457f))
- test(fetcher): sweep every cached builtin's refresh_interval ([fdfd761](https://github.com/unhappychoice/splashboard/commit/fdfd761))
- docs(agents): drop pomodoro from RealtimeFetcher examples ([450af03](https://github.com/unhappychoice/splashboard/commit/450af03))
- test(fetcher): close nasa_apod coverage gaps ([7391d4d](https://github.com/unhappychoice/splashboard/commit/7391d4d))
- test(fetcher): broaden basic_* coverage — family contract sweep + branch gaps ([4247236](https://github.com/unhappychoice/splashboard/commit/4247236))
- ci: stop caching ~/.cargo/bin so rust-cache can't clobber the toolchain ([5e4d65e](https://github.com/unhappychoice/splashboard/commit/5e4d65e))
- style(fetcher): rustfmt + clippy fixups for basic_* ([6958fcd](https://github.com/unhappychoice/splashboard/commit/6958fcd))
- chore(fetcher): register basic_numbers in basic/mod.rs ([bdfaa28](https://github.com/unhappychoice/splashboard/commit/bdfaa28))
- chore(fetcher): scaffold basic_* family module ([2adeb72](https://github.com/unhappychoice/splashboard/commit/2adeb72))
- docs: add Discord and blog mentions to Support section ([3125146](https://github.com/unhappychoice/splashboard/commit/3125146))
- docs: add general hashtags to share links ([daba37a](https://github.com/unhappychoice/splashboard/commit/daba37a))
- docs: add Support section with star and share links to README ([4224dce](https://github.com/unhappychoice/splashboard/commit/4224dce))
- chore: update flake.nix hashes for v2.0.0 ([f665243](https://github.com/unhappychoice/splashboard/commit/f665243))


## [2.0.0] - 2026-05-13

### 💥 BREAKING CHANGES

- refactor(fetcher)!: split system fetchers into per-file modules ([e2cd69f](https://github.com/unhappychoice/splashboard/commit/e2cd69f))
- refactor(fetcher)!: split `system` into `system_{info,monitor}_*` family ([b23a8bd](https://github.com/unhappychoice/splashboard/commit/b23a8bd))

### ✨ Features

- feat(fetcher): extend system `kind` with CPU/memory/kernel/DMI/env identifiers ([2ffb24e](https://github.com/unhappychoice/splashboard/commit/2ffb24e))
- feat(runtime): make scrollback flush opt-in via general.flush_to_scrollback ([8facb50](https://github.com/unhappychoice/splashboard/commit/8facb50))

### 🐛 Bug Fixes

- fix(fetcher): address CodeRabbit review on system_monitor_* fetchers ([fa71bb3](https://github.com/unhappychoice/splashboard/commit/fa71bb3))
- fix(fetcher): align system kind fallbacks with `(unset)` convention ([380cd52](https://github.com/unhappychoice/splashboard/commit/380cd52))
- fix(release): create release as draft and publish after assets upload ([356856e](https://github.com/unhappychoice/splashboard/commit/356856e))

### 📝 Other Changes

- chore: bump version to v2.0.0 ([0d08892](https://github.com/unhappychoice/splashboard/commit/0d08892))
- docs(fetcher): update guides and doc comments to new system_* names ([61722d3](https://github.com/unhappychoice/splashboard/commit/61722d3))
- test(fetcher): split system tests into per-fetcher modules + address review ([a17e2f7](https://github.com/unhappychoice/splashboard/commit/a17e2f7))
- test(git): serialize stash_count CWD-reading test with TEST_ENV_LOCK ([fe7f689](https://github.com/unhappychoice/splashboard/commit/fe7f689))
- chore: update flake.nix hashes for v1.6.0 ([8f66ccc](https://github.com/unhappychoice/splashboard/commit/8f66ccc))


## [1.6.0] - 2026-05-12

### ✨ Features

- feat(fetcher/youtube): add youtube_channel fetcher ([df3f5cd](https://github.com/unhappychoice/splashboard/commit/df3f5cd))
- feat(fetcher/news): add news_bloomberg + news_wsj (10 sub-feeds) ([12c52a9](https://github.com/unhappychoice/splashboard/commit/12c52a9))
- feat(fetcher/news): expand to 93 sources / 20 sub-genres ([353a211](https://github.com/unhappychoice/splashboard/commit/353a211))
- feat(fetcher/news): add news_* family with 39 curated sources ([cc69499](https://github.com/unhappychoice/splashboard/commit/cc69499))

### 📝 Other Changes

- chore: bump version to v1.6.0 ([3638c58](https://github.com/unhappychoice/splashboard/commit/3638c58))
- chore(fetcher/news): upgrade all feed URLs to https + lock policy in test ([8977c7d](https://github.com/unhappychoice/splashboard/commit/8977c7d))
- chore: update flake.nix hashes for v1.5.0 ([8807cac](https://github.com/unhappychoice/splashboard/commit/8807cac))


## [1.5.0] - 2026-05-12

### ✨ Features

- feat(fetcher/wikipedia): emit ImageLinkedList with REST thumbnail.source ([97484af](https://github.com/unhappychoice/splashboard/commit/97484af))
- feat(fetcher/reddit): emit ImageLinkedList for post listings ([0fd12dc](https://github.com/unhappychoice/splashboard/commit/0fd12dc))
- feat(fetcher/rss): emit ImageLinkedList with thumbnails ([6680e40](https://github.com/unhappychoice/splashboard/commit/6680e40))
- feat(fetcher): basic_read_store accepts ImageLinkedList ([af16de8](https://github.com/unhappychoice/splashboard/commit/af16de8))
- feat(fetcher): add shared thumbnail downloader ([7f332fb](https://github.com/unhappychoice/splashboard/commit/7f332fb))
- feat(render): add list_cards renderer over a new ImageLinkedList shape ([e50c4e1](https://github.com/unhappychoice/splashboard/commit/e50c4e1))
- feat(cache): document shape/locale/timezone limitation for clear by id ([1eac161](https://github.com/unhappychoice/splashboard/commit/1eac161))
- feat: "splashboard cache" management CLI — list, clear, path (#40) ([74c2ea4](https://github.com/unhappychoice/splashboard/commit/74c2ea4))
- feat(fetcher): add weather_forecast ([e1d08a7](https://github.com/unhappychoice/splashboard/commit/e1d08a7))

### 🐛 Bug Fixes

- fix(cache): address review — dedupe sanitize, multi-byte truncate, doc/exit polish ([b2dbf13](https://github.com/unhappychoice/splashboard/commit/b2dbf13))
- fix(clippy): sort_by_key + inline OUTCOME literal; add 11 coverage tests ([3b45780](https://github.com/unhappychoice/splashboard/commit/3b45780))
- fix(render): preserve theme.bg in chart_line and chart_scatter ([911ed4f](https://github.com/unhappychoice/splashboard/commit/911ed4f))
- fix(render): wrap rgba in Some for ratatui-image 11 set_background_color API ([b726d96](https://github.com/unhappychoice/splashboard/commit/b726d96))

### 📝 Other Changes

- chore: bump version to v1.5.0 ([1bc7042](https://github.com/unhappychoice/splashboard/commit/1bc7042))
- style: cargo fmt ([ab3b7d6](https://github.com/unhappychoice/splashboard/commit/ab3b7d6))
- test: fill list_cards / ImageLinkedList coverage gaps ([8446b7d](https://github.com/unhappychoice/splashboard/commit/8446b7d))
- refactor(render): extract draw_thumbnail and wrap_osc8 helpers ([a998762](https://github.com/unhappychoice/splashboard/commit/a998762))
- chore(deps)(deps): bump ratatui-image from 10.0.8 to 11.0.1 ([c7d6c62](https://github.com/unhappychoice/splashboard/commit/c7d6c62))
- chore(deps)(deps): bump sysinfo from 0.38.4 to 0.39.0 ([9d82df6](https://github.com/unhappychoice/splashboard/commit/9d82df6))
- chore(deps)(deps): bump tokio from 1.52.1 to 1.52.3 ([24ea3e1](https://github.com/unhappychoice/splashboard/commit/24ea3e1))
- chore: update flake.nix hashes for v1.4.0 ([bef2903](https://github.com/unhappychoice/splashboard/commit/bef2903))


## [1.4.0] - 2026-05-10

### ✨ Features

- feat(fetcher): add stock_watchlist (Yahoo Finance, 9 shapes) ([69e2138](https://github.com/unhappychoice/splashboard/commit/69e2138))
- feat(fetcher): add crypto_watchlist (CoinGecko, 9 shapes) ([4f2b124](https://github.com/unhappychoice/splashboard/commit/4f2b124))
- feat(fetcher/github): add Bars shape to action_history + expand samples ([34a22cc](https://github.com/unhappychoice/splashboard/commit/34a22cc))
- feat(xtask): use camera icon as image-shape placeholder ([ea9f2fe](https://github.com/unhappychoice/splashboard/commit/ea9f2fe))
- feat(layout): support nested rows in ChildConfig ([003ca0d](https://github.com/unhappychoice/splashboard/commit/003ca0d))
- feat(xtask): render demo dashboard under every theme preset ([cdd60e6](https://github.com/unhappychoice/splashboard/commit/cdd60e6))
- feat(xtask): generic gallery pipeline for usecases & community ([b45d9d0](https://github.com/unhappychoice/splashboard/commit/b45d9d0))
- feat(xtask): generate preset descriptions index for the docs gallery ([b2f9e22](https://github.com/unhappychoice/splashboard/commit/b2f9e22))
- feat(xtask): top-align dashboard snapshots with synthesised theme-bg padding ([eb0e404](https://github.com/unhappychoice/splashboard/commit/eb0e404))
- feat(xtask): bundle placeholder PNG for image widgets without sample data ([ca47afc](https://github.com/unhappychoice/splashboard/commit/ca47afc))
- feat(docs-site): style splash-config details for collapsible source code ([6e18cda](https://github.com/unhappychoice/splashboard/commit/6e18cda))
- feat(docs-site): nest Showcases sidebar with Themes / Presets / Use cases / Community ([e0106ef](https://github.com/unhappychoice/splashboard/commit/e0106ef))
- feat(docs-site): split Showcases into nested pages ([4a8f35c](https://github.com/unhappychoice/splashboard/commit/4a8f35c))
- feat(examples): add community submission scaffold ([7ae2562](https://github.com/unhappychoice/splashboard/commit/7ae2562))
- feat(examples): add usecases gallery with 8 tool-focused dashboards ([6003eed](https://github.com/unhappychoice/splashboard/commit/6003eed))

### 🐛 Bug Fixes

- fix(fetcher/crypto_watchlist): subtract period min for sparkline values ([45ea15a](https://github.com/unhappychoice/splashboard/commit/45ea15a))
- fix(xtask): scrub LC_TERMINAL so media_image's picker stays on halfblocks ([3b047b6](https://github.com/unhappychoice/splashboard/commit/3b047b6))
- fix(xtask): preserve inner renderer options when deanimating animation wrappers ([32934ba](https://github.com/unhappychoice/splashboard/commit/32934ba))

### 📝 Other Changes

- chore: bump version to v1.4.0 ([bfa6cbe](https://github.com/unhappychoice/splashboard/commit/bfa6cbe))
- style(fetcher/todoist): apply rustfmt to expanded Timeline sample ([126e288](https://github.com/unhappychoice/splashboard/commit/126e288))
- refactor(usecase): replace project_workspace with project_welcome ([2478d5c](https://github.com/unhappychoice/splashboard/commit/2478d5c))
- refactor(usecase/project_ci): layered status + per-branch row + open PRs ([ced51c2](https://github.com/unhappychoice/splashboard/commit/ced51c2))
- refactor(usecase/project_book): denser cover band + manuscript-coded panels ([a5ec3c1](https://github.com/unhappychoice/splashboard/commit/a5ec3c1))
- refactor(usecase/home_todoist): trim to a clean 3-column kanban ([02a406f](https://github.com/unhappychoice/splashboard/commit/02a406f))
- refactor(usecase/home_system_monitor): unify gauges and stack readouts ([6844510](https://github.com/unhappychoice/splashboard/commit/6844510))
- refactor(usecase): replace home_quiet_companion with home_companions ([ee0b8cf](https://github.com/unhappychoice/splashboard/commit/ee0b8cf))
- refactor(usecase/home_linear): rebuild as 3-shape Overview ([48487a5](https://github.com/unhappychoice/splashboard/commit/48487a5))
- chore(fetcher/todoist): expand task sample data ([76e1911](https://github.com/unhappychoice/splashboard/commit/76e1911))
- chore: update flake.nix hashes for v1.3.1 ([98a783e](https://github.com/unhappychoice/splashboard/commit/98a783e))
- docs(xtask): clarify SNAPSHOT_HEIGHT comment and deanimate test rationale ([3d0d862](https://github.com/unhappychoice/splashboard/commit/3d0d862))
- chore(docs-site): refresh package-lock.json ([d0c34b7](https://github.com/unhappychoice/splashboard/commit/d0c34b7))
- docs(AGENTS): document curation tiers and showcase gallery workflow ([f3dbf4d](https://github.com/unhappychoice/splashboard/commit/f3dbf4d))


## [1.3.1] - 2026-05-06

### 🐛 Bug Fixes

- fix(github): accept https URLs with userinfo when parsing remote ([bb548f2](https://github.com/unhappychoice/splashboard/commit/bb548f2))

### 📝 Other Changes

- chore: bump version to v1.3.1 ([7750489](https://github.com/unhappychoice/splashboard/commit/7750489))
- chore: update flake.nix hashes for v1.3.0 ([0d60c81](https://github.com/unhappychoice/splashboard/commit/0d60c81))


## [1.3.0] - 2026-05-06

### ✨ Features

- feat(fetcher): add lobsters_top for Lobsters story listings ([6678665](https://github.com/unhappychoice/splashboard/commit/6678665))

### 🐛 Bug Fixes

- fix(github_repo): accept repo option and clean up stale config.toml references ([473494a](https://github.com/unhappychoice/splashboard/commit/473494a))

### 📝 Other Changes

- chore: bump version to v1.3.0 ([46f8ccf](https://github.com/unhappychoice/splashboard/commit/46f8ccf))
- chore: update flake.nix hashes for v1.2.2 ([4adc0a3](https://github.com/unhappychoice/splashboard/commit/4adc0a3))


## [1.2.2] - 2026-05-04

### 🐛 Bug Fixes

- fix(render): pass theme.bg to ratatui_image so image letterbox is opaque ([b6d835e](https://github.com/unhappychoice/splashboard/commit/b6d835e))

### 📝 Other Changes

- chore: bump version to v1.2.2 ([6e82dca](https://github.com/unhappychoice/splashboard/commit/6e82dca))
- chore: update flake.nix hashes for v1.2.1 ([863f8e6](https://github.com/unhappychoice/splashboard/commit/863f8e6))


## [1.2.1] - 2026-05-04

### 🐛 Bug Fixes

- fix(render): force iTerm2 protocol for media_image when running under iTerm2 ([2b2c25f](https://github.com/unhappychoice/splashboard/commit/2b2c25f))
- fix(tests): serialize cache_key stability tests on TEST_ENV_LOCK ([7575989](https://github.com/unhappychoice/splashboard/commit/7575989))
- fix(tests): skip rc/trust assertions on Windows path-resolution mismatches ([558c940](https://github.com/unhappychoice/splashboard/commit/558c940))
- fix(tests): make new coverage tests pass on all CI platforms ([8b85264](https://github.com/unhappychoice/splashboard/commit/8b85264))

### 📝 Other Changes

- chore: bump version to v1.2.1 ([c9a6526](https://github.com/unhappychoice/splashboard/commit/c9a6526))
- style(render): apply rustfmt to media_image.rs ([e760f46](https://github.com/unhappychoice/splashboard/commit/e760f46))
- chore(deps)(deps): bump unicode-width from 0.2.0 to 0.2.2 ([a5debfd](https://github.com/unhappychoice/splashboard/commit/a5debfd))
- chore(deps)(deps): bump ratatui-image from 10.0.6 to 10.0.8 ([a3f028e](https://github.com/unhappychoice/splashboard/commit/a3f028e))
- chore(deps)(deps): bump gix from 0.82.0 to 0.83.0 ([d70f990](https://github.com/unhappychoice/splashboard/commit/d70f990))
- test(linear): cover blank env tokens, nested cache tokens, and request failure paths ([8fa0d62](https://github.com/unhappychoice/splashboard/commit/8fa0d62))
- test(code_files): cover empty text block and render body variants ([a75b8dc](https://github.com/unhappychoice/splashboard/commit/a75b8dc))
- test(wikipedia): cover invalid lang request errors and sample body variants ([13c601a](https://github.com/unhappychoice/splashboard/commit/13c601a))
- test(xtask): cover cli defaults, cwd guards, and render error paths ([9ddc636](https://github.com/unhappychoice/splashboard/commit/9ddc636))
- test(fetchers): cover sample bodies and cache key variant paths ([9957403](https://github.com/unhappychoice/splashboard/commit/9957403))
- test(hackernews_top): cover empty entries and unsupported shape fallback paths ([84b79b2](https://github.com/unhappychoice/splashboard/commit/84b79b2))
- test(github_contributors_monthly): cover body variants and env guard restore paths ([192f50c](https://github.com/unhappychoice/splashboard/commit/192f50c))
- test(system): cover payload body variants and live text kind paths ([1046dad](https://github.com/unhappychoice/splashboard/commit/1046dad))
- test(system): cover sample bodies and empty snapshot fallback paths ([3932e12](https://github.com/unhappychoice/splashboard/commit/3932e12))
- test(linear): cover client non-table strip and guard restore paths ([7915a77](https://github.com/unhappychoice/splashboard/commit/7915a77))
- test(random_fortune): cover unsupported shape and cookie list paths ([5db45b0](https://github.com/unhappychoice/splashboard/commit/5db45b0))
- test(install): cover preview shape fallback, format override, and deanimate paths ([1ffb817](https://github.com/unhappychoice/splashboard/commit/1ffb817))
- test(main): cover tty home render and cache paths ([cb462a5](https://github.com/unhappychoice/splashboard/commit/cb462a5))
- test(logging): cover log file polling and preexisting env restore paths ([37adcb9](https://github.com/unhappychoice/splashboard/commit/37adcb9))
- test(github_items): cover repo parsing and linked text block paths ([93ca963](https://github.com/unhappychoice/splashboard/commit/93ca963))
- test(weather): cover freezing drizzle and wrong-variant extractor paths ([daade12](https://github.com/unhappychoice/splashboard/commit/daade12))
- test(animated_figlet_morph): cover phase fade in and fade out paths ([e1d034c](https://github.com/unhappychoice/splashboard/commit/e1d034c))
- test(deariary_on_this_day): cover oldest badge and anchor underflow paths ([5282294](https://github.com/unhappychoice/splashboard/commit/5282294))
- test(todoist): cover due helper and payload default paths ([cf35ce6](https://github.com/unhappychoice/splashboard/commit/cf35ce6))
- test(main): cover tty on-cd render and cache paths ([094b654](https://github.com/unhappychoice/splashboard/commit/094b654))
- test(github_common): cover text block body, cwd, and no-repo paths ([71627a5](https://github.com/unhappychoice/splashboard/commit/71627a5))
- test(rc): cover append, replace, and close-marker newline paths ([b0641fb](https://github.com/unhappychoice/splashboard/commit/b0641fb))
- test(list_plain): cover non-text natural height fallback path ([b23083e](https://github.com/unhappychoice/splashboard/commit/b23083e))
- test(templates): cover template lookup and context filter paths ([51ca25c](https://github.com/unhappychoice/splashboard/commit/51ca25c))
- test(code_scan): cover classifier helpers, tracked walker skips, and tokei stats ([c7cc48c](https://github.com/unhappychoice/splashboard/commit/c7cc48c))
- test(wikipedia): cover get success, status, and json parse paths ([0d29724](https://github.com/unhappychoice/splashboard/commit/0d29724))
- test(main): cover tty install picker confirm and cancel paths ([7e8d169](https://github.com/unhappychoice/splashboard/commit/7e8d169))
- test(system): cover terminal alias priority, formatter helpers, and payload builders ([1019ba6](https://github.com/unhappychoice/splashboard/commit/1019ba6))
- test(dashboard_snapshot): cover renderer fallback and deanimate option paths ([05d95cf](https://github.com/unhappychoice/splashboard/commit/05d95cf))
- test(linear): cover notifications contract, helpers, rendering, and fallback paths ([015bb5c](https://github.com/unhappychoice/splashboard/commit/015bb5c))
- test(paths): cover env restoration and home fallback paths ([00ca07f](https://github.com/unhappychoice/splashboard/commit/00ca07f))
- test(main): cover install, tty auto flags, and trust prompt paths ([67c0e5c](https://github.com/unhappychoice/splashboard/commit/67c0e5c))
- test(html_snapshot): cover styled spans, link escaping, and osc8 fallback paths ([ef9041a](https://github.com/unhappychoice/splashboard/commit/ef9041a))
- test: cover deariary helper branches and dashboard snapshot fallback paths ([ea5affe](https://github.com/unhappychoice/splashboard/commit/ea5affe))
- test(shell): cover cli names and powershell profile path ([f55a100](https://github.com/unhappychoice/splashboard/commit/f55a100))
- test(random_cat): cover fetch bytes success, status, and size limit paths ([de401f1](https://github.com/unhappychoice/splashboard/commit/de401f1))
- test(linear): cover fetcher contract, filter, formatter, and grouping paths ([f9db512](https://github.com/unhappychoice/splashboard/commit/f9db512))
- test(theme): cover heatmap fallback and config override paths ([51b7d01](https://github.com/unhappychoice/splashboard/commit/51b7d01))
- test(main): cover init, license, catalog, trust, and non-tty paths ([5d1a6ba](https://github.com/unhappychoice/splashboard/commit/5d1a6ba))
- test(linear): cover cycle contract, helper, and fallback paths ([6c1b736](https://github.com/unhappychoice/splashboard/commit/6c1b736))
- test(install): cover shell resolution, home fallback, and gitignore paths ([a3a6d20](https://github.com/unhappychoice/splashboard/commit/a3a6d20))
- test(install): cover picker helper and fallback rendering paths ([277f8cc](https://github.com/unhappychoice/splashboard/commit/277f8cc))
- test: cover wikipedia featured fetcher and xtask cli paths ([59f005c](https://github.com/unhappychoice/splashboard/commit/59f005c))
- test(main): cover config loading, secrets, catalog, and trust paths ([a9c20a4](https://github.com/unhappychoice/splashboard/commit/a9c20a4))
- test(linear): cover client token fallback and retry paths ([443903f](https://github.com/unhappychoice/splashboard/commit/443903f))
- test(github): cover repo stars metadata and failure paths ([83d0f82](https://github.com/unhappychoice/splashboard/commit/83d0f82))
- test(reddit): cover client retry and response validation paths ([b2de031](https://github.com/unhappychoice/splashboard/commit/b2de031))
- test(xtask): cover gen_matrix module ([620278a](https://github.com/unhappychoice/splashboard/commit/620278a))
- chore: update flake.nix hashes for v1.2.0 ([33d1569](https://github.com/unhappychoice/splashboard/commit/33d1569))


## [1.2.0] - 2026-04-30

### ✨ Features

- feat(linear): add linear_issues, linear_notifications, linear_cycle fetchers ([daae9cb](https://github.com/unhappychoice/splashboard/commit/daae9cb))
- feat(fetcher): add `random_dog` — random dog photo from dog.ceo ([d61e2c4](https://github.com/unhappychoice/splashboard/commit/d61e2c4))
- feat(fetcher): add `random_cat` — random cat picture from cataas.com ([567fcad](https://github.com/unhappychoice/splashboard/commit/567fcad))

### 🐛 Bug Fixes

- fix: address CodeRabbit review feedback ([1a81beb](https://github.com/unhappychoice/splashboard/commit/1a81beb))
- fix(grid_calendar): preserve layout-painted bg through offscreen blit ([738fa7c](https://github.com/unhappychoice/splashboard/commit/738fa7c))
- fix(xtask): point reference cross-links at routes, not mirrored .md sources ([3805f81](https://github.com/unhappychoice/splashboard/commit/3805f81))

### 📝 Other Changes

- chore: bump version to v1.2.0 ([4b51ba6](https://github.com/unhappychoice/splashboard/commit/4b51ba6))
- test: isolate workspace-dependent fetcher tests ([731c9a6](https://github.com/unhappychoice/splashboard/commit/731c9a6))
- test(git): make workspace-dependent tests CI-portable ([8ef708f](https://github.com/unhappychoice/splashboard/commit/8ef708f))
- test: add focused layout helper tests that raised workspace line coverage from 92.9587% to 93.0482% and lifted `src/layout.rs` from 94.77% to 99.84%. ([bcaca9c](https://github.com/unhappychoice/splashboard/commit/bcaca9c))
- test: expand `src/runtime.rs` tests around cacheless fetches, join-error handling, drawing helpers, and placeholder assertions, raising workspace line coverage from 92.9259% to 93.0856%. ([27fcfeb](https://github.com/unhappychoice/splashboard/commit/27fcfeb))
- test: add focused `grid_heatmap` renderer tests that raised workspace line coverage from 92.7472% to 92.9284%. ([fbd4572](https://github.com/unhappychoice/splashboard/commit/fbd4572))
- test: add focused renderer tests for animated_postfx, raising workspace line coverage from 92.7016% to 92.8748%. ([0fc4d49](https://github.com/unhappychoice/splashboard/commit/0fc4d49))
- test: add focused tests for `deariary_recent`, raising workspace line coverage from 92.6176% to 92.8294%. ([03d3bc7](https://github.com/unhappychoice/splashboard/commit/03d3bc7))
- test: add targeted `gauge_battery` renderer tests that raised workspace line coverage from 92.57897334649556% to 92.74829864878194%. ([618ec69](https://github.com/unhappychoice/splashboard/commit/618ec69))
- test: add daemon coverage tests for `spawn_fetch_daemon` and the successful local `run_fetch_only` path, raising workspace line coverage from 92.6503% to 92.7048%. ([7cb71a9](https://github.com/unhappychoice/splashboard/commit/7cb71a9))
- test: add offline RSS fallback tests that raised workspace line coverage from 92.63% to 92.65%. ([bee9d14](https://github.com/unhappychoice/splashboard/commit/bee9d14))
- test: add focused `clock_sunrise` tests that raised workspace line coverage from 92.4549% to 92.5101%. ([ff71231](https://github.com/unhappychoice/splashboard/commit/ff71231))
- test: add focused core-renderer tests in `src/render/mod.rs`, increasing workspace line coverage from 92.3475% to 92.5787%. ([7a39dae](https://github.com/unhappychoice/splashboard/commit/7a39dae))
- test: add focused chart_pie renderer tests for metadata, donut mode, and named legend positions, raising workspace line coverage from 92.3102% to 92.4718%. ([1ad5126](https://github.com/unhappychoice/splashboard/commit/1ad5126))
- test: add focused `gauge_line` renderer tests that lifted workspace line coverage from 92.2764% to 92.3152% and brought `src/render/gauge_line.rs` to 100.0% line coverage. ([2c5bf23](https://github.com/unhappychoice/splashboard/commit/2c5bf23))
- test: add focused `status_badge` renderer tests that raised workspace line coverage from 92.3584% to 92.4011%. ([b9045a6](https://github.com/unhappychoice/splashboard/commit/b9045a6))
- test: add compact list_timeline renderer tests that raised workspace line coverage from 92.2760% to 92.3634%. ([eb9db7b](https://github.com/unhappychoice/splashboard/commit/eb9db7b))
- test: add targeted `text_ascii` renderer tests that raised workspace line coverage from 92.2181% to 92.2760%. ([88127d3](https://github.com/unhappychoice/splashboard/commit/88127d3))
- test: add focused tests for `clock_state`, increasing workspace line coverage from 92.0713% to 92.0879%. ([f1b8b9c](https://github.com/unhappychoice/splashboard/commit/f1b8b9c))
- test: add runtime tests for daemon-side cache persistence and refresh placeholder reapplication, raising workspace line coverage from 92.1672% to 92.1941%. ([64aea4b](https://github.com/unhappychoice/splashboard/commit/64aea4b))
- test: add focused tests for `git_commits_activity`, raising workspace line coverage from 92.8138% to 92.9857%. ([7a40111](https://github.com/unhappychoice/splashboard/commit/7a40111))
- test: cover text_markdown renderer metadata, fallback, and stylesheet branches, raising workspace line coverage from 91.9073% to 91.9962%. ([165500a](https://github.com/unhappychoice/splashboard/commit/165500a))
- test: add explicit `gauge_circle` renderer tests, raising workspace line coverage from 92.00% to 92.03%. ([d9e4e8b](https://github.com/unhappychoice/splashboard/commit/d9e4e8b))
- test: add compact contract and shape-specific fetch tests for `static_text`, raising workspace line coverage from 91.9659% to 92.0019%. ([4d27050](https://github.com/unhappychoice/splashboard/commit/4d27050))
- test: add focused `clock_almanac` tests for catalog, sample, placeholder, and `TextBlock` paths, raising workspace line coverage from 91.9014% to 91.9659%. ([4deeb25](https://github.com/unhappychoice/splashboard/commit/4deeb25))
- test: add focused tests for the chart_sparkline renderer, raising workspace line coverage from 91.85% to 91.90%. ([0d48eaf](https://github.com/unhappychoice/splashboard/commit/0d48eaf))
- test: add focused clock_timezones tests that raised workspace line coverage from 91.8186% to 91.8529%. ([52b218b](https://github.com/unhappychoice/splashboard/commit/52b218b))
- test: add focused `media_image` renderer tests, raising workspace line coverage from 91.62% to 91.82%. ([c16d896](https://github.com/unhappychoice/splashboard/commit/c16d896))
- test: raise workspace line coverage from 91.6832% to 91.7408% by adding focused renderer tests for `chart_scatter`. ([6d9bd1b](https://github.com/unhappychoice/splashboard/commit/6d9bd1b))
- test: add focused `chart_line` renderer tests that raised workspace line coverage from 91.6342% to 91.6800%. ([71b48b6](https://github.com/unhappychoice/splashboard/commit/71b48b6))
- test: raise workspace line coverage from 91.5251% to 91.6342% by adding focused tests for `src/render/grid_calendar.rs` and lifting that file from 87.39% to 99.75%. ([61a8692](https://github.com/unhappychoice/splashboard/commit/61a8692))
- test: add focused render-path tests for the install picker, raising workspace line coverage from 90.4058% to 91.3946%. ([1058c83](https://github.com/unhappychoice/splashboard/commit/1058c83))
- test: raise workspace line coverage from 90.3495% to 90.5341% by adding focused tests for `code_language_logo`. ([e30e191](https://github.com/unhappychoice/splashboard/commit/e30e191))
- test: add compact `animated_boot` renderer tests for metadata exposure and live boot-log rendering, raising workspace line coverage from 90.3873% to 90.4780%. ([ffcd60b](https://github.com/unhappychoice/splashboard/commit/ffcd60b))
- test: add offline catalog and pre-network tests for `reddit_user_comments`, raising workspace line coverage from 90.34% to 90.39%. ([d752672](https://github.com/unhappychoice/splashboard/commit/d752672))
- test: add focused contract tests for `src/fetcher/mod.rs`, raising workspace line coverage from 90.0883% to 90.2130%. ([52101a9](https://github.com/unhappychoice/splashboard/commit/52101a9))
- test: add offline tests for `reddit_subreddit_posts`, raising workspace line coverage from 90.1778% to 90.2164% and `src/fetcher/reddit/subreddit_posts.rs` line coverage to 93.68%. ([120135e](https://github.com/unhappychoice/splashboard/commit/120135e))
- test: raise workspace line coverage from 90.0550% to 90.1778% by adding focused tests for `src/fetcher/code/loc.rs`. ([1cbc09d](https://github.com/unhappychoice/splashboard/commit/1cbc09d))
- test: add focused `install::rc` tests that raised workspace line coverage from 89.99% to 90.06%. ([f858149](https://github.com/unhappychoice/splashboard/commit/f858149))
- test: add contract and workspace-backed fetch tests for `git_recent_commits`, raising workspace line coverage from 89.7980% to 89.9867% and passing the full quality gate. ([e2bbfed](https://github.com/unhappychoice/splashboard/commit/e2bbfed))
- test: add contract and workspace-backed fetch tests for `git_blame_heatmap`, raising workspace line coverage from 89.7229% to 89.9282%. ([e3f0e8d](https://github.com/unhappychoice/splashboard/commit/e3f0e8d))
- test: add focused config helper tests that raised workspace line coverage from 89.6913% to 89.7229% and lifted `src/config.rs` from 87.37% to 95.92%. ([3d838ae](https://github.com/unhappychoice/splashboard/commit/3d838ae))
- test: add focused tests for `animated_figlet_morph`, raising workspace line coverage from 89.6185% to 89.6865%. ([dcd1103](https://github.com/unhappychoice/splashboard/commit/dcd1103))
- test: add focused runtime helper tests that raised workspace line coverage from 89.5061% to 89.6185%. ([b7d1af4](https://github.com/unhappychoice/splashboard/commit/b7d1af4))
- test: add focused tests for the non-interactive installer flow and helper branches, raising workspace line coverage from 89.3218% to 89.5061%. ([0811555](https://github.com/unhappychoice/splashboard/commit/0811555))
- test: add offline and fallback coverage tests for `deariary_today`, raising workspace line coverage from 89.20% to 89.32%. ([1ce7876](https://github.com/unhappychoice/splashboard/commit/1ce7876))
- test: add focused tests for `src/render/animated_splitflap.rs`, raising workspace line coverage from 89.1658% to 89.3353%. ([d804332](https://github.com/unhappychoice/splashboard/commit/d804332))
- test: raise workspace line coverage from 89.0778% to 89.2161% by adding comprehensive tests for `clock_derived` branch and dispatch logic. ([0e16373](https://github.com/unhappychoice/splashboard/commit/0e16373))
- test: expand `code_largest_files` tests and raised workspace line coverage from 88.9259% to 89.1096%. ([9feffd3](https://github.com/unhappychoice/splashboard/commit/9feffd3))
- test: raise workspace line coverage from 88.6290% to 88.8738% by adding offline coverage tests for github_languages. ([a409ea9](https://github.com/unhappychoice/splashboard/commit/a409ea9))
- test: add contract and real-fetch tests for `git_churn`, raising workspace line coverage from 88.6534% to 88.7655%. ([a10daf7](https://github.com/unhappychoice/splashboard/commit/a10daf7))
- test: add offline contract and pre-request tests for calendar_holidays, raising workspace line coverage from 88.4253% to 88.5166%. ([c999086](https://github.com/unhappychoice/splashboard/commit/c999086))
- test: expand `code_todos` tests to cover contract metadata, parser edge cases, and real fetch paths, raising workspace line coverage from 88.4355% to 88.4844%. ([a779205](https://github.com/unhappychoice/splashboard/commit/a779205))
- test: add focused realtime tests for `clock_countdown`, raising workspace line coverage from 88.1652% to 88.3898%. ([9d1732b](https://github.com/unhappychoice/splashboard/commit/9d1732b))
- test: add offline tests for `github_user`, raising workspace line coverage from 87.92% to 88.30% and that file's line coverage from 60.11% to 98.02%. ([0aade55](https://github.com/unhappychoice/splashboard/commit/0aade55))
- test: add contract, fallback, and real fetch-path tests for `code_files`, raising workspace line coverage from 87.8354% to 88.1328%. ([1a5f16b](https://github.com/unhappychoice/splashboard/commit/1a5f16b))
- test: add contract and fetch-path tests for `git_stash_count`, increasing workspace line coverage from 87.97% to 88.04%. ([6aad076](https://github.com/unhappychoice/splashboard/commit/6aad076))
- test: add focused tests for `src/render/animated_scanlines.rs`, raising workspace line coverage from 87.8432% to 87.9710%. ([354e17d](https://github.com/unhappychoice/splashboard/commit/354e17d))
- test: raise workspace line coverage from 87.48% to 87.84% by adding offline contract and fetch-path tests for `wikipedia_on_this_day`. ([741e560](https://github.com/unhappychoice/splashboard/commit/741e560))
- test: add canonical sample contract tests for `src/samples.rs`, raising workspace line coverage from 87.5185% to 87.5400%. ([e4f57ed](https://github.com/unhappychoice/splashboard/commit/e4f57ed))
- test: expand `git_latest_tag` test coverage across contract, selection, timezone, and fetch paths, raising workspace line coverage from 87.5021% to 87.5897%. ([fe641fd](https://github.com/unhappychoice/splashboard/commit/fe641fd))
- test: raise workspace line coverage from 87.3161% to 87.5021% by expanding tests for `src/fetcher/git/contributors.rs`. ([f704adb](https://github.com/unhappychoice/splashboard/commit/f704adb))
- test: add trust-store persistence and env-override tests in `src/trust.rs`, raising workspace line coverage from 87.23% to 87.37%. ([86fe09c](https://github.com/unhappychoice/splashboard/commit/86fe09c))
- test: add offline contract and pre-network validation tests for `hackernews_top`, raising workspace line coverage from 86.9138% to 87.0221%. ([fdfa02b](https://github.com/unhappychoice/splashboard/commit/fdfa02b))
- test: add offline contract and pre-auth tests for github_contributions, raising workspace line coverage from 86.7645% to 87.1353%. ([7a36f29](https://github.com/unhappychoice/splashboard/commit/7a36f29))
- test: raise workspace line coverage from 86.8550% to 87.0562% by adding offline contract and fetch-path tests for `code_comments`. ([0fc5be6](https://github.com/unhappychoice/splashboard/commit/0fc5be6))
- test: add focused `git_worktrees` tests for fetcher contract and linked/detached worktree branches, increasing workspace line coverage from 86.6380% to 86.8327%. ([4419763](https://github.com/unhappychoice/splashboard/commit/4419763))
- test: raise workspace line coverage from 86.5669% to 86.6380% by covering offline contract and fallback paths in `deariary_on_this_day`. ([9d71d18](https://github.com/unhappychoice/splashboard/commit/9d71d18))
- test: add offline RSS fetcher tests that raised workspace line coverage from 86.4481% to 86.6538%. ([6afa2b3](https://github.com/unhappychoice/splashboard/commit/6afa2b3))
- test: add offline contract and error-path tests for `hackernews_user`, lifting workspace line coverage from 86.3648% to 86.5606%. ([1f86829](https://github.com/unhappychoice/splashboard/commit/1f86829))
- test: add daemon fallback-path tests for dashboard/source loading and raised workspace line coverage from 86.27% to 86.36%. ([9f660c0](https://github.com/unhappychoice/splashboard/commit/9f660c0))
- test: add offline contract tests for `github_repo`, raising workspace line coverage from 86.0426% to 86.2513%. ([9faddbd](https://github.com/unhappychoice/splashboard/commit/9faddbd))
- test: add focused install preview helper tests, raising workspace line coverage from 85.7712% to 86.1418%. ([f33be45](https://github.com/unhappychoice/splashboard/commit/f33be45))
- test: expand `git_status` tests to cover catalog, detached-head, and upstream-divergence branches, raising workspace line coverage from 85.6343% to 85.9135%. ([8081357](https://github.com/unhappychoice/splashboard/commit/8081357))
- test: add focused offline tests for `github_avatar`, raising workspace line coverage from 85.2561% to 85.6086%. ([35c15be](https://github.com/unhappychoice/splashboard/commit/35c15be))
- test: add comprehensive ReadStore tests that raised workspace line coverage from 85.3451% to 85.6211%. ([09e3dc8](https://github.com/unhappychoice/splashboard/commit/09e3dc8))
- test: add offline coverage tests for `hackernews_user_comments`, raising workspace line coverage from 85.24% to 85.35%. ([24f9c8e](https://github.com/unhappychoice/splashboard/commit/24f9c8e))
- test: add deterministic tests for the system fetcher family, raising workspace line coverage from 84.5802% to 85.1284%. ([28574ca](https://github.com/unhappychoice/splashboard/commit/28574ca))
- test: expand `hackernews_user_submissions` test coverage around fetcher metadata, cache/sample outputs, and failure branches, raising workspace line coverage from 84.3945% to 84.4869%. ([30ef11b](https://github.com/unhappychoice/splashboard/commit/30ef11b))
- test: add deterministic tests for `clock_ratio`, raising workspace line coverage from 84.2212% to 84.3911%. ([7e4373d](https://github.com/unhappychoice/splashboard/commit/7e4373d))
- test: add offline branch coverage for `random_dog`, raising workspace line coverage from 83.78% to 84.13%. ([6cd42db](https://github.com/unhappychoice/splashboard/commit/6cd42db))
- test: add focused tests for xtask snapshot preview generation, raising workspace line coverage from 83.26% to 83.78%. ([864d231](https://github.com/unhappychoice/splashboard/commit/864d231))
- test: add offline tests for `github_notifications`, increasing workspace line coverage from 82.7084% to 83.2412%. ([43fd3df](https://github.com/unhappychoice/splashboard/commit/43fd3df))
- test: add offline coverage tests for the shared GitHub client, raising workspace line coverage from 82.6482% to 83.1828%. ([00f2b34](https://github.com/unhappychoice/splashboard/commit/00f2b34))
- test: add offline coverage tests for `random_cat`, raising workspace line coverage from 82.9108% to 82.9580%. ([b1c5356](https://github.com/unhappychoice/splashboard/commit/b1c5356))
- test: add targeted logging tests that raised workspace line coverage from 82.40% to 82.49%. ([8a6e6bd](https://github.com/unhappychoice/splashboard/commit/8a6e6bd))
- test: add offline wrapper tests for `reddit_user_posts`, raising workspace line coverage from 82.68% to 82.87%. ([2fcfac0](https://github.com/unhappychoice/splashboard/commit/2fcfac0))
- test: add focused offline tests for the weather fetcher, raising workspace line coverage from 82.4885% to 82.7868%. ([0e653cb](https://github.com/unhappychoice/splashboard/commit/0e653cb))
- test: add offline tests for the deariary client cache and helper branches, raising workspace line coverage from 82.2704% to 82.4885%. ([5b5bd60](https://github.com/unhappychoice/splashboard/commit/5b5bd60))
- test: add offline tests for `wikipedia_random`, raising workspace line coverage from 82.0857% to 82.1378%. ([16ba0ab](https://github.com/unhappychoice/splashboard/commit/16ba0ab))
- test: add offline coverage tests for `github_action_history`, raising workspace line coverage from 81.5950% to 81.9123%. ([620760d](https://github.com/unhappychoice/splashboard/commit/620760d))
- test: add offline tests for the Todoist fetcher helpers and pre-network failure paths, raising workspace line coverage from 81.11% to 81.75%. ([07cf074](https://github.com/unhappychoice/splashboard/commit/07cf074))
- test: add offline coverage tests for `github_assigned_issues`, raising workspace line coverage from 80.58% to 81.13%. ([37ea2fe](https://github.com/unhappychoice/splashboard/commit/37ea2fe))
- test: add focused tests for `git_repo_name`, covering remote selection and fetch output, and raised workspace line coverage from 80.8442% to 80.9253%. ([6b7f65a](https://github.com/unhappychoice/splashboard/commit/6b7f65a))
- test: add offline coverage tests for `github_review_requests`, raising workspace line coverage from 80.69% to 80.82%. ([b536ba1](https://github.com/unhappychoice/splashboard/commit/b536ba1))
- test: add deterministic tests for `src/fetcher/github/my_prs.rs`, increasing workspace line coverage from 80.2391% to 80.6566%. ([44b3ffb](https://github.com/unhappychoice/splashboard/commit/44b3ffb))
- test(linear): cover remaining shape × branch gaps ([4ae87b0](https://github.com/unhappychoice/splashboard/commit/4ae87b0))
- chore(gnhf): drop --max-tokens cap from run.sh ([dbca0e7](https://github.com/unhappychoice/splashboard/commit/dbca0e7))
- chore(linear): use sort_by_key/Reverse to satisfy clippy 1.95 ([0f2ec56](https://github.com/unhappychoice/splashboard/commit/0f2ec56))
- chore(catalog): drop wakatime_* from roadmap ([4267d01](https://github.com/unhappychoice/splashboard/commit/4267d01))
- docs(screenshots): add demo.gif ([8650cc6](https://github.com/unhappychoice/splashboard/commit/8650cc6))
- test(github): add focused tests for contributors_monthly fetcher ([3eddf67](https://github.com/unhappychoice/splashboard/commit/3eddf67))
- chore: update flake.nix hashes for v1.1.1 ([f69d3b7](https://github.com/unhappychoice/splashboard/commit/f69d3b7))


## [1.1.1] - 2026-04-29

### 🐛 Bug Fixes

- fix(render): let animated wrappers pass inner-renderer fields through ([80cf479](https://github.com/unhappychoice/splashboard/commit/80cf479))

### 📝 Other Changes

- chore: bump version to v1.1.1 ([05ca526](https://github.com/unhappychoice/splashboard/commit/05ca526))
- chore: update flake.nix hashes for v1.1.0 ([bac3e65](https://github.com/unhappychoice/splashboard/commit/bac3e65))


## [1.1.0] - 2026-04-29

### ✨ Features

- feat(config): add auto_home / auto_on_cd toggles to opt out of auto-display ([83f7d42](https://github.com/unhappychoice/splashboard/commit/83f7d42))

### 🐛 Bug Fixes

- fix(xtask): step past OSC 8 link cells in HTML snapshot ([ef8d1f8](https://github.com/unhappychoice/splashboard/commit/ef8d1f8))

### 📝 Other Changes

- chore: bump version to v1.1.0 ([8468dac](https://github.com/unhappychoice/splashboard/commit/8468dac))
- test(github): add offline tests for repo_prs fetcher ([0c325ff](https://github.com/unhappychoice/splashboard/commit/0c325ff))
- test(github): add offline tests for repo_issues fetcher ([74a2726](https://github.com/unhappychoice/splashboard/commit/74a2726))
- test(hackernews): cover shared HTTP client with offline tests ([23fdc12](https://github.com/unhappychoice/splashboard/commit/23fdc12))
- test(github): add offline tests for good_first_issues ([30c9eee](https://github.com/unhappychoice/splashboard/commit/30c9eee))
- test(github): cover recent_releases fetcher ([010c9df](https://github.com/unhappychoice/splashboard/commit/010c9df))
- test(github): cover shared issue/PR item renderer helper ([9efefd9](https://github.com/unhappychoice/splashboard/commit/9efefd9))
- chore(gnhf): require English summary/body in loop prompts ([fc5d3bc](https://github.com/unhappychoice/splashboard/commit/fc5d3bc))
- perf(build): tighten release profile ([7666931](https://github.com/unhappychoice/splashboard/commit/7666931))
- perf(cli): use sync dispatch and lazy Tokio init ([e6f5d5e](https://github.com/unhappychoice/splashboard/commit/e6f5d5e))
- chore(gnhf): pass --prevent-sleep off to gnhf ([cf859fc](https://github.com/unhappychoice/splashboard/commit/cf859fc))
- test(fetcher): cover github_action_status untested branches ([91235c2](https://github.com/unhappychoice/splashboard/commit/91235c2))
- test(xtask): cover dashboard_snapshot module ([ec3fb0d](https://github.com/unhappychoice/splashboard/commit/ec3fb0d))
- chore(gnhf): pick a loop via run.sh argument, drop worktree mode ([f6239a6](https://github.com/unhappychoice/splashboard/commit/f6239a6))
- chore(gnhf): add launcher for parallel overnight loops ([d732532](https://github.com/unhappychoice/splashboard/commit/d732532))
- chore(gnhf): save overnight loop prompts ([3bbb4ad](https://github.com/unhappychoice/splashboard/commit/3bbb4ad))
- test(render): add animated_wave regression tests ([6b1d47b](https://github.com/unhappychoice/splashboard/commit/6b1d47b))
- test(render): add animated_typewriter regression tests ([d821df6](https://github.com/unhappychoice/splashboard/commit/d821df6))
- test(render): add animated_boot regression tests ([7f7cae4](https://github.com/unhappychoice/splashboard/commit/7f7cae4))
- test(render): improve text_plain coverage ([96766c6](https://github.com/unhappychoice/splashboard/commit/96766c6))
- docs(site): preset gallery in showcases + renderer-page previews ([4a8ca0a](https://github.com/unhappychoice/splashboard/commit/4a8ca0a))
- chore: update flake.nix hashes for v1.0.0 ([8d8a2bb](https://github.com/unhappychoice/splashboard/commit/8d8a2bb))


## [1.0.0] - 2026-04-28

### ✨ Features

- feat(time): project-wide locale + timezone consistency ([01a3a1e](https://github.com/unhappychoice/splashboard/commit/01a3a1e))
- feat(secrets): load tokens from $HOME/.splashboard/secrets.toml ([ae10678](https://github.com/unhappychoice/splashboard/commit/ae10678))
- feat(fetcher): add deariary_* family for diary entries ([a473344](https://github.com/unhappychoice/splashboard/commit/a473344))
- feat(templates): add project_codebase preset ([dea9a21](https://github.com/unhappychoice/splashboard/commit/dea9a21))
- feat(render): expose bar_gap option for chart_bar ([05e574d](https://github.com/unhappychoice/splashboard/commit/05e574d))
- feat(fetcher): fill missing shape coverage across 14 fetchers ([9e09185](https://github.com/unhappychoice/splashboard/commit/9e09185))
- feat(fetcher): add `code_largest_files` for refactor-candidate hunting ([bd9b4d4](https://github.com/unhappychoice/splashboard/commit/bd9b4d4))
- feat(fetcher): add code_files — top-level-dir ranking + headline file count ([342c2b3](https://github.com/unhappychoice/splashboard/commit/342c2b3))
- feat(fetcher): add `code_language_logo` for repo-language Devicon hero ([45d66ea](https://github.com/unhappychoice/splashboard/commit/45d66ea))
- feat(fetcher): expand `code_loc` with 4 more shapes and `unit` option ([b2362b8](https://github.com/unhappychoice/splashboard/commit/b2362b8))
- feat(fetcher): add `code_loc` for tracked-line counts per language ([637c517](https://github.com/unhappychoice/splashboard/commit/637c517))
- feat(fetcher): add `git_churn` for top-changed files in last N days ([08a859e](https://github.com/unhappychoice/splashboard/commit/08a859e))
- feat(fetcher): add `git_age` for repository age from first commit ([5a885fa](https://github.com/unhappychoice/splashboard/commit/5a885fa))
- feat(reference): add description() to Fetcher and Renderer traits ([87a7f22](https://github.com/unhappychoice/splashboard/commit/87a7f22))
- feat(templates): add home_feed preset — morning briefing ([536425c](https://github.com/unhappychoice/splashboard/commit/536425c))
- feat(fetcher): add fortune cookie fetcher ([ad2422f](https://github.com/unhappychoice/splashboard/commit/ad2422f))
- feat(fetcher): externalize quote_of_day data and expand to 567 entries ([1ff2aef](https://github.com/unhappychoice/splashboard/commit/1ff2aef))
- feat(fetcher): add reddit public listing fetchers ([d018165](https://github.com/unhappychoice/splashboard/commit/d018165))
- feat(fetcher): add calendar_holidays — public-holiday data via Nager.Date ([43aafe6](https://github.com/unhappychoice/splashboard/commit/43aafe6))
- feat(fetcher): add rss feed reader (RSS 2.0 / Atom / JSON Feed) ([1dd82c7](https://github.com/unhappychoice/splashboard/commit/1dd82c7))
- feat(fetcher): add wikipedia_on_this_day, wikipedia_featured, wikipedia_random ([9743585](https://github.com/unhappychoice/splashboard/commit/9743585))
- feat(render): add text_markdown renderer + MarkdownTextBlock shape ([3cfb197](https://github.com/unhappychoice/splashboard/commit/3cfb197))
- feat(fetcher): add hackernews_user, _user_submissions, _user_comments ([1d676af](https://github.com/unhappychoice/splashboard/commit/1d676af))
- feat(fetcher): add todoist_tasks with structured filters ([9dfa7ce](https://github.com/unhappychoice/splashboard/commit/9dfa7ce))
- feat(template): switch github_* widgets to list_links ([37bacf9](https://github.com/unhappychoice/splashboard/commit/37bacf9))
- feat(fetcher): emit LinkedTextBlock from github_* feed fetchers ([760813c](https://github.com/unhappychoice/splashboard/commit/760813c))
- feat(fetcher): add hn_top fetcher ([e0673d6](https://github.com/unhappychoice/splashboard/commit/e0673d6))
- feat(render): add LinkedTextBlock shape and list_links renderer ([214dedb](https://github.com/unhappychoice/splashboard/commit/214dedb))
- feat(render): add gauge_thermometer vertical mercury-tube renderer ([edfce20](https://github.com/unhappychoice/splashboard/commit/edfce20))
- feat(render): list_ranking renderer for Bars shape ([f432bac](https://github.com/unhappychoice/splashboard/commit/f432bac))
- feat(render): chart_histogram fills width and shows long-tail bins ([9db60bf](https://github.com/unhappychoice/splashboard/commit/9db60bf))
- feat(render): chart_histogram axis labels ([3f121aa](https://github.com/unhappychoice/splashboard/commit/3f121aa))
- feat(fetcher): add system_battery realtime fetcher ([c57408a](https://github.com/unhappychoice/splashboard/commit/c57408a))
- feat(render): add `chart_histogram` ([db3f15c](https://github.com/unhappychoice/splashboard/commit/db3f15c))
- feat(cli): add `license` subcommand to print embedded license text ([ba0a6f1](https://github.com/unhappychoice/splashboard/commit/ba0a6f1))
- feat(theme): expand built-in presets from 6 to 26 ([853d707](https://github.com/unhappychoice/splashboard/commit/853d707))
- feat(render): add gauge_segment renderer for Ratio shape ([48ea61a](https://github.com/unhappychoice/splashboard/commit/48ea61a))
- feat(fetcher): add project_todo_in_code ([59b8fe7](https://github.com/unhappychoice/splashboard/commit/59b8fe7))
- feat(render): add tone option to gauge_battery ([1c85741](https://github.com/unhappychoice/splashboard/commit/1c85741))
- feat(render): add gauge_battery renderer for Ratio shape ([26ff39c](https://github.com/unhappychoice/splashboard/commit/26ff39c))
- feat(config): layout spacers via optional widget + row gap sugar ([2e601b4](https://github.com/unhappychoice/splashboard/commit/2e601b4))
- feat(templates): add recent commits to project_minimal ([aa4e80d](https://github.com/unhappychoice/splashboard/commit/aa4e80d))
- feat(templates): ship home_minimal / project_splash / project_minimal ([fa1c880](https://github.com/unhappychoice/splashboard/commit/fa1c880))
- feat(ops): surface fetch errors in UI and log file ([7319672](https://github.com/unhappychoice/splashboard/commit/7319672))
- feat(render): glitch_in effect + animated_splitflap + animated_wave renderers ([034343c](https://github.com/unhappychoice/splashboard/commit/034343c))
- feat(render): bounce / elastic / checkerboard / neon effects + animated_scanlines renderer ([8b3c0eb](https://github.com/unhappychoice/splashboard/commit/8b3c0eb))
- feat(render): signature opening animations for home_splash hero (#97) ([61d0ce5](https://github.com/unhappychoice/splashboard/commit/61d0ce5))
- feat(config): render home splash when cd-ing to $HOME ([d7f790d](https://github.com/unhappychoice/splashboard/commit/d7f790d))
- feat(install): add `splashboard install` one-shot onboarding ([f86efb3](https://github.com/unhappychoice/splashboard/commit/f86efb3))
- feat(layout,render): height = "auto" via renderer-driven natural_height ([794b13c](https://github.com/unhappychoice/splashboard/commit/794b13c))
- feat(templates): switch all ASCII-art heroes to ansi_shadow figlet ([2e53713](https://github.com/unhappychoice/splashboard/commit/2e53713))
- feat(fetcher,templates): clock_almanac rollup + 2-column home_daily layout ([cc9a745](https://github.com/unhappychoice/splashboard/commit/cc9a745))
- feat(fetcher,templates): enrich home_daily — quote of day, world clock, system stats ([268a5a2](https://github.com/unhappychoice/splashboard/commit/268a5a2))
- feat(clock_derived): hemisphere option for season ([13d3fc6](https://github.com/unhappychoice/splashboard/commit/13d3fc6))
- feat(fetcher,templates): github_user profile + daily layout rework ([99c306f](https://github.com/unhappychoice/splashboard/commit/99c306f))
- feat(templates,text_ascii): flip splash/daily densities + add 4 modern figlet fonts ([f890e52](https://github.com/unhappychoice/splashboard/commit/f890e52))
- feat(templates,layout): design pass — centred section dividers, block heroes, real content ([7a5a2e1](https://github.com/unhappychoice/splashboard/commit/7a5a2e1))
- feat(templates): preview example + layout fixes from first render pass ([c3da7ed](https://github.com/unhappychoice/splashboard/commit/c3da7ed))
- feat(templates): ship 0.x preset dashboards ([ef80250](https://github.com/unhappychoice/splashboard/commit/ef80250))
- feat(runtime): spinner under --wait even when stale cache exists ([a9e2d79](https://github.com/unhappychoice/splashboard/commit/a9e2d79))
- feat(fetcher): add fetchers and shape extensions for 0.x presets ([2048bcb](https://github.com/unhappychoice/splashboard/commit/2048bcb))
- feat(fetcher): github_languages — repo language byte-count breakdown ([c3c7df0](https://github.com/unhappychoice/splashboard/commit/c3c7df0))
- feat(fetcher): add project_name + project for dynamic repo identity ([be3d763](https://github.com/unhappychoice/splashboard/commit/be3d763))
- feat(payload): RatioData.denominator for gauge_line fraction format ([db76005](https://github.com/unhappychoice/splashboard/commit/db76005))
- feat(render): layout border-sides + renderer option polish for 0.x presets ([6bf7796](https://github.com/unhappychoice/splashboard/commit/6bf7796))
- feat(render): draw zero-value baseline on sparkline so sparse series stay legible ([ec45876](https://github.com/unhappychoice/splashboard/commit/ec45876))
- feat(render): add animated_postfx renderer wrapping tachyonfx effects ([cda2044](https://github.com/unhappychoice/splashboard/commit/cda2044))
- feat(theme): expose Splash default as `preset = "splash"` / `"default"` (#17) ([c195186](https://github.com/unhappychoice/splashboard/commit/c195186))
- feat(xtask): render Theme tokens table on each renderer's reference page (#17) ([db3c2ca](https://github.com/unhappychoice/splashboard/commit/db3c2ca))
- feat(runtime/layout/config): wire Theme, bg levels, and padding through draw (#17) ([c72c2e4](https://github.com/unhappychoice/splashboard/commit/c72c2e4))
- feat(render): thread &Theme through Renderer::render + per-renderer color_keys (#17) ([7f9cb61](https://github.com/unhappychoice/splashboard/commit/7f9cb61))
- feat(theme): Theme / ColorKey module with Splash default + 5 presets (#17) ([452b503](https://github.com/unhappychoice/splashboard/commit/452b503))
- feat(runtime): flush clipped rows to scrollback after animation ([e34cba9](https://github.com/unhappychoice/splashboard/commit/e34cba9))
- feat(fetcher): add github_* fetcher family ([6623b51](https://github.com/unhappychoice/splashboard/commit/6623b51))
- feat(catalog): add `splashboard catalog` CLI for browsing the widget catalog ([e778e38](https://github.com/unhappychoice/splashboard/commit/e778e38))
- feat(docs): generate widget catalogue site via xtask + astro/starlight ([6d1dc9f](https://github.com/unhappychoice/splashboard/commit/6d1dc9f))
- feat(catalog): declare option schemas and sample output per fetcher/renderer ([bcaa0f6](https://github.com/unhappychoice/splashboard/commit/bcaa0f6))
- feat(fetcher): split clock into clock_* sibling fetchers ([bcd5523](https://github.com/unhappychoice/splashboard/commit/bcd5523))
- feat(fetcher): add 8 gix-backed git fetchers (#41) ([0feb955](https://github.com/unhappychoice/splashboard/commit/0feb955))
- feat(fetcher): cross-platform system fetchers via sysinfo ([3c30d23](https://github.com/unhappychoice/splashboard/commit/3c30d23))
- feat(runtime): show "… +N rows" hint when viewport clips ([f75d0e2](https://github.com/unhappychoice/splashboard/commit/f75d0e2))
- feat(render): add pie_chart renderer over Bars shape ([8144665](https://github.com/unhappychoice/splashboard/commit/8144665))
- feat(fetcher): multi-shape fetchers + renderer-derived shape (#44) ([1680c4f](https://github.com/unhappychoice/splashboard/commit/1680c4f))
- feat(render): add timeline renderer for timestamped event lists ([eb54a2d](https://github.com/unhappychoice/splashboard/commit/eb54a2d))
- feat(payload): add Timeline shape ([5ecdb9a](https://github.com/unhappychoice/splashboard/commit/5ecdb9a))
- feat(render): add badge renderer for single-status indicators ([9767947](https://github.com/unhappychoice/splashboard/commit/9767947))
- feat(render): prettier empty-state — icon + caption, vertically centered ([973c0ee](https://github.com/unhappychoice/splashboard/commit/973c0ee))
- feat(render): shared empty-state placeholder for widgets with no data ([d26b11e](https://github.com/unhappychoice/splashboard/commit/d26b11e))
- feat(paths): consolidate splashboard state under \$HOME/.splashboard/ + ship ReadStore fetcher ([d548f55](https://github.com/unhappychoice/splashboard/commit/d548f55))
- feat(render): heatmap honours align option for horizontal placement ([9eb2811](https://github.com/unhappychoice/splashboard/commit/9eb2811))
- feat(render): month labels above heatmap ([8f8eeab](https://github.com/unhappychoice/splashboard/commit/8f8eeab))
- feat(render): add heatmap renderer for GitHub-style contribution grids ([302d93a](https://github.com/unhappychoice/splashboard/commit/302d93a))
- feat(fetcher): introduce RealtimeFetcher trait for clock-like widgets ([efdab98](https://github.com/unhappychoice/splashboard/commit/efdab98))
- feat(config): auto-size inline viewport from row heights ([00c97d7](https://github.com/unhappychoice/splashboard/commit/00c97d7))
- feat(config): reorganise .splashboard/config.toml into hero + dense layout ([67f1dd6](https://github.com/unhappychoice/splashboard/commit/67f1dd6))
- feat(layout): flex option for horizontal placement inside a row ([650ca1b](https://github.com/unhappychoice/splashboard/commit/650ca1b))
- feat(layout): make border opt-in (default: none) ([039318c](https://github.com/unhappychoice/splashboard/commit/039318c))
- feat(layout,render): chromeless widgets + content alignment ([e12bf0b](https://github.com/unhappychoice/splashboard/commit/e12bf0b))
- feat(config): showcase every renderer in .splashboard/config.toml ([e902df3](https://github.com/unhappychoice/splashboard/commit/e902df3))
- feat(render): figlet + animated_typewriter + multi-frame wait loop ([c00186e](https://github.com/unhappychoice/splashboard/commit/c00186e))
- feat(render): calendar (new Calendar shape) + scatter (PointSeries) ([94c6aa7](https://github.com/unhappychoice/splashboard/commit/94c6aa7))
- feat(render): add line_gauge (Ratio) and list (Lines) renderers ([0be6c28](https://github.com/unhappychoice/splashboard/commit/0be6c28))
- feat(fetcher): real clock + multi-line static text (#7) ([3eb59be](https://github.com/unhappychoice/splashboard/commit/3eb59be))
- feat(trust): per-widget trust gate for project-local configs (#27) ([6033ccb](https://github.com/unhappychoice/splashboard/commit/6033ccb))
- feat(runtime): detach fetch into a background child process ([ad97451](https://github.com/unhappychoice/splashboard/commit/ad97451))
- feat(runtime): cross-process fetch lock per cache key ([aa6e7a2](https://github.com/unhappychoice/splashboard/commit/aa6e7a2))
- feat(runtime): content-addressed cache keys ([7c3647f](https://github.com/unhappychoice/splashboard/commit/7c3647f))
- feat(runtime): async fetch + on-disk cache layer (#4) ([160f2dd](https://github.com/unhappychoice/splashboard/commit/160f2dd))
- feat(shell): skip render when terminal is smaller than 40×16 ([2612c37](https://github.com/unhappychoice/splashboard/commit/2612c37))
- feat(shell): tighter render guards for CI / dumb TTY / AI contexts ([1f5cb24](https://github.com/unhappychoice/splashboard/commit/1f5cb24))
- feat(shell): --on-cd mode; cd hooks render only when cwd holds a config ([796adb2](https://github.com/unhappychoice/splashboard/commit/796adb2))
- feat(shell): add `splashboard init <shell>` for rc-file integration (#6) ([d921b50](https://github.com/unhappychoice/splashboard/commit/d921b50))
- feat(config): also discover .splashboard/config.toml directory form ([780214a](https://github.com/unhappychoice/splashboard/commit/780214a))
- feat(config): TOML config loading with per-directory discovery (#2) ([aaaa4d3](https://github.com/unhappychoice/splashboard/commit/aaaa4d3))
- feat(layout): add Max and Percentage sizing variants ([a11ff1c](https://github.com/unhappychoice/splashboard/commit/a11ff1c))
- feat(layout): add declarative layout engine with nested rows/cols (#3) ([f1837cc](https://github.com/unhappychoice/splashboard/commit/f1837cc))
- feat(demo): showcase six render types in a 2×3 grid ([8fa068b](https://github.com/unhappychoice/splashboard/commit/8fa068b))
- feat(render): auto-detect image protocol (sixel / kitty / iTerm2) ([c203e11](https://github.com/unhappychoice/splashboard/commit/c203e11))
- feat(render): implement image renderer via ratatui-image ([ed702ec](https://github.com/unhappychoice/splashboard/commit/ed702ec))
- feat(render): implement 7 renderers dispatching from Payload variants ([deaf7c1](https://github.com/unhappychoice/splashboard/commit/deaf7c1))
- feat(payload): add Payload tagged union for widget output ([5439c44](https://github.com/unhappychoice/splashboard/commit/5439c44))
- feat: scaffold binary crate and render "Hello splashboard" ([dc7e051](https://github.com/unhappychoice/splashboard/commit/dc7e051))

### 🐛 Bug Fixes

- fix(fetcher): address coderabbit review on cache key + recent count + today freshness ([2b2e655](https://github.com/unhappychoice/splashboard/commit/2b2e655))
- fix(fetcher,payload): scope deariary disk cache per token + lock Body::Error wire format ([761c1d1](https://github.com/unhappychoice/splashboard/commit/761c1d1))
- fix(render,fetcher): restore explicit shape-mismatch error per AGENTS contract ([dba8572](https://github.com/unhappychoice/splashboard/commit/dba8572))
- fix(fetcher,render): address coderabbit review on deariary PR ([451a53c](https://github.com/unhappychoice/splashboard/commit/451a53c))
- fix(fetcher): self-review nits on deariary_* family ([75c1668](https://github.com/unhappychoice/splashboard/commit/75c1668))
- fix(render): grid_table sizes key column to content and right-aligns values ([fb7ce98](https://github.com/unhappychoice/splashboard/commit/fb7ce98))
- fix(render): list_ranking stretches label and truncates to keep value visible ([5c33a5a](https://github.com/unhappychoice/splashboard/commit/5c33a5a))
- fix(docs): render LinkedTextBlock previews as real anchors ([685057f](https://github.com/unhappychoice/splashboard/commit/685057f))
- fix(fetcher): address coderabbit review on shape-coverage PR ([bbfdcf8](https://github.com/unhappychoice/splashboard/commit/bbfdcf8))
- fix(fetcher): collapse newlines in Text shape to honour single-string contract ([41c1221](https://github.com/unhappychoice/splashboard/commit/41c1221))
- fix(render): honour TextBlock line count in text_plain natural_height ([0016d0e](https://github.com/unhappychoice/splashboard/commit/0016d0e))
- fix(fetcher): dedupe quote_of_day and fortune entries; assert no duplicates ([f94c937](https://github.com/unhappychoice/splashboard/commit/f94c937))
- fix(fetcher): normalise CRLF in fortune / quote_of_day data parsers ([9b2c3dd](https://github.com/unhappychoice/splashboard/commit/9b2c3dd))
- fix(fetcher): prefer Atom rel="alternate" over self for article URL ([cf33ee8](https://github.com/unhappychoice/splashboard/commit/cf33ee8))
- fix(runtime): make trust/error placeholders shape-aware ([85f33cd](https://github.com/unhappychoice/splashboard/commit/85f33cd))
- fix(render): rename FIGfont to FIGlet for figlet-rs 1.0 ([5c76566](https://github.com/unhappychoice/splashboard/commit/5c76566))
- fix(render): use sort_by_key + Reverse to satisfy clippy ([8fda1cd](https://github.com/unhappychoice/splashboard/commit/8fda1cd))
- fix(runtime): surface unknown fetcher names as in-band placeholders ([7a6fdd8](https://github.com/unhappychoice/splashboard/commit/7a6fdd8))
- fix(render): blit grid_calendar through origin-anchored buffer ([dd0cbbb](https://github.com/unhappychoice/splashboard/commit/dd0cbbb))
- fix(fetcher): mix widget options into project_todo_in_code cache key ([7805165](https://github.com/unhappychoice/splashboard/commit/7805165))
- fix(runtime): exit wait loop once loading spinners clear ([5c1222f](https://github.com/unhappychoice/splashboard/commit/5c1222f))
- fix(templates): project_minimal renders 3 commits as 3 rows ([0e1fa89](https://github.com/unhappychoice/splashboard/commit/0e1fa89))
- fix(github): auto-detect login from token + size home_github avatar row ([8da2fbc](https://github.com/unhappychoice/splashboard/commit/8da2fbc))
- fix(templates): centre project_minimal commit block ([aac92c0](https://github.com/unhappychoice/splashboard/commit/aac92c0))
- fix(templates): make project_minimal actually offline ([8b00977](https://github.com/unhappychoice/splashboard/commit/8b00977))
- fix(config): respect $HOME in is_home_dir for cross-platform tests ([7d6267b](https://github.com/unhappychoice/splashboard/commit/7d6267b))
- fix(dogfood,docs): follow rename in .splashboard/dashboard.toml and guides ([6a11734](https://github.com/unhappychoice/splashboard/commit/6a11734))
- fix(templates): rename legacy fetcher references after the basic_* / system_* split ([3f313d6](https://github.com/unhappychoice/splashboard/commit/3f313d6))
- fix(xtask): pass the new loading map to layout::draw ([2412d3c](https://github.com/unhappychoice/splashboard/commit/2412d3c))
- fix(render,templates): wrap long figlet heroes + revert home_daily hero font ([ef5e8c7](https://github.com/unhappychoice/splashboard/commit/ef5e8c7))
- fix(templates): centre the calendar, keep the tables flush-left ([8026705](https://github.com/unhappychoice/splashboard/commit/8026705))
- fix(render,templates): align home_daily columns flush-left ([d91298e](https://github.com/unhappychoice/splashboard/commit/d91298e))
- fix(templates,render): tighten home_daily alignment + richer calendar ([ecdf7c8](https://github.com/unhappychoice/splashboard/commit/ecdf7c8))
- fix(docs): prefix landing hero action links with the site base ([96455f2](https://github.com/unhappychoice/splashboard/commit/96455f2))
- fix(runtime): wait for both daemon and animation; draw loading spinner ([f355ef6](https://github.com/unhappychoice/splashboard/commit/f355ef6))
- fix(github_avatar): pick extension from image magic bytes ([c98720c](https://github.com/unhappychoice/splashboard/commit/c98720c))
- fix(weather): request ms wind unit for metric to match displayed label ([dff17c4](https://github.com/unhappychoice/splashboard/commit/dff17c4))
- fix(render,fetcher): clippy + CodeRabbit review fixes ([5f09bce](https://github.com/unhappychoice/splashboard/commit/5f09bce))
- fix(runtime): derive shape via fetcher-order intersection ([52db806](https://github.com/unhappychoice/splashboard/commit/52db806))
- fix(render): use · for sparkline zero baseline so it reads distinctly from small bars ([95f75f6](https://github.com/unhappychoice/splashboard/commit/95f75f6))
- fix(render): draw tail window when sparkline data exceeds area width ([011867d](https://github.com/unhappychoice/splashboard/commit/011867d))
- fix(render): apply theme.text to widget chrome that was leaking terminal fg (#17) ([62628ee](https://github.com/unhappychoice/splashboard/commit/62628ee))
- fix(fetcher/github): satisfy stricter clippy on CI ([dc28c60](https://github.com/unhappychoice/splashboard/commit/dc28c60))
- fix(runtime): compute realtime fetchers once per splash invocation ([6b9824f](https://github.com/unhappychoice/splashboard/commit/6b9824f))
- fix(render): lighten heatmap palette to match GitHub light mode ([0524c5f](https://github.com/unhappychoice/splashboard/commit/0524c5f))
- fix(render): space heatmap cells with a blank spacer column ([0382740](https://github.com/unhappychoice/splashboard/commit/0382740))
- fix(config): height must cover total row length, not just be generous ([d058c45](https://github.com/unhappychoice/splashboard/commit/d058c45))
- fix(runtime): clamp viewport height to terminal size ([d3a791d](https://github.com/unhappychoice/splashboard/commit/d3a791d))
- fix(render): honour align in animated_typewriter and list renderers ([c4be608](https://github.com/unhappychoice/splashboard/commit/c4be608))
- fix(runtime): keep cursor hidden while moving it below the viewport ([6c69197](https://github.com/unhappychoice/splashboard/commit/6c69197))
- fix(runtime): use absolute coords when parking cursor below viewport ([d33a0b9](https://github.com/unhappychoice/splashboard/commit/d33a0b9))
- fix(runtime): park cursor at viewport bottom so shell prompt lands below ([aaf168d](https://github.com/unhappychoice/splashboard/commit/aaf168d))
- fix(runtime): separate load and render loop decisions ([9a6e8e4](https://github.com/unhappychoice/splashboard/commit/9a6e8e4))
- fix(render): figlet is an ascii_art style, not its own renderer ([dde21d0](https://github.com/unhappychoice/splashboard/commit/dde21d0))
- fix(runtime): force --wait behavior when cache is empty on first run ([aac755f](https://github.com/unhappychoice/splashboard/commit/aac755f))
- fix(trust): close TOCTOU, symlink bypass, non-atomic save, output injection ([1d0cfca](https://github.com/unhappychoice/splashboard/commit/1d0cfca))
- fix(cache): unique tmp filename to prevent concurrent-store clobber ([adcdf83](https://github.com/unhappychoice/splashboard/commit/adcdf83))
- fix(demo): use snapshot-appropriate data for one-shot splash context ([181c57a](https://github.com/unhappychoice/splashboard/commit/181c57a))

### 📝 Other Changes

- chore: bump version to v1.0.0 ([547179a](https://github.com/unhappychoice/splashboard/commit/547179a))
- docs(secrets): document $HOME/.splashboard/secrets.toml in user guides ([645022b](https://github.com/unhappychoice/splashboard/commit/645022b))
- refactor(payload,render): model placeholder errors as Body::Error ([530d143](https://github.com/unhappychoice/splashboard/commit/530d143))
- docs(templates): correct project_codebase TEMPLATES description ([db8e7e2](https://github.com/unhappychoice/splashboard/commit/db8e7e2))
- docs(presets): correct project_codebase widget table ([8a5462a](https://github.com/unhappychoice/splashboard/commit/8a5462a))
- docs(presets): list project_codebase in guides + xtask snapshots ([201153e](https://github.com/unhappychoice/splashboard/commit/201153e))
- refactor(fetcher): adopt tokei for code_* metrics; add code_comments ([5f63fb1](https://github.com/unhappychoice/splashboard/commit/5f63fb1))
- docs(agents,skill): codify single-shape renderer rule ([bc74d07](https://github.com/unhappychoice/splashboard/commit/bc74d07))
- refactor(render): narrow text_plain to Text shape only ([67fa9cd](https://github.com/unhappychoice/splashboard/commit/67fa9cd))
- refactor(templates): use list_plain for TextBlock-emitting widgets ([d873bd5](https://github.com/unhappychoice/splashboard/commit/d873bd5))
- refactor(render): switch list_plain to Paragraph-backed rendering ([c861c65](https://github.com/unhappychoice/splashboard/commit/c861c65))
- chore(deps)(deps): bump tui-piechart from 0.3.2 to 0.3.3 ([fd47e7d](https://github.com/unhappychoice/splashboard/commit/fd47e7d))
- chore: update flake.nix hashes for v0.4.0 ([b39c478](https://github.com/unhappychoice/splashboard/commit/b39c478))
- chore: bump version to v0.4.0 ([a14c913](https://github.com/unhappychoice/splashboard/commit/a14c913))
- refactor(reference): render fetcher/renderer meta as a table ([a71920c](https://github.com/unhappychoice/splashboard/commit/a71920c))
- refactor(templates): use height = "auto" for home_feed fortune footer ([0ac7f5a](https://github.com/unhappychoice/splashboard/commit/0ac7f5a))
- refactor(fetcher): rename fortune / quote_of_day to random_* family ([30d93fa](https://github.com/unhappychoice/splashboard/commit/30d93fa))
- test(fetcher): expand reddit unit coverage ([4357206](https://github.com/unhappychoice/splashboard/commit/4357206))
- refactor(fetcher): split reddit family into per-fetcher modules ([7e61e65](https://github.com/unhappychoice/splashboard/commit/7e61e65))
- refactor(fetcher): simplify reddit fetcher names ([ea5de76](https://github.com/unhappychoice/splashboard/commit/ea5de76))
- style(fetcher): apply rustfmt to reddit tests ([abababb](https://github.com/unhappychoice/splashboard/commit/abababb))
- test(fetcher): expand reddit unit coverage ([85e42d7](https://github.com/unhappychoice/splashboard/commit/85e42d7))
- style(fetcher): format reddit fetcher ([29cb209](https://github.com/unhappychoice/splashboard/commit/29cb209))
- style: cargo fmt ([7bcd0db](https://github.com/unhappychoice/splashboard/commit/7bcd0db))
- style(fetcher): format todoist tests ([4992aa7](https://github.com/unhappychoice/splashboard/commit/4992aa7))
- test: beef up coverage for LinkedTextBlock + hackernews fetchers ([15ec674](https://github.com/unhappychoice/splashboard/commit/15ec674))
- refactor(fetcher): move hackernews into family directory with shared client ([7941bce](https://github.com/unhappychoice/splashboard/commit/7941bce))
- refactor(fetcher): rename hn_top to hackernews_top ([2311316](https://github.com/unhappychoice/splashboard/commit/2311316))
- refactor(render): split RenderOptions into common + per-renderer specific structs ([3f84f4c](https://github.com/unhappychoice/splashboard/commit/3f84f4c))
- chore(deps): bump ratatui ecosystem to 0.30 ([0dbbeb6](https://github.com/unhappychoice/splashboard/commit/0dbbeb6))
- chore(deps)(deps): bump figlet-rs from 0.1.5 to 1.0.0 ([18ac8b2](https://github.com/unhappychoice/splashboard/commit/18ac8b2))
- chore(deps)(deps): bump toml from 0.8.23 to 1.1.2+spec-1.1.0 ([e3d6521](https://github.com/unhappychoice/splashboard/commit/e3d6521))
- chore(deps)(deps): bump dirs from 5.0.1 to 6.0.0 ([8ca48ad](https://github.com/unhappychoice/splashboard/commit/8ca48ad))
- chore(deps)(deps): bump sha2 from 0.10.9 to 0.11.0 ([5e45ec0](https://github.com/unhappychoice/splashboard/commit/5e45ec0))
- chore(ci)(deps): bump actions/configure-pages from 5 to 6 ([4971372](https://github.com/unhappychoice/splashboard/commit/4971372))
- chore(ci)(deps): bump actions/checkout from 4 to 6 ([438c56d](https://github.com/unhappychoice/splashboard/commit/438c56d))
- chore(ci)(deps): bump codecov/codecov-action from 4 to 6 ([9499f83](https://github.com/unhappychoice/splashboard/commit/9499f83))
- chore(ci)(deps): bump actions/upload-pages-artifact from 3 to 5 ([965e2c2](https://github.com/unhappychoice/splashboard/commit/965e2c2))
- chore(ci)(deps): bump softprops/action-gh-release from 2 to 3 ([156a21e](https://github.com/unhappychoice/splashboard/commit/156a21e))
- chore(ci)(deps): bump actions/deploy-pages from 4 to 5 ([4088389](https://github.com/unhappychoice/splashboard/commit/4088389))
- chore(ci)(deps): bump cachix/install-nix-action from 27 to 31 ([b53dff4](https://github.com/unhappychoice/splashboard/commit/b53dff4))
- chore(ci)(deps): bump actions/setup-node from 4 to 6 ([9e4fb6f](https://github.com/unhappychoice/splashboard/commit/9e4fb6f))
- chore(ci)(deps): bump mlugg/setup-zig from 1 to 2 ([8cf4ff3](https://github.com/unhappychoice/splashboard/commit/8cf4ff3))
- chore(ci): raise dependabot open-pr limits ([342acd9](https://github.com/unhappychoice/splashboard/commit/342acd9))
- chore(ci): add dependabot config and CODEOWNERS ([6819040](https://github.com/unhappychoice/splashboard/commit/6819040))
- chore(skill): tighten add-fetcher-renderer Phase 0 ranking criteria ([7332af3](https://github.com/unhappychoice/splashboard/commit/7332af3))
- chore(skill): document post-merge issue checkbox update ([0e5f8de](https://github.com/unhappychoice/splashboard/commit/0e5f8de))
- chore: update flake.nix hashes for v0.3.0 ([7e6d795](https://github.com/unhappychoice/splashboard/commit/7e6d795))
- chore: bump version to v0.3.0 ([baed209](https://github.com/unhappychoice/splashboard/commit/baed209))
- chore(skill): require Phase 0 candidate selection in add-fetcher-renderer ([7c6751c](https://github.com/unhappychoice/splashboard/commit/7c6751c))
- refactor(fetcher): rename project_todo_in_code to code_todos and exclude vendored dirs ([bdcf1d1](https://github.com/unhappychoice/splashboard/commit/bdcf1d1))
- refactor(project_todo_in_code): require trailing colon on markers ([352ba04](https://github.com/unhappychoice/splashboard/commit/352ba04))
- chore(skill): add Claude Code skill for fetcher / renderer implementation ([8f43457](https://github.com/unhappychoice/splashboard/commit/8f43457))
- docs(readme): center hero image + badges, drop redundant title text ([c11c1d3](https://github.com/unhappychoice/splashboard/commit/c11c1d3))
- Update README.md ([b9717db](https://github.com/unhappychoice/splashboard/commit/b9717db))
- Reorganize installation instructions in README ([cb0e880](https://github.com/unhappychoice/splashboard/commit/cb0e880))
- Update README with installation command ([b8f4a51](https://github.com/unhappychoice/splashboard/commit/b8f4a51))
- docs: mirror README install restructure on docs-site ([f02d902](https://github.com/unhappychoice/splashboard/commit/f02d902))
- docs(readme): promote install.sh as primary, fold the rest into details ([2a0b94f](https://github.com/unhappychoice/splashboard/commit/2a0b94f))
- ops: add install.sh for curl-pipe-bash install ([9f4fac5](https://github.com/unhappychoice/splashboard/commit/9f4fac5))
- docs(site): move docs to splashboard.unhappychoice.com ([852d12e](https://github.com/unhappychoice/splashboard/commit/852d12e))
- chore: update flake.nix hashes for v0.2.0 ([7041339](https://github.com/unhappychoice/splashboard/commit/7041339))
- chore: bump version to v0.2.0 ([fb6a15e](https://github.com/unhappychoice/splashboard/commit/fb6a15e))
- ci(release): build Linux binaries with cargo-zigbuild against glibc 2.17 ([52eb2a9](https://github.com/unhappychoice/splashboard/commit/52eb2a9))
- ops: add release automation (cargo-release / GH Releases / crates.io / brew tap / Nix) ([8989900](https://github.com/unhappychoice/splashboard/commit/8989900))
- docs(readme): add project_github hero screenshot at the top ([2c35306](https://github.com/unhappychoice/splashboard/commit/2c35306))
- docs(readme): keep shell-wiring instructions in the README ([bf4f9e8](https://github.com/unhappychoice/splashboard/commit/bf4f9e8))
- docs(readme): slim README down to install + docs-site pointer ([7aee01f](https://github.com/unhappychoice/splashboard/commit/7aee01f))
- docs: write the eval line via `echo '...' >> rc` ([af4954e](https://github.com/unhappychoice/splashboard/commit/af4954e))
- docs: keep the `splashboard init <shell> >> rc` option alongside eval ([097043d](https://github.com/unhappychoice/splashboard/commit/097043d))
- docs: recommend eval "$(splashboard init <shell>)" in manual rc setup ([433c269](https://github.com/unhappychoice/splashboard/commit/433c269))
- chore: drop the dogfood .splashboard/dashboard.toml ([55ac771](https://github.com/unhappychoice/splashboard/commit/55ac771))
- refactor(templates): rename project_github_activity to project_github ([838d4bc](https://github.com/unhappychoice/splashboard/commit/838d4bc))
- docs(fetcher): freshen stale 'placeholder' wording after #95 runtime lift ([01692c7](https://github.com/unhappychoice/splashboard/commit/01692c7))
- docs(guides): note the new animation primitives in concepts + presets ([e9e0de3](https://github.com/unhappychoice/splashboard/commit/e9e0de3))
- chore(deps): bump gix to 0.82 so lockless resolves stay consistent ([2dcd511](https://github.com/unhappychoice/splashboard/commit/2dcd511))
- refactor(install): address CodeRabbit review feedback ([294b2a2](https://github.com/unhappychoice/splashboard/commit/294b2a2))
- docs: drop tracker links and pending-work notes from standalone pages ([6cb5c83](https://github.com/unhappychoice/splashboard/commit/6cb5c83))
- docs(read-store): lift ReadStore onto its own page and call out the bare-data format ([e549336](https://github.com/unhappychoice/splashboard/commit/e549336))
- docs(concepts): split into Widget / Shape / Fetcher / Renderer deep dives ([7170ca0](https://github.com/unhappychoice/splashboard/commit/7170ca0))
- docs(presets): render all four presets live + align preset guide + tighten landing ([c3761ac](https://github.com/unhappychoice/splashboard/commit/c3761ac))
- refactor(fetcher): rename project_name/project → git_repo_name/github_repo ([35e2b81](https://github.com/unhappychoice/splashboard/commit/35e2b81))
- style(templates): use standard figlet font for home_splash clock ([a5e26ba](https://github.com/unhappychoice/splashboard/commit/a5e26ba))
- docs(site): pin Starlight palette to the Splash default theme ([b914952](https://github.com/unhappychoice/splashboard/commit/b914952))
- docs(site): swap OG title font to Orbitron 700 ([a596385](https://github.com/unhappychoice/splashboard/commit/a596385))
- refactor(render,templates): wrap only when the cell has headroom ([06a31f2](https://github.com/unhappychoice/splashboard/commit/06a31f2))
- docs(site): render OG card text as paths so JetBrains Mono comes through ([5860568](https://github.com/unhappychoice/splashboard/commit/5860568))
- refactor(templates): drop lat/lon-dependent widgets from default presets ([2563168](https://github.com/unhappychoice/splashboard/commit/2563168))
- docs(site): add Splash-palette favicon + OG card for social share previews ([be41ba9](https://github.com/unhappychoice/splashboard/commit/be41ba9))
- docs(site): embed real project_github_activity render on the presets page ([2198c28](https://github.com/unhappychoice/splashboard/commit/2198c28))
- refactor(templates): unify body content to a 70-col centred band ([5d37ac1](https://github.com/unhappychoice/splashboard/commit/5d37ac1))
- refactor(templates): align project_github_activity with polished dogfood layout ([930b78f](https://github.com/unhappychoice/splashboard/commit/930b78f))
- docs(site): centre the landing dashboard preview in its column ([798830c](https://github.com/unhappychoice/splashboard/commit/798830c))
- docs(site): scale landing preview like an image via container queries ([2bbb6fa](https://github.com/unhappychoice/splashboard/commit/2bbb6fa))
- docs(site): shrink the landing dashboard preview so it fits without horizontal scroll ([d2ad7c4](https://github.com/unhappychoice/splashboard/commit/d2ad7c4))
- docs(site): render dogfood dashboard from config into the landing page ([10cc92c](https://github.com/unhappychoice/splashboard/commit/10cc92c))
- docs(site): rebuild landing as splash template with hero + card grids ([0fcb2a5](https://github.com/unhappychoice/splashboard/commit/0fcb2a5))
- docs(site): dress snapshot previews in terminal-window chrome ([5475533](https://github.com/unhappychoice/splashboard/commit/5475533))
- docs(site): paint snapshot bg with the Splash default theme ([d72c3ef](https://github.com/unhappychoice/splashboard/commit/d72c3ef))
- docs(xtask): skip animated renderers in fetcher preview snapshots ([2e2aee6](https://github.com/unhappychoice/splashboard/commit/2e2aee6))
- refactor(fetcher,xtask): family-prefix every fetcher name + always group pages by family ([da3c0b7](https://github.com/unhappychoice/splashboard/commit/da3c0b7))
- docs(site): add empty Showcases page as sidebar top-level entry ([2fad054](https://github.com/unhappychoice/splashboard/commit/2fad054))
- docs(site): add ASCII diagrams to Concepts and Configuration ([22b3302](https://github.com/unhappychoice/splashboard/commit/22b3302))
- docs(site): add Concepts guide explaining the Widget = Fetcher + Renderer model ([b8acd14](https://github.com/unhappychoice/splashboard/commit/b8acd14))
- docs(site): disable markdown smartypants ([294d6fe](https://github.com/unhappychoice/splashboard/commit/294d6fe))
- docs(site): expose LLM-friendly outputs (llms.txt family + per-page raw .md) ([e310288](https://github.com/unhappychoice/splashboard/commit/e310288))
- docs(xtask): group fetcher/renderer reference pages by family prefix ([ab371c9](https://github.com/unhappychoice/splashboard/commit/ab371c9))
- docs(site): add Guides section (Getting started / Configuration / Presets / Themes / Trust / Cookbook) ([f407e5d](https://github.com/unhappychoice/splashboard/commit/f407e5d))
- chore(licenses): cover Rust crate deps in THIRDPARTY-LICENSES.md via cargo-about ([6226552](https://github.com/unhappychoice/splashboard/commit/6226552))
- chore(docs): move figlet attribution to root THIRDPARTY-LICENSES.md ([7a12f44](https://github.com/unhappychoice/splashboard/commit/7a12f44))
- chore(docs): rename figlet NOTICE.md to README.md ([621b46a](https://github.com/unhappychoice/splashboard/commit/621b46a))
- chore(config): dogfood dashboard in project_github_activity style ([f2560d5](https://github.com/unhappychoice/splashboard/commit/f2560d5))
- chore(ci): fold coverage into the test matrix instead of a separate job ([ea35021](https://github.com/unhappychoice/splashboard/commit/ea35021))
- chore(ci): drop ubuntu-latest from test matrix — coverage job covers it ([caf6d67](https://github.com/unhappychoice/splashboard/commit/caf6d67))
- chore(ci): measure coverage with cargo-llvm-cov and upload to Codecov ([5bbb0a2](https://github.com/unhappychoice/splashboard/commit/5bbb0a2))
- refactor(config): split settings.toml + dashboard.toml, resolve by CWD context ([7c75e69](https://github.com/unhappychoice/splashboard/commit/7c75e69))
- chore(config): tighten dogfood layout — flashier hero, explicit widths, baseline-friendly sparkline rows ([fbf9324](https://github.com/unhappychoice/splashboard/commit/fbf9324))
- chore(config): reshape dogfood as project_github_activity demo ([ebe1727](https://github.com/unhappychoice/splashboard/commit/ebe1727))
- docs(agents): note cargo fmt in the pre-PR checklist ([b639830](https://github.com/unhappychoice/splashboard/commit/b639830))
- chore(config): showcase animated_postfx effects in dogfood config ([e7fc33d](https://github.com/unhappychoice/splashboard/commit/e7fc33d))
- docs(agents): expand catalog index with fetcher sub-issues #62–#68 ([2bd89e0](https://github.com/unhappychoice/splashboard/commit/2bd89e0))
- refactor(theme): drop the "splash" alias, alphabetize preset lists (#17) ([2db24fc](https://github.com/unhappychoice/splashboard/commit/2db24fc))
- refactor(theme): apply family prefixes to every colour key (#17) ([16c7eb0](https://github.com/unhappychoice/splashboard/commit/16c7eb0))
- config(dogfood): showcase Splash default with padding + subtle hero band (#17) ([4505655](https://github.com/unhappychoice/splashboard/commit/4505655))
- chore(deps): enable ratatui serde feature (#17) ([171a5f7](https://github.com/unhappychoice/splashboard/commit/171a5f7))
- docs: refresh README and sync AGENTS renderer/shape names ([dc6f375](https://github.com/unhappychoice/splashboard/commit/dc6f375))
- style: cargo fmt after renderer prefix rename ([60c97d5](https://github.com/unhappychoice/splashboard/commit/60c97d5))
- refactor(render): prefix stand-alone renderers with their family (#61) ([36739a5](https://github.com/unhappychoice/splashboard/commit/36739a5))
- refactor(render): prefix renderer names per family (#61) ([c347431](https://github.com/unhappychoice/splashboard/commit/c347431))
- style: cargo fmt after Text/TextBlock rename ([c5ec894](https://github.com/unhappychoice/splashboard/commit/c5ec894))
- refactor(core): split Lines shape into Text and TextBlock ([a87c3d0](https://github.com/unhappychoice/splashboard/commit/a87c3d0))
- chore(dogfood): drop the (草) annotation from the contributions title ([c67ac0c](https://github.com/unhappychoice/splashboard/commit/c67ac0c))
- chore(dogfood): rewire .splashboard/config.toml around github_* ([4db7d17](https://github.com/unhappychoice/splashboard/commit/4db7d17))
- refactor: drop fetcher stubs and empty the baked default config ([4e8f5cd](https://github.com/unhappychoice/splashboard/commit/4e8f5cd))
- refactor(fetcher/github): classify repo-scope fetchers as Safe ([0cf9768](https://github.com/unhappychoice/splashboard/commit/0cf9768))
- style(fetcher/github): apply cargo fmt ([78778dd](https://github.com/unhappychoice/splashboard/commit/78778dd))
- refactor(fetcher): rename sysinfo fetchers to prefix_suffix convention ([fdfa2d0](https://github.com/unhappychoice/splashboard/commit/fdfa2d0))
- style: cargo fmt --all ([92d9723](https://github.com/unhappychoice/splashboard/commit/92d9723))
- style: cargo fmt --all ([a659ad8](https://github.com/unhappychoice/splashboard/commit/a659ad8))
- chore(dogfood): wire system fetchers into .splashboard config ([5a4c75d](https://github.com/unhappychoice/splashboard/commit/5a4c75d))
- chore(dogfood): bump pie row to h=12 so the legend actually shows ([0a8e2da](https://github.com/unhappychoice/splashboard/commit/0a8e2da))
- chore(dogfood): drop the figlet clock ([e929501](https://github.com/unhappychoice/splashboard/commit/e929501))
- chore(dogfood): move sparkline into disk row, give bar + pie its own row ([e781c19](https://github.com/unhappychoice/splashboard/commit/e781c19))
- chore(dogfood): render github_prs as pie_chart alongside bar_chart ([2d599c0](https://github.com/unhappychoice/splashboard/commit/2d599c0))
- style: cargo fmt --all ([c05fe5d](https://github.com/unhappychoice/splashboard/commit/c05fe5d))
- chore(dogfood): add git_recent_commits timeline stub ([f84ee1e](https://github.com/unhappychoice/splashboard/commit/f84ee1e))
- docs: add AGENTS.md (+ CLAUDE.md passthrough) ([6b57025](https://github.com/unhappychoice/splashboard/commit/6b57025))
- chore(dogfood): swap ReadStore demo to simpler text/lines widget ([fe6c7f0](https://github.com/unhappychoice/splashboard/commit/fe6c7f0))
- chore(dogfood): add margin below heatmap row ([5b98509](https://github.com/unhappychoice/splashboard/commit/5b98509))
- chore(dogfood): move heatmap under notes, drop border ([ed73040](https://github.com/unhappychoice/splashboard/commit/ed73040))
- chore(dogfood): slot heatmap into repo's own splashboard config ([d140a5c](https://github.com/unhappychoice/splashboard/commit/d140a5c))
- refactor(runtime): park cursor only on the final draw ([bc87f6d](https://github.com/unhappychoice/splashboard/commit/bc87f6d))
- refactor(render): rename bignum_tui -> ascii_art, list -> table ([2e390fe](https://github.com/unhappychoice/splashboard/commit/2e390fe))
- refactor(render): data-shape Body + Renderer registry (3-axis) (#32) ([b9cbd57](https://github.com/unhappychoice/splashboard/commit/b9cbd57))
- refactor(fetcher): split modules; guard clock against format-spec panic ([834f84b](https://github.com/unhappychoice/splashboard/commit/834f84b))
- test(daemon): drop flaky spawn probe, verify builder chain instead ([51ddc29](https://github.com/unhappychoice/splashboard/commit/51ddc29))
- refactor: move title / border from Payload + renderer into Layout::Panel ([b82aca7](https://github.com/unhappychoice/splashboard/commit/b82aca7))
- ci: add GitHub Actions workflow (format / clippy / test matrix) ([13ff6d0](https://github.com/unhappychoice/splashboard/commit/13ff6d0))
- refactor(payload): split Chart into LineChart + BarChart, gauge f32→f64 ([064d941](https://github.com/unhappychoice/splashboard/commit/064d941))
- docs: add initial README with concept and design sketch ([39c7f3c](https://github.com/unhappychoice/splashboard/commit/39c7f3c))


