{"id":51475353,"url":"https://github.com/asmuelle/ibrief","last_synced_at":"2026-07-06T20:30:32.557Z","repository":{"id":368188037,"uuid":"1283391766","full_name":"asmuelle/ibrief","owner":"asmuelle","description":"Selbstverbesserndes, personalisiertes Morning Briefing — lokal-first in Rust mit lokalen LLMs. Lernt Gewichte, Prompts und Quellen; Anti-Blase by design.","archived":false,"fork":false,"pushed_at":"2026-06-29T11:27:28.000Z","size":145,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-29T13:14:29.369Z","etag":null,"topics":["ai-agents","llm","local-first","morning-briefing","ollama","rust","self-improving"],"latest_commit_sha":null,"homepage":"https://asmuelle.github.io/ibrief/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/asmuelle.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-28T22:01:27.000Z","updated_at":"2026-06-29T11:27:32.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/asmuelle/ibrief","commit_stats":null,"previous_names":["asmuelle/ibrief"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/asmuelle/ibrief","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asmuelle%2Fibrief","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asmuelle%2Fibrief/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asmuelle%2Fibrief/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asmuelle%2Fibrief/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/asmuelle","download_url":"https://codeload.github.com/asmuelle/ibrief/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asmuelle%2Fibrief/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35205739,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-06T02:00:07.184Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","llm","local-first","morning-briefing","ollama","rust","self-improving"],"created_at":"2026-07-06T20:30:31.752Z","updated_at":"2026-07-06T20:30:32.538Z","avatar_url":"https://github.com/asmuelle.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ibrief\n\n[![CI](https://github.com/asmuelle/ibrief/actions/workflows/ci.yml/badge.svg)](https://github.com/asmuelle/ibrief/actions/workflows/ci.yml)\n[![Rust 1.95](https://img.shields.io/badge/rust-1.95%20edition%202024-orange.svg)](https://www.rust-lang.org)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n\nSelbstverbesserndes, personalisiertes Morning Briefing — lokal-first in Rust, mit lokalen LLMs.\nSiehe [SPEC.md](SPEC.md) · **[Projektseite ↗](https://asmuelle.github.io/ibrief/)**\n\n**Stand: M1–M6 ✓** — vollständige Pipeline plus Selbstverbesserung auf drei Achsen (Gewichte,\nPrompts, Quellen), jede abgesichert. Anti-Blase-Sektionen (Gegenperspektive, Wildcard) sind\nnicht abschaltbar. Build + Tests grün unter Rust 1.95 / Edition 2024.\n\n## Voraussetzungen\n\n- Rust (1.80+)\n- [Ollama](https://ollama.com) lokal laufend, mit den Modellen aus `config/profile.toml`:\n\n```bash\nollama pull qwen2.5:14b      # Massen-Tier (Enrich)\nollama pull llama3.3:70b     # Synthese-Tier (TL;DR)\n```\n\n\u003e Auf kleinerer Hardware kleinere Modelle eintragen (z.B. `llama3.1:8b` für beide).\n\n## Lauf\n\n```bash\ncargo run -p ibrief-app                 # = `brief`: Briefing erzeugen\ncargo run -p ibrief-app -- brief ./config\n```\n\nErgebnis: `out/briefing-YYYY-MM-DD.md` (+ stdout) und Persistenz in `ibrief.db`\n(Items werden dedupliziert — bereits gesehene erscheinen nicht erneut).\n\n### Feedback via Telegram (optional)\n\n1. Bot bei [@BotFather](https://t.me/BotFather) anlegen, Token holen.\n2. `chat_id` in `config/profile.toml` setzen, `enabled = true`.\n3. Token als Env-Var bereitstellen und beide Prozesse starten:\n\n```bash\nexport IBRIEF_TELEGRAM_TOKEN=123456:ABC...\ncargo run -p ibrief-app -- brief        # pusht das Briefing mit 👍/👎-Buttons\ncargo run -p ibrief-app -- feedback     # Long-Polling: Klicks → ibrief.db (Tabelle feedback)\n```\n\nDie erfassten 👍/👎 sind die Datengrundlage für den Lern-Loop ab M3/M4.\n\n## Workspace\n\n| Crate | Zweck |\n|-------|-------|\n| `ibrief-core` | Domänentypen (`ContentItem`, `Briefing`, …) |\n| `ibrief-llm` | `LanguageModel`-Trait + Backends: `OllamaClient` (lokal), `ClaudeCodeModel` (Abo via `claude -p`) |\n| `ibrief-ingest` | RSS/Atom-Fetch (`feed-rs`) |\n| `ibrief-pipeline` | Stages: Enrich, Curate, Render |\n| `ibrief-store` | SQLite (sqlx): Content, Briefing-Records, Feedback, Evals, Dedup |\n| `ibrief-telegram` | Telegram-Push + Feedback-Buttons (Bot-API via reqwest) |\n| `ibrief-eval` | Eval Engine: Verhaltens-Score + LLM-Judge + Strukturchecks |\n| `ibrief-learn` | Gewichts-Lernen: Thompson-Sampling + Safety Gate + A/B-Entscheidung + Config-Versionierung |\n| `ibrief-optimize` | Prompt-Optimierung: Optimizer-LLM + Schatten-Test + Prompt-Versionierung |\n| `ibrief-sources` | Quellen-Evolution: Qualitäts-Scoring + Pruning + Drift-Wächter |\n| `ibrief-research` | AutoResearch (§14): gated Loop + Beleg-Verifikation über lokalen Korpus |\n| `ibrief-app` | Binary `ibrief` (`brief`/`feedback`/`eval`/`learn`/`config`/`optimize`/`experiment`/`sources`/`research`) |\n\n## Eval (M3)\n\n```bash\ncargo run -p ibrief-app -- eval               # heutiges Briefing bewerten (Judge lokal)\ncargo run -p ibrief-app -- eval 2026-06-28    # bestimmtes Datum\ncargo run -p ibrief-app -- eval calibrate     # Judge via Abo (claude -p) statt lokal\n```\n\nErgebnis: `total`-Note (0–1) aus `behavior`/`judge`/`structure` (Gewichte 0.5/0.3/0.2),\ngespeichert in der `evals`-Tabelle pro `date × config_version`. Diagnose-Notizen inklusive.\n\n## Lernen (M4)\n\n```bash\ncargo run -p ibrief-app -- learn              # Gewichte aus Feedback lernen (Thompson + Safety Gate)\ncargo run -p ibrief-app -- config list        # Config-Historie (aktive mit * markiert)\ncargo run -p ibrief-app -- config rollback cfg-xxxx   # auf frühere Version zurück\n```\n\n`learn` aggregiert das Feedback je Quelle/Thema, sampelt neue Gewichte (Beta/Thompson,\ngeklemmt auf [0.2, 2.0] → Exploration-Floor gegen Aussterben), prüft das **Safety Gate**\n(Grenzen + Quellen-Diversität) und übernimmt nur bei PASS als neue, versionierte Config.\n`brief` nutzt die aktive Config beim Ranking (`recency × source_weight × topic_weight`).\n\n## Prompt-Optimierung (M5)\n\n```bash\ncargo run -p ibrief-app -- optimize 2026-06-28          # TL;DR-Prompt im Schatten-Test verbessern\ncargo run -p ibrief-app -- optimize 2026-06-28 calibrate # Optimizer+Judge via Abo (claude -p)\ncargo run -p ibrief-app -- experiment list               # A/B-Experiment-Historie\n```\n\nEin Optimizer-LLM erzeugt eine Prompt-Variante; im **Schatten-Test** rendern aktiver und\nKandidaten-Prompt dasselbe Beispiel-Briefing, der Judge bewertet beide. Nur bei klarem\nVorsprung (Marge 0.05) wird der Kandidat neue, versionierte Default-Prompt-Version.\n`brief` nutzt stets den aktiven Prompt. Die temporale A/B-Entscheidung\n(`ibrief-learn::ab_decision`) ist die Grundlage für mehrtägige Behavioral-Tests.\n\n## Quellen-Evolution \u0026 AutoResearch (M6)\n\n```bash\ncargo run -p ibrief-app -- sources list      # Registry: Qualität, aktiv/inaktiv\ncargo run -p ibrief-app -- sources evolve     # bewerten + aussortieren (mit Drift-Wächter)\ncargo run -p ibrief-app -- research \"Was ist neu bei lokalen LLMs?\"\n```\n\n`sources evolve` bewertet Quellen aus Feedback + Selektionshäufigkeit, deaktiviert schwache\n(nie unter 3 aktive), und der **Drift-Wächter** setzt Pruning aus, wenn die Quellen-Diversität\nzu stark sinkt (HHI \u003e 0.5) — Anti-Blase vor Engagement.\n`research` ist der gated AutoResearch-Loop (§14) über den lokalen Korpus: belegpflichtig,\nunbelegte Aussagen werden verworfen. Die `ResearchSource`-Trait erlaubt später ein Web-Backend.\n\n## Roadmap\n\nM1 statisch ✓ · M2 Persistenz + Feedback ✓ · M3 Eval ✓ · M4 Lernen (Gewichte) ✓ · M5 Prompt-Opt ✓ · M6 Quellen-Evolution + AutoResearch ✓.\nDetails in [SPEC.md](SPEC.md). Alle Meilensteine implementiert; Build + 19 Tests grün.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasmuelle%2Fibrief","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fasmuelle%2Fibrief","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasmuelle%2Fibrief/lists"}