Class: Aireview::ReviewRenderer

Inherits:
Object
  • Object
show all
Defined in:
lib/aireview/review_renderer.rb

Constant Summary collapse

MISMATCH_LIMIT =
2
IMPORTANT_LIMIT =
3
TOTAL_FINDINGS_LIMIT =
3
IMPORTANT_CATEGORIES =
%w[
  bug
  regression
  security
  performance
  data_loss
  edge_case
].freeze
SEVERITY_ORDER =
{
  'critical' => 0,
  'major' => 1,
  'minor' => 2
}.freeze
DEFAULT_LANGUAGE =
'en'
LABELS =
{
  'en' => {
    summary: 'Summary',
    mismatches: 'Mismatches',
    important: 'Important findings',
    result: 'Result',
    disclaimer: 'This report was generated by an AI and may contain mistakes. ' \
                'Verify the findings by hand before acting on them.',
    no_summary: 'The first pass did not return a summary of the changes.',
    none_found: 'None found.',
    not_specified: 'Not specified.',
    where: 'Where',
    problem: 'Problem',
    why: 'Why it matters',
    suggestion: 'Suggestion',
    partial: 'Partial review',
    not_reviewed: 'Not reviewed',
    files_not_shown: 'files not reviewed',
    files_partial: 'files reviewed partially',
    files_unavailable: 'files without an available diff',
    sections_truncated: 'sections truncated',
    hunks_of: 'hunks shown',
    diff_unavailable: 'diff not available',
    section_list: 'Truncated sections',
    fallback_used: 'Fallback model used',
    critique_weaker: 'Critique ran on a model weaker than Generate: the findings were checked less strictly.',
    jev: 'The findings were checked by Jev, a fast classifier, without refining their wording.',
    jev_partial: 'The findings were checked by Jev, a fast classifier, without refining their wording; ' \
                 'those Jev could not judge were checked by the LLM critique.',
    jev_failed: 'Jev was unavailable: the findings were checked by the LLM critique.',
    quote_missing: 'quote not found in the diff'
  },
  'ru' => {
    summary: 'Сводка',
    mismatches: 'Несоответствия',
    important: 'Важные замечания',
    result: 'Результат',
    disclaimer: 'Отчёт сгенерирован ИИ и может содержать ошибки. ' \
                'Проверьте замечания вручную перед принятием решений.',
    no_summary: 'Сводка изменений не была возвращена на первом проходе.',
    none_found: 'Не найдено.',
    not_specified: 'Не указано.',
    where: 'Где',
    problem: 'Проблема',
    why: 'Почему важно',
    suggestion: 'Предложение',
    partial: 'Ревью частичное',
    not_reviewed: 'Не вошло в ревью',
    files_not_shown: 'файлов не проверено',
    files_partial: 'файлов проверено частично',
    files_unavailable: 'файлов без доступного диффа',
    sections_truncated: 'секций усечено',
    hunks_of: 'хунков показано',
    diff_unavailable: 'дифф недоступен',
    section_list: 'Усечённые секции',
    fallback_used: 'Использована резервная модель',
    critique_weaker: 'Критика выполнена моделью слабее generate: замечания проверены менее строго.',
    jev: 'Замечания проверены быстрым классификатором Jev, без уточнения формулировок.',
    jev_partial: 'Замечания проверены быстрым классификатором Jev, без уточнения формулировок; ' \
                 'те, что Jev не смог оценить, проверила LLM-критика.',
    jev_failed: 'Jev был недоступен: замечания проверила LLM-критика.',
    quote_missing: 'цитата не найдена в диффе'
  }
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(language: DEFAULT_LANGUAGE) ⇒ ReviewRenderer

Returns a new instance of ReviewRenderer.



89
90
91
# File 'lib/aireview/review_renderer.rb', line 89

def initialize(language: DEFAULT_LANGUAGE)
  @labels = LABELS.fetch(language.to_s) { LABELS.fetch(DEFAULT_LANGUAGE) }
end

Instance Method Details

#render(accepted, summary:, coverage: nil, fallback_models: {}, critique_weaker: false, jev_note: nil) ⇒ Object

coverage: the truncation facts from the pipeline, not the model's text. result is still about the findings; incomplete coverage is written next to it so that the result line does not read as "everything was checked". jev_note — how Jev took part in the critique (see JevStage::Outcome). The facts about the run are named one by one on purpose.



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/aireview/review_renderer.rb', line 99

def render(accepted, summary:, coverage: nil, fallback_models: {}, critique_weaker: false, jev_note: nil) # rubocop:disable Metrics/ParameterLists
  mismatches, important = select_findings(Array(accepted))
  result = mismatches.empty? && important.empty? ? 'ok' : 'needs attention'

  <<~MARKDOWN.rstrip
    ## #{label(:summary)}

    #{summary_text(summary)}

    ## #{label(:mismatches)}

    #{render_findings(mismatches)}

    ## #{label(:important)}

    #{render_findings(important)}

    ## #{label(:result)}

    #{result}#{partial_note(coverage)}
    #{coverage_block(coverage)}#{fallback_note(fallback_models)}#{weaker_note(critique_weaker)}#{jev_note(jev_note)}
    #{label(:disclaimer)}
  MARKDOWN
end