Skip to content

fix(report): unrated content carries no trend, demoted gets no model narrative (ADR-0038) - #59

Merged
MikkoNumminen merged 2 commits into
masterfrom
fix/moderation-no-trend-no-synthesis
Jul 15, 2026
Merged

fix(report): unrated content carries no trend, demoted gets no model narrative (ADR-0038)#59
MikkoNumminen merged 2 commits into
masterfrom
fix/moderation-no-trend-no-synthesis

Conversation

@MikkoNumminen

Copy link
Copy Markdown
Owner

Follow-up to #58. Closes the two residual severity-leak surfaces that audit surfaced there (Notes A and B). Independent of #58 (disjoint code regions) — can merge in either order.

Problem

After ADR-0032 made demoted categories (rasismi/asiaton) unrated, two severity-derived signals still reached the moderation view:

  • Note A — the standard /report path (management view / + the offline snapshot) ran a full LLM synthesis over demoted groups. The synthesis digest feeds the model each item's severity, so it could editorialize a rating back into the moderation card — '<slur>' (korkea) — the very thing ADR-0032 removed from the badges. (The desk/live-summary path was already deterministic there.)
  • Note B — the trend (kasvava/paheneva/…) was computed and shown for demoted themes on desk, management, and snapshot. paheneva (worsening) is severity-derived, so a moderation card could show a severity judgment on hostile content.

Fix

  • A demoted category is built as a count-only moderation theme (ReportService.BuildModerationTheme) in both the standard and live-summary paths: neutral stable direction with an empty label, a deterministic count narrative (ReportText.ModerationNarrative), and no model call — the model never authors prose over hostile content, and the LLM budget is saved.
  • The views (desk, index.html, SnapshotHtml) suppress the trend for unrated themes, symmetric with the existing severity/sentiment suppression.

Unrated now means no severity, no sentiment, no trend, no model narrative — the full "the category is the signal" contract.

Tests

  • New regression test StandardMode_DemotedCategory_IsCountOnlyModerationTheme_NoModelNarrative_NoTrend: a demoted group makes no LLM call (exactly one call, for the rated group), is Unrated with stable/empty direction, and its narrative carries no severity words.
  • Full solution: Api 148, Llm 79, Generator 25 — 0 failed.

AI-first docs

Yes — new ADR-0038 (unrated = no trend + no model narrative for demoted), indexed in docs/decisions/README.md.

…narrative (ADR-0038)

Two severity-derived signals still leaked onto the moderation view after ADR-0032:

1. The standard /report path (management view + offline snapshot) ran a full LLM
   synthesis over demoted (rasismi/asiaton) groups too. The synthesis digest feeds
   the model each item's severity, so it could editorialize a rating back into the
   moderation card ("'<slur>' (korkea)") — the thing ADR-0032 removed from badges.
2. The trend/direction was computed and shown for demoted themes on desk,
   management, and snapshot. "paheneva" (worsening) is severity-derived, so a
   moderation card could show a severity judgment on hostile content.

Build a demoted category as a deterministic count-only moderation theme
(BuildModerationTheme) in both the standard and live-summary paths: neutral
"stable" direction with an EMPTY label, a deterministic count narrative
(ReportText.ModerationNarrative), and no model call — so the model never authors
prose over hostile content (and the LLM budget is saved). The views (desk,
index.html, SnapshotHtml) suppress the trend for unrated themes, symmetric with
how they already suppress severity/sentiment.

Unrated now means no severity, no sentiment, no trend, no model narrative — the
full "the category is the signal" contract.

Adds a regression test: a demoted group makes no LLM call, is Unrated with a
"stable"/empty direction, and its narrative carries no severity words.
…ct, tidy moderation UI

From the two-PR review:
- Reword ADR-0038 so it does not assert the whole-window Yhteenveto is already
  fixed on this branch: scope the "no model over demoted" claim to the per-category
  moderation themes, and reference the companion rated-only Overall change
  (ADR-0033 §3) for the Yhteenveto — accurate whether or not the companion PR is
  merged yet.
- Relocate this PR's ReportServiceTests [Fact] to a disjoint anchor (after the
  Alerts test) so it no longer collides with the sibling PR's test at the same
  insertion point — the two now merge without a hand-resolved conflict.
- index.html: also drop the "automaattinen kooste" tag on unrated moderation
  cards, so a moderation card is count-only and consistent with the desk/snapshot.
- feedctl: print the count only (no "stable" trend token) for unrated themes,
  matching the management views.
@MikkoNumminen
MikkoNumminen merged commit 707be07 into master Jul 15, 2026
3 checks passed
@MikkoNumminen
MikkoNumminen deleted the fix/moderation-no-trend-no-synthesis branch July 15, 2026 01:01
MikkoNumminen added a commit that referenced this pull request Jul 16, 2026
* chore: ignore local poro-findings.pdf export; record TODO #9 (deploy) done

The canonical Poro findings are docs/poro-findings.md; the root PDF is a
personal export, so gitignore it rather than track a binary. Also commits the
already-recorded TODO item #9 (rebuild+restart to pick up the #58/#59
demoted-content fixes, verified live 2026-07-15).

* docs: mark TODO #8 (SQLite security watch) done — resolved by #55

Bundled SQLite is now 3.50.4 (>= 3.50.2), clearing GHSA-2m69-gcr7-jv3q.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant