Skip to content

feat: surface data freshness + env typo linting on the dashboard (FIX-09)#22

Merged
ChelseaKR merged 3 commits into
mainfrom
roadmap/fix-09-degradation-and-freshness-made-le
Jul 12, 2026
Merged

feat: surface data freshness + env typo linting on the dashboard (FIX-09)#22
ChelseaKR merged 3 commits into
mainfrom
roadmap/fix-09-degradation-and-freshness-made-le

Conversation

@ChelseaKR

Copy link
Copy Markdown
Owner

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" (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"> 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


    Backfill PR for a completed roadmap item (roadmap/fix-09-degradation-and-freshness-made-le, 1 commit(s) over main). Part of the portfolio roadmap batch.

@ChelseaKR

Copy link
Copy Markdown
Owner Author

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):

  1. 2501e19 — merged current main (clean auto-merge).
  2. 5971c3d — review finding turned into a gate: KNOWN_STACKS_ENV is hand-maintained, so the moment a new STACKS_* variable ships (concretely: PR Research panel + roadmap; implement top items #7 adds STACKS_HIDE_SENSITIVE), stacks doctor would false-flag the legitimate variable as a typo. Added test_known_stacks_env_covers_every_var_the_code_reads — scans quoted STACKS_* literals in app/ingest/recommender source and asserts set-equality with the allowlist, so that drift is now a red test, not a silent lie. Artifacts (coverage.xml) regenerated, never text-merged.

Review findings (otherwise clean): freshness stamp rendered as ISO-8601 UTC with an accessible caption/scope table; staleness banner is role="status" text, never colour-only; "never refreshed" correctly distinct from "stale"; doctor() stays mutation-free (existing hash-guard test still covers it); now injection keeps staleness testable without patching.

Merge-order notes for whoever merges:

Local gate evidence (CI billing-blocked — local run is the review gate): make verify green end-to-end — ruff + marker-hygiene, mypy --strict, 204 tests @ 96.67% branch coverage, pip-audit + gitleaks + osv-scanner clean, static a11y + pa11y/axe 0 violations, offline eval green.

🤖 Generated with Claude Code

ChelseaKR and others added 2 commits July 9, 2026 19:22
…-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>
@ChelseaKR
ChelseaKR force-pushed the roadmap/fix-09-degradation-and-freshness-made-le branch from 5971c3d to 97ba62c Compare July 10, 2026 02:22
@ChelseaKR

Copy link
Copy Markdown
Owner Author

Attempted to process this PR in the auto-merge queue: rebased cleanly onto main and pushed (no conflicts), but CI cannot run — both standards and verify checks fail immediately with:

The job was not started because recent account payments have failed or your spending limit needs to be increased. Please check the 'Billing & plans' section in your settings

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
@ChelseaKR
ChelseaKR merged commit 48fa5a9 into main Jul 12, 2026
5 checks passed
@ChelseaKR
ChelseaKR deleted the roadmap/fix-09-degradation-and-freshness-made-le branch July 12, 2026 06:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant