docs: record the stale-news / clientRank fix as a key decision
Some checks failed
CI / Build · Debug (push) Has been cancelled
CI / Build · Release (push) Has been cancelled

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Kutesir
2026-07-13 03:17:22 +03:00
parent 326d5fe983
commit bb067df482

View File

@@ -120,6 +120,18 @@ API/contract.md — REST + WebSocket API spec
- Pagination: cursor-based via `nextCursor`. - Pagination: cursor-based via `nextCursor`.
- `StoryStore.setPill()` resets `lastSyncedAt` to bypass the 30s rate-limit on filter switch. - `StoryStore.setPill()` resets `lastSyncedAt` to bypass the 30s rate-limit on filter switch.
- `sectionSupplement` fetches populate sparse regional sections in the All digest independently. - `sectionSupplement` fetches populate sparse regional sections in the All digest independently.
- **Age must be read from `firstSeenAt`, never `updatedAt`.** The backend bumps `updatedAt`
every time it attaches another article to a cluster, however loosely related a story
can read "1 hr ago" while being weeks old (see `docs/BACKLOG.md` #15). `firstSeenAt` is
the honest age and is already decoded on `StorySummary`.
- **Stale-news control (client-side, `Views/Shared/Theme.swift`):** `clientRank` applies a
soft time-decay to `signalScore` so fresh stories outrank stale high-scorers in
`feedOrder` it computes age from `firstSeenAt`, not `updatedAt` (was silently broken
by the same bug above until fixed). `StorySummary.isFossil` (`firstSeenAt` > 5 days) is a
hard backstop on top of that: `SignalFeedView.mainStories` and `.makeDigest()` sink
fossils below current stories so one can never take the hero/lead slot, regardless of
score. Fossils still appear in the feed — just not in the most prominent position. This
is a display/ordering patch; the server's own ranking is still wrong at the source.
--- ---