Commit graph

8 commits

Author SHA1 Message Date
Austin Schaefer
73c80491be Turn RankedArticleRow into a struct instead of a 7-field tuple
All checks were successful
CI / check (pull_request) Successful in 1m34s
CI / test (pull_request) Successful in 3m19s
CI / audit (pull_request) Successful in 12s
Tuples this large stop being readable at the call site (positional
indices like rows[0].6 give no hint what they mean); a named struct
documents each field and lets rustc catch reordering mistakes.
2026-09-03 21:20:41 +02:00
Austin Schaefer
33d2dfe011 Merge list_feeds_with_titles into list_feeds
All checks were successful
CI / check (pull_request) Successful in 5m2s
CI / test (pull_request) Successful in 3m18s
CI / audit (pull_request) Successful in 15s
Both queried the same table with near-identical loads, differing only
by an extra title column and ordering. Fold title into list_feeds'
tuple (its one prior caller, the polling job, ignores it) so there's
a single feed-listing query instead of two that can drift apart.
2026-09-03 19:49:39 +02:00
Austin Schaefer
6a2bf8c9a8 Add feed sidebar navigation, built from Dioxus's component library
Default view stays the all-feeds joined article list, now with a sidebar
listing every subscribed feed so a reader can pin down to one feed's
articles. Filtering happens server-side (list_ranked_articles now takes
an optional feed_id).

Pulled in the sidebar/badge/scroll_area (plus their sheet/skeleton/
tooltip/separator dependencies) components via `dx components add`
instead of hand-rolling nav/tag/scroll markup, matching this project's
existing pattern of using the Dioxus component library over raw
elements (see button/input).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqTJmazHBQK878vjQ4JnnF
2026-09-03 16:28:22 +02:00
Austin Schaefer
6fb470084d Poll subscribed feeds for new articles on a schedule
All checks were successful
CI / check (pull_request) Successful in 13m50s
CI / test (pull_request) Successful in 4m15s
CI / audit (pull_request) Successful in 15s
Feeds were already persisted, but nothing ever re-fetched them after
the initial subscribe — scoring.rs had a TODO where feed polling was
supposed to go. Add a feed_polling job that re-fetches every
subscribed feed, relies on articles.url's unique constraint to skip
ones already seen, and stamps last_fetched_at. Runs once on startup
(so reopening the app catches up immediately) and every 15 minutes
after, ahead of the scoring pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QmwX8eafbMstJvt8XPSqft
2026-09-03 13:20:30 +02:00
Austin Schaefer
44b9724645 Split web crate into layered modules (api/services/jobs/view)
All checks were successful
CI / check (pull_request) Successful in 8m13s
CI / test (pull_request) Successful in 2m36s
CI / audit (pull_request) Successful in 11s
Separates controllers (api/, the #[server] endpoints) from business
services (server/services/), background scheduling (server/jobs/,
renamed from pipeline.rs), infra bootstrap/config (server/mod.rs,
server/config.rs), and view components (app/), each one file per
responsibility instead of the previous server.rs/app.rs/pipeline.rs
grab-bags.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LoXS1ERDGC1P189RqmUxAF
2026-09-03 12:03:15 +02:00
Austin Schaefer
341ff9517a Apply cargo fmt across the workspace
Some checks failed
CI / test (pull_request) Has been cancelled
CI / audit (pull_request) Has been cancelled
CI / check (pull_request) Has been cancelled
Needed for the new fmt-check CI step to pass; the repo had never had
formatting enforced before. No logic changes.
2026-08-21 13:10:08 +02:00
Austin Schaefer
a8d4599a03 Replace sqlx with Diesel + diesel-async for compile-time-checked queries
Some checks failed
CI / check (push) Failing after 10s
sqlx's query!/query_as! macros only check raw SQL strings against the live
schema; Diesel's table!-derived DSL type-checks query structure itself at
compile time. SQLite has no native async driver, so diesel-async wraps a
blocking SqliteConnection via SyncConnectionWrapper, pooled with bb8.

Migrations move from sqlx's single-file-per-migration format to Diesel's
up.sql/down.sql pairs, run transactionally via diesel_migrations against a
throwaway sync connection at boot (MigrationHarness needs a sync
Connection), giving revertable migrations that sqlx::migrate! doesn't
support.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-21 11:04:38 +02:00
Austin Schaefer
1a4a72fc27 Scaffold feedsignal: Rust workspace for LLM-filtered RSS reader
Some checks failed
CI / check (push) Failing after 26s
Rust workspace with core (topic-affinity learning engine + relevance
scoring), db (sqlite/sqlx schema + repo), feeds (RSS/Atom fetch), llm
(rig + local Ollama embeddings/completion), and web (axum + Dioxus
fullstack UI, no separate JS stack). Two-stage relevance filtering
(embedding shortlist -> LLM judgment) and an engagement/surprise-based
topic affinity engine with daily decay. All crates compile and core's
affinity engine has passing unit tests; server and wasm client targets
of feedsignal-web both check clean.
2026-08-20 17:04:14 +02:00