5fe8f228c1
Add a read-only /ecosystem page that consumes the sibling services' JSON APIs (Nexus entities, Praxis attention, Hexis capabilities), fetched concurrently with honest per-panel error states. Siblings stay headless — mavweb is their human surface (arch §16). Wired via mavweb -nexus/-praxis/-hexis flags; mavweb joins the ecosystem compose network. Fix mobile horizontal overflow across all pages: .content is a flex child with default min-width:auto, so it refused to shrink below the tables' intrinsic width. min-width:0 lets wide tables pan inside .scroll instead of dragging the page sideways. Verified via CDP geometry check (scrollWidth === clientWidth at 430px). Also includes in-progress Ethos UI redesign, ecosystem deploy compose, and planning docs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2.4 KiB
2.4 KiB
Plan: RSS / News Feed Reader
Goal: Maven periodically polls configured RSS/Atom feeds, extracts new items, classifies them by relevance using the embedder, and either stores interesting items as notes or surfaces breaking news via the dispatcher.
Done when:
internal/rss/package — feed parser (Go stdlibencoding/xmlorgithub.com/mmcdole/gofeed), poll loop- Feed config in
config.Config—feeds: [{name, url, category, poll_interval}] - New items are classified by the existing
router.Embedder— items below a relevance threshold are silently dropped - Interesting items: written as
WriteNotewithsource="rss:<feed_name>"; breaking/high-severity items dispatched as care nudges (sev2-3) - Queryable via voice: "что нового в лентах?", "что по технологиям?"
Scope:
- New
internal/rss/package — periodic poller, feed parser, item classifier - Config extension:
feedsarray inconfig.Config - Reuses
internal/router.Embedderfor relevance scoring (same ONNX model or HashEmbedder floor) - Reuses
internal/ipc.CoreAPIfor writing notes - Reuses
internal/delivery.Dispatcherfor breaking news nudges - Reuses
internal/llm.Clientfor item summarization (optional, for long articles)
Steps:
- Add
gofeedor raw XML parser —internal/rss/feed.go:ParseFeed(url) ([]Item, error)whereItem{Title, Link, Summary, Published, Content} - Create
internal/rss/poller.go—Pollerholds[]FeedConfig, polls each on its own interval, trackslast_pollper feed via a fact (kind=config, key=rss:poll:<name>) - Implement relevance classifier — embed each item's title+summary with
router.Embedder, compare against user interest profile (built from notes/facts), drop items below threshold - Interesting items →
ipc.WriteNote(ctx, ts, title+"\n"+summary, embedding, "rss:<feed_name>") - Breaking items (keywords: "CVE", "outage", "critical") →
ipc.WriteFact(kind=env, key=news:breaking, value=title)→ loop ruleBreakingNewsRule(sev3) dispatches nudge - Wire poller into
cmd/mavend/main.go— starts after unlock, separate goroutine - Add voice query handler —
"что нового?"queriesRecentNotesfiltered by source prefixrss:and phrases viaphraser.PhraseQuery - Add
feedsblock toconfig.Configanddeploy/mavend.json - Test with a live RSS feed (e.g.,
https://news.ycombinator.com/rss) — verify items appear in notes table