feat: surface data freshness + env typo linting on the dashboard (FIX-09)#22
Conversation
Review verdict — 2026-07-09: READY TO MERGE (verified locally; CI billing-blocked)Adversarial review + merge-readiness work pushed to this branch (2 commits, no force-push):
Review findings (otherwise clean): freshness stamp rendered as ISO-8601 UTC with an accessible caption/scope table; staleness banner is Merge-order notes for whoever merges:
Local gate evidence (CI billing-blocked — local run is the review gate): 🤖 Generated with Claude Code |
…-09) Implements the standalone, FIX-08-independent slice of FIX-09: the dashboard was persisting Store.refreshed_at() but never rendering it, so staleness and unconfigured/misspelled STACKS_* env vars were invisible. - app/render.py: new `_data_status_section` renders an accessible "Data status" <table> (caption + scoped th) as the first thing in <main>, showing the refresh stamp as ISO-8601 UTC, "never refreshed — run `stacks refresh`" when absent, and a text `<p role="status">` staleness banner (never colour-only) when the data is old. - app/view.py: `DashboardView` gains `refreshed_at`/`stale`; `build_view` computes staleness against a new `STALE_AFTER_SECONDS` (7 days) module constant, with an overridable `now` for testability; `view_from_store` reads `store.refreshed_at()` and threads it through; `render_view` passes both into `render_dashboard`. - ingest/config.py: export `KNOWN_STACKS_ENV`, the single source of truth for recognized STACKS_* variables. - ingest/refresh.py: `doctor()` gains an `env` param (defaults to os.environ) and now flags any STACKS_* variable not in `KNOWN_STACKS_ENV` as a failing Check — catches typos like STACKS_CALIBER_DB that were previously silently ignored. Per-source RefreshResult rows (calibre/koreader/kosync) stay out of scope pending FIX-08, per the roadmap doc's own note that the stamp + env linting are "standalone and cheap." Roadmap doc updated with a Status note under FIX-09. Validated: `pytest` (202 passed, 96.56% coverage, gate is 85%), `ruff format --check` + `ruff check` clean, `mypy --strict` clean, `make a11y` 0 violations. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review finding on FIX-09: KNOWN_STACKS_ENV is a hand-maintained allowlist, so the moment a new STACKS_* variable ships (e.g. PR #7's STACKS_HIDE_SENSITIVE), 'stacks doctor' would false-flag the legitimate variable as a typo — the exact failure mode the allowlist exists to prevent. New test scans the quoted STACKS_* literals in app/ingest/ recommender source and asserts set-equality with KNOWN_STACKS_ENV, so the drift becomes a red test instead of a silent lie. Artifacts regenerated. make verify green: 204 tests @ 96.67% cov, pa11y 0, eval green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
5971c3d to
97ba62c
Compare
|
Attempted to process this PR in the auto-merge queue: rebased cleanly onto
This is a GitHub Actions billing/spending-limit block at the account level, not an issue with this PR's code. No code review or merge was performed since CI cannot execute. Please resolve the billing issue in GitHub Settings > Billing & plans, then re-run checks. |
# Conflicts: # app/view.py # docs/audits/dashboard.html # docs/ideation/02-large-scale-fixes.md # tests/test_render_view.py
Implements the standalone, FIX-08-independent slice of FIX-09: the
dashboard was persisting Store.refreshed_at() but never rendering it, so
staleness and unconfigured/misspelled STACKS_* env vars were invisible.
_data_status_sectionrenders an accessible "Datastatus" (caption + scoped th) as the first thing in ,
showing the refresh stamp as ISO-8601 UTC, "never refreshed — run
stacks refresh" when absent, and a text<p role="status">stalenessbanner (never colour-only) when the data is old.
DashboardViewgainsrefreshed_at/stale;build_viewcomputes staleness against a new
STALE_AFTER_SECONDS(7 days) moduleconstant, with an overridable
nowfor testability;view_from_storereads
store.refreshed_at()and threads it through;render_viewpassesboth into
render_dashboard.KNOWN_STACKS_ENV, the single source of truthfor recognized STACKS_* variables.
doctor()gains anenvparam (defaults toos.environ) and now flags any STACKS_* variable not in
KNOWN_STACKS_ENVas a failing Check — catches typos likeSTACKS_CALIBER_DB that were previously silently ignored.
Per-source RefreshResult rows (calibre/koreader/kosync) stay out of scope
pending FIX-08, per the roadmap doc's own note that the stamp + env
linting are "standalone and cheap." Roadmap doc updated with a Status note
under FIX-09.
Validated:
pytest(202 passed, 96.56% coverage, gate is 85%),ruff format --check+ruff checkclean,mypy --strictclean,make a11y0 violations.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
Backfill PR for a completed roadmap item (
roadmap/fix-09-degradation-and-freshness-made-le, 1 commit(s) overmain). Part of the portfolio roadmap batch.