Files
rengine/reports/sections/changes/section.py
T
Yogesh OjhaandClaude Opus 5 2b52fa0d0a refactor(ui): the interface explained itself to the reader instead of naming things
Page subtitles, panel descriptions and field labels had drifted into prose
that narrates a feature rather than naming it. A subtitle read "Connect a
language model to draft report narratives. Everything reNgine computes works
without it; a model only changes how the findings are written up." where the
older pages already say "Instance-wide configuration".

A subtitle and a panel description are noun phrases with no trailing period.
Four patterns went out:

- Second person. "Your keywords", "Your themes", "Your templates", "Your
  company" and three "Yours" origin badges become "Keywords", "Custom themes",
  "Custom templates", "Company", "Custom" — moved in the backend SSOT so the
  frontend mirrors follow. "Checks you uploaded" is "Custom templates";
  "Upload your own in the Tools Arsenal" is "Custom lists are uploaded in the
  Tools Arsenal". The user's own credentials keep "your".

- Rhetorical What/Where/Why headings. "What is listening" is "Service
  classes", "Where it concentrates" is "Findings by target", "What changed"
  is "Changes", "Worth acting on first" is "Priority queue", "Why this is
  interesting" is "Signals". Nine query-grammar field descriptions follow the
  rule already on record: "How many parameters the endpoint accepts" is
  "Number of parameters the endpoint accepts".

- The reassuring second clause that explains the first away. Cut from the AI
  page, the reports empty state and the schedules panel. The AI alert states
  what is sent and what is not, then stops.

- "Create your first X" as a heading, now "No scan engines" / "Create a
  project".

Two delete dialogs were missing the standard "This action cannot be undone."
tail. schedule-list-card used a native title= for a hover hint, which the
project forbids; it is a Hint now.

Copy in shared/, stages/, reports/ and interest/ renders straight into the UI
and gets the same pass. MCP tool descriptions are left alone: they are prompts
a model plans against, not UI copy, even though /mcp displays them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016AeRG6G2FdSyWjG4AXPhBA
2026-09-06 19:50:21 +05:30

59 lines
2.0 KiB
Python

from __future__ import annotations
from reports.base import RenderContext, Section
from reports.config import SectionConfig, flag, limit
from shared.definitions.reports import SectionGroup
from shared.definitions.surface import SURFACE_LABELS, SURFACE_NOUN
class ChangesConfig(SectionConfig):
list_added: bool = flag(True, title="List what appeared")
list_gone: bool = flag(True, title="List what went away")
max_items: int = limit(
20, title="Items listed per dimension", minimum=1, maximum=200
)
show_new_findings: bool = flag(
True, title="Highlight findings this run reported first"
)
class ChangesSection(Section):
name = "changes"
title = "Changes"
description = "The difference against the previous run. Nothing is reported as new on a first run."
group = SectionGroup.SUMMARY.value
order = 50
config_model = ChangesConfig
def build(self, ctx: RenderContext, cfg: ChangesConfig) -> dict | None:
if ctx.data.previous_scan is None:
return {"first_run": True, "rows": [], "new_findings": []}
rows = [
{
"label": SURFACE_LABELS[line.dimension],
"noun": SURFACE_NOUN[line.dimension][1],
"added": line.added,
"gone": line.gone,
"added_sample": line.added_sample[: cfg.max_items]
if cfg.list_added
else [],
"gone_sample": line.gone_sample[: cfg.max_items]
if cfg.list_gone
else [],
}
for line in ctx.brief.changes
]
new_findings = (
[f for f in ctx.data.findings if f.is_new][:25]
if cfg.show_new_findings
else []
)
if not rows and not new_findings:
return None
return {
"first_run": False,
"rows": rows,
"new_findings": new_findings,
"previous": ctx.data.previous_scan,
}