Files
jarvis/docs/BACKLOG.md
Kutesir fcd4e2cce5
All checks were successful
CI / Build · Debug (push) Successful in 24s
CI / Build · Release (push) Successful in 30s
docs: log freshness-decay bug — old stories never leave the top of the feed
Live-verified against the backend API: 13/20 top stories are 5+ days old
by firstSeenAt but still score 90+. Freshness decays from lastUpdatedAt
(cluster last touched) instead of the actual news event age, and it
compounds with the known over-clustering bug (#2) — tangential articles
keep attaching to old clusters, resetting their clock indefinitely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-10 03:17:25 +03:00

5.4 KiB
Raw Blame History

Backlog & status

Source-of-truth tracker. The Gitea issue tracker is currently empty (0 issues) — run scripts/create-issues.sh with a token to populate it. [client] = iOS, [backend] = the platform service on the Docker host, [ci] = build/test.

Status: 🔴 open · 🟡 mitigated client-side (real fix still pending) · 🟢 done.

Backend — data quality (highest priority)

  1. 🟡 [backend] F1 mis-classified into tech/finance/politics. No sport category, so F1 (100% F1 sources) scatters across topics: "Monaco Grand Prix…" → tech, "F1 reports 35% CO2…" → finance, "McLaren launch appeal…" → politics. Add a sport/f1 topic and route motorsport sources there. Client mitigation shipped: F1 pill matches clear F1 headlines + a majority of F1 sources, and F1 is excluded from All/Tech/Finance. Backend still mis-tags.
  2. 🔴 [backend] Catastrophic over-clustering — unrelated articles merged on a single shared word. Newly confirmed on-device: a story merged a Russian-film-director article + "Who's afraid of Michael Jackson?" + "Chelsea Jackson Roberts" (wellness) — grouped on the surname Jackson. Another merged "Gunfire at Niger airport" + "L.A. County Whiteman Airport crash" + "Niger fintech". Result: wrong headline, summary, topic, and inflated signal. Raise the TF-IDF threshold hard (~0.22 → 0.450.55) and require multiple shared distinctive terms / named-entity overlap, with a tight time window. If still over-merging, move to sentence embeddings (all-MiniLM-L6-v2, cosine ≥ ~0.6). Make canonical headline + summary come from the same representative article. No client fix is possible — the story object itself is wrong.
  3. 🔴 [backend] Add accurate per-story tags (topic + region). So the client can read tags (sport, uganda, south-africa, …) instead of keyword-guessing. Unblocks #6.
  4. 🔴 [backend] Topic-classifier coverage for the 47 feeds. science/world/tech mapping.
  5. 🔴 [backend] Freshness score decays from lastUpdatedAt (cluster last touched), not from the actual news event age — old stories never leave the top of the feed. Confirmed live on /api/v1/stories: 13 of the top 20 stories are 5+ days old by firstSeenAt but still score 90+; the #1 story (story_511c67eb064d) has firstSeenAt: 2026-06-17, lastUpdatedAt: 2026-07-09 (21 days later), freshnessScore: 1.0, signal 100. Compounds with #2 (over-clustering): a loose cluster keeps absorbing tangential articles indefinitely (this story's timeline includes "Security forces ready for June 30 marches: Ramaphosa" — unrelated to the football story it's attached to), each attachment resets lastUpdatedAt to now, so the cluster's clock never runs out and its canonical headline drifts to whatever was clustered last (list view showed "South Africa stun South Korea…"; story detail showed "Updated FIFA rankings after Bafana Bafana exit" for the same story_id). Fix: decay freshness from firstSeenAt (or the newest article whose relevance to the cluster core is verified), not from "last touched." Tightening the TF-IDF threshold in #2 should also reduce how often unrelated articles keep a stale cluster's clock alive. No client fix possible — the story object's freshness field itself is wrong before it reaches the app.

Backend — features

  1. 🔴 [backend] Server-side push for breaking alerts (APNs or ntfy). For breaking-story notifications while the app is closed. Client does local notifications + background refresh only.

Client

  1. 🔴 [client] Move interest filters server-side once tags (#3) exist. Today's pills are client-side keyword/headline matches on loaded stories. Refined since: regions match headline-only (no polluted summaries/outlets), regions exclusive, F1 by source majority, East Africa removed.
  2. 🔴 [client] SSID-based trusted networks. Needs Access WiFi Information entitlement (device + paid account). Approximated by LAN reachability today.
  3. 🔴 [client] Optional in-app WireGuard tunnel. NetworkExtension; entitlement + device. Deferred.
  4. 🔴 [client] App icon + launch assets. AppIcon is an empty placeholder.
  5. 🔴 [client] Flesh out Latest / Search tabs. Saved is now bookmarks; Latest/Search still minimal.
  6. 🔴 [client] Verify hero image loading. AsyncImage vs real feed imageUrls.
  7. 🔴 [client] Offline-first polish. Pre-cache top stories.

CI

  1. 🔴 [ci] Add unit/UI tests + a test matrix leg. Build matrix compiles, runs no tests.
  2. 🔴 [ci] Backend CI build matrix. Python 3.113.13 + lint + Docker build/health probe.

🟢 Shipped

Signal feed + detail + reader + feed manager · LAN⇄Tailscale connectivity · notifications (morning/evening briefings + breaking alerts) with Open-Meteo weather · device code signing · feed resilience (no blank-on-refresh, ignore cancelled, coalesced WS refresh) · clearer empty states (polling / unreachable+host / offline / caught-up) · deterministic feed order · 6-line summary preview · pinned filters (F1 split out, regions exclusive & headline-matched, Finance/Tech by topic) · swipe actions (short→Save / long→Mark read, right→Share) · read/seen handling (seen-tracking with per-load snapshot, read stories collapse into a "Read" shelf with compact rows, "all caught up" state).