Skip to content

v1.0.0: Stable. Opinion coverage, copied-article detection, simpler install

Choose a tag to compare

@grregis grregis released this 20 Oct 23:35
· 20 commits to main since this release

Status: stable. MuckScraper is out of beta. From here on, upgrades within
1.x never break your stored config or customizations (topics, RSS feeds,
prompts, scheduled fetches, ingestion blocks); anything that would is saved
for 2.0 and called out there. Since 0.8 this release adds opinion
coverage
(an Op/Ed section with columns linked to the stories they argue
about, each with its stance, and a roundup of what each side says),
copied-article detection so one wire report under three mastheads counts
once, deep analysis for every edition article, past editions, and
Google News search feeds for the big outlets whose own feeds died. It
also makes a fresh install simpler (both secret keys generated on the first
run) and safer (a placeholder SECRET_KEY is refused), and moves to current
urllib3 and requests.

Added

  • OLLAMA_THINK (optional, blank by default). Set it to false to turn
    off a thinking model's hidden reasoning (gemma4, qwen3, deepseek-r1), which
    is most of the time those models spend per call. Blank keeps Ollama's
    default, so existing installs are unchanged.
  • Read-only MCP server (mcp_server/, docs in docs/MCP.md), off by
    default behind the mcp Compose profile. Gives an AI assistant health and
    troubleshooting checks: run status and history, last run, filtered scheduler
    logs, Ollama state (without waking the box), outage signs, edition lineups,
    quality report, story/article lookup and search, scrape and bias coverage,
    containers, search index, whether running code is current, and a runbook
    lookup over the docs. The database connection refuses writes, the checkout
    is mounted read-only, and HTTP access needs a bearer token (MCP_TOKEN).
  • docker-restart-proxy lists each container's start time and restart count,
    and has a bounded, read-only log route (GET /containers/<name>/logs).
  • Op/Ed. Opinion pieces are still kept out of the news, but they are now
    saved to their own table instead of being dropped, and listed on a new Op/Ed
    page (sidebar, below the topics) with a time window, a Left / Center / Right
    filter and search. A new op_ed RSS bucket stores every entry of an
    opinion feed straight to Op/Ed; ten default feeds, balanced across the
    spectrum. On full runs, each new column is linked to the news story it
    argues about (embedding match plus a yes/no check by the fast model), and a
    story with two or more linked columns gets a short opinion roundup saying
    what each side argues. Letters to the editor are never linked.
  • Copied articles are marked. An article that shares at least half its
    text with another outlet's article in the same story (a syndicated wire
    story, or one outlet running another's piece) is labelled "Same report as
    ..." on the story page, and is not counted as a separate source in story
    selection, headlines, summaries or reports.
  • Deep analysis for every edition article with at least 500 characters of
    text, shown in a Deep Analysis box on the article page. Sports reports first
    decide whether the story is about a game, and stop assuming one.
  • Quality check for invented titles: the quality report flags summaries
    and reports that call someone "former President ..." (or another former
    office) when no source does.
  • Past editions. A Past editions page lists every edition, grouped by
    month, and opens each one as it was published, read live from the
    database, so opinion columns added to its stories since are there too.
  • A page for each Op/Ed piece: what it argues, the story it's linked
    to, its text (signed-in readers only) and a link to the publisher. The
    Op/Ed list and the story page's columns link there.
  • Opinion page per edition: the stories that got new opinion columns in
    that edition, each column with a one-line stance. Every linked column now
    gets a stance, not only the ones a roundup described.
  • Outlets without a working RSS feed (CNN, AP, Reuters, WSJ) come in
    through Google News search feeds. Each link is resolved to the publisher's
    own URL before anything is stored; an entry that can't be resolved is
    dropped and retried next run.
  • Feed fallback URL: any RSS feed can have a second URL, fetched instead
    when the feed answers an HTTP error or can't be parsed (set it on the RSS
    Feeds page).
  • Signed-out article pages say in plain words how much of the article
    could be read ("Fully read", "Publisher blocked full-text access", ...), and
    why there is no summary when the text couldn't be read.

Changed

  • Ingestion refuses more junk: fantasy-sports advice, "odds, predictions"
    betting picks, Seeking Alpha contributor pieces, editorial cartoons (as
    news and as Op/Ed), show and interview transcripts, and "News of the day"
    digests. News about cartoons or transcripts is kept. HTML tags embedded in
    feed titles are stripped.
  • Editions prefer stories covered by two or more outlets, not two
    articles: one outlet's pair (a transcript plus its write-up) no longer
    jumps ahead of single-source stories.
  • "former President" is fixed in code. Summaries, reports, headlines and
    opinion roundups no longer call the current President or Vice President
    "former" unless a source does. Prompt rules alone never stopped the model
    doing it.
  • Back to Feed returns to where you were. Going back from a story or
    article lands on the same card in the list, or the same row in Search,
    instead of the top of the page.
  • On article pages, scrape details sit above the summary for signed-in readers.
  • The dark top bar spans the full page width on All Stories, Grouped Stories
    and Search.
  • Layout and navigation pass: every page has its back link in the same
    place ("Back to Feed" returns to the list you came from, config pages go
    "Back to Admin Tools"); the accent colour is the sidebar's indigo (blue is
    left for Left); every page has the Light/Dark button and follows the saved
    theme; the Headlines and Fetch top bars are sticky; and no page is wider
    than a phone screen, upright or sideways.
  • The browser tab icon is the raccoon mascot.
  • The quality checker accepts either label set when a prompt offers two
    formats.
  • seed_defaults() seeds prompts as the migrations leave them, so a fresh
    install starts with the current prompt text.
  • Article summaries are shown as one paragraph, without the section labels.
  • Phones: the top bar keeps the title, theme button and account control on
    one line.
  • Default feeds: Google News searches replace the dead CNN, AP, Reuters,
    WSJ and The Economist feeds; more right-leaning news feeds; and ten Op/Ed
    feeds balanced left and right (the op_ed bucket had none by default).
    Existing installs get the new rows added and nothing else changed: the dead
    feeds stay as they are, so disable them on the RSS Feeds page.
  • Install: .env.sample leaves the optional news API keys blank (no more
    "still unedited" prompt for them) and suggests a starting model;
    install.sh creates .env readable by its owner only; the optional
    Langfuse, n8n and Wake-on-LAN settings no longer print Compose warnings
    when unset; a first start no longer prints a database traceback while
    Postgres is starting. The first run of install.sh now generates
    SECRET_KEY and MEILI_MASTER_KEY when it creates .env, so you only
    fill in the Ollama settings and the admin password. On an upgrade it
    rebuilds the scheduler image too (before, the scheduler kept running the
    old code until it was rebuilt by hand).
  • The restart proxy finds its own Compose project, so the Admin Tools
    restart buttons work in a clone with any folder name (it assumed
    muckscraper). COMPOSE_PROJECT_NAME in its environment overrides it.
  • Outlet names: Politico, Reason, Newsmax and The Daily Wire now match
    their AllSides entries.

Fixed

  • A wedged Ollama no longer looks asleep. When the port accepts a
    connection but nothing answers, the health probe now treats the box as
    broken and the run fails fast, instead of waiting out hundreds of timeouts.
  • Edition dedupe: two stories sharing only country and leader names
    ("Russia", "Trump", "Ukraine") are no longer treated as the same event; one
    shared word has to be something else. A six-outlet Ukraine story had been
    dropped from two editions.
  • Headlines ending in a quotation keep their closing quote mark.

Removed

  • restart.sh (use ./install.sh, the Admin Tools restart buttons, or
    docker compose up -d <service>), create_admin.py (install.sh creates
    the admin; add more on the Users page) and catcode.sh (an old code-dump
    helper).

Security

  • The app refuses to start with the .env.sample placeholder as its
    SECRET_KEY.
    It used to accept it, and since that value is public, anyone
    could forge a login session on an install that kept it (only possible by
    editing .env by hand; install.sh always replaced it). .env.sample now
    shows the command to generate a key.
  • urllib3 1.26.20 -> 2.8.0 (decompression-bomb and redirect advisories,
    relevant because the pipeline fetches pages from sites it doesn't control)
    and requests 2.31.0 -> 2.34.2. The old urllib3<2.0.0 pin is gone.

Database

  • Seven migrations: f2a6c9e4b7d1 (deep-analysis prompts), a7d3e9f1c2b4
    (Op/Ed table), b3f7c1d9e5a2 (Op/Ed links and roundups), c5d1e8a3f7b9
    (copied-article columns), d8e2a4f6b1c3 (opinion stance prompt),
    e4b7c2a9d6f1 (feed fallback URL), f7a1d3c5e8b2 (new default feeds,
    added only where missing). All are additive.

Upgrade Notes

  • Wait for a run to finish, then pull and run the installer:

    git pull
    ./install.sh

    It rebuilds the images (the scheduler and the restart proxy included),
    applies the seven migrations and recreates the containers. By hand:
    docker compose up -d --build, then
    docker compose exec app flask db upgrade.

  • If .env still has the sample SECRET_KEY, the app now refuses to
    start. Generate a key with
    python3 -c "import secrets; print(secrets.token_hex(32))", put it in
    .env, and run docker compose up -d app scheduler. Everyone has to sign
    in again afterwards.

  • New default feeds are added; your own feeds are left alone. So the
    old defaults the new ones replace stay enabled: on the RSS Feeds page,
    disable the CNN, AP, Reuters and WSJ feeds (dead), The Economist's "world
    this week" feed (weekly round-ups only) and National Review in general
    and right_enrichment (its columns were landing in the news; it now comes
    in through Op/Ed). Their replacements are already in.

  • New optional settings: OLLAMA_THINK (blank keeps Ollama's default;
    false turns off a thinking model's hidden reasoning) and MCP_TOKEN for
    the optional MCP server
    (docker compose --profile mcp up -d --build mcp docker-restart-proxy).