Skip to content

refactor(review): model summary degradation as one enum - #531

Merged
devops-thiago merged 1 commit into
release/v0.6.0from
fix/527-summary-degradation-enum
Aug 11, 2026
Merged

refactor(review): model summary degradation as one enum#531
devops-thiago merged 1 commit into
release/v0.6.0from
fix/527-summary-degradation-enum

Conversation

@devops-thiago

@devops-thiago devops-thiago commented Aug 11, 2026

Copy link
Copy Markdown
Owner

What type of PR is this?

  • 🔧 Refactor

Description

summaryResponseCut and summarySkippedAtCeiling were two mutually exclusive booleans set on disjoint control paths (salvagedOrCountsOnlySummary vs countsOnlySummary). The pair made the meaningless both-true state representable, forced ordered else if chains at the render sites, and duplicated the entire AtomicBoolean recorder/accessor/defensive-snapshot apparatus on BudgetPlan.

This replaces the pair with a single SummaryDegradation enum (NONE / RESPONSE_CUT / SKIPPED_AT_CEILING):

  • BudgetPlan: one AtomicReference<SummaryDegradation> component with one recorder (recordSummaryDegradation), one value accessor (summaryDegradation()) and one defensive snapshot accessor, replacing both AtomicBoolean apparatuses — the canonical constructor shrinks from 9 to 8 args.
  • TruncationDetail: one enum component replacing both booleans — the canonical constructor shrinks from 6 to 5 args. The isEmpty() / hasFileGaps() guards (and the truncationDisclosure gap-only guard built on them) are preserved verbatim: a degradation still defeats isEmpty(), still does not create a file gap.
  • Render sites switch on the enum: VerdictBuilder's banner selection and truncationSuffixFor, plus the shared ReviewResult.coverageGapClause and coverageGapBrief.
  • Recording sites in FindingPipeline pass the matching constant; a single slot makes the impossible cut-and-skipped-at-once state unrepresentable by construction.

Related Issues

Fixes #527

How Has This Been Tested?

  • Unit tests

Behavior-preserving: every rendered string stays byte-identical — no rendering test's expected strings changed (the test diff touches only constructor arities, recorder calls, and flag-accessor assertions, all migrated mechanically to the enum). Full suite green: 2594 tests, 0 failures (one fewer than before only because the four per-boolean plan-apparatus tests consolidated into three enum-slot tests covering the same contracts: live recording, defensive snapshot, caller-supplied slot staying live, and no approval hold).

Gates: spotless:apply clean; clean compile spotbugs:check spotless:check — BugInstance size is 0; jacoco ∩ diff on all changed main code (including the new SummaryDegradation.java): 0 missed instructions, 0 missed branches.

Checklist

  • My code follows the project's coding standards
  • I have performed a self-review of my own code
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I have updated the documentation accordingly
  • My changes generate no new warnings or errors

Screenshots / Logs

N/A

Additional Notes

Originally stacked on #530 (the degenerate-lane ceiling catch, whose recording site this refactor also migrates); #530 has since merged, so this targets release/v0.6.0 directly, rebased on top of it. Diff is scoped to #527 only.

summaryResponseCut and summarySkippedAtCeiling were two mutually
exclusive booleans set on disjoint control paths, which made the
meaningless both-true state representable, forced ordered else-if
chains at the render sites, and duplicated the whole AtomicBoolean
recorder/accessor/defensive-snapshot apparatus on BudgetPlan.

Replace the pair with a single SummaryDegradation enum
(NONE / RESPONSE_CUT / SKIPPED_AT_CEILING):

- BudgetPlan carries one AtomicReference slot with one recorder
  (recordSummaryDegradation), one value accessor and one defensive
  snapshot accessor — canonical constructor shrinks to 8 args
- TruncationDetail carries one enum component — canonical constructor
  shrinks to 5 args; isEmpty/hasFileGaps guards preserved verbatim
- the render sites (review banner, check-run suffix, coverage-gap
  clause, check-run brief) switch on the enum

Behavior-preserving: every rendered string stays byte-identical; the
full suite is green with only mechanical test migrations.
@github-actions

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@thrillhousebot

Copy link
Copy Markdown

🤖 ThrillhouseBot PR Summary

What this PR does

Replaces the mutually-exclusive summaryResponseCut/summarySkippedAtCeiling boolean pairs on BudgetPlan and TruncationDetail with a single SummaryDegradation enum (NONE/RESPONSE_CUT/SKIPPED_AT_CEILING), collapsing the two AtomicBoolean recorder/accessor/defensive-snapshot apparatuses into one AtomicReference slot. Recording sites in FindingPipeline pass the matching enum constant, and render sites in VerdictBuilder and ReviewResult switch on the enum instead of ordered else-if chains, preserving all rendered output byte-for-byte while making the both-at-once degradation state unrepresentable.

Control-Flow Diagram

🔀 Show diagram
flowchart TD
    A["Summary call finishes"]
    A --> B{"Degradation lane?"}
    B -- "response cut at length cap" --> C["recordSummaryDegradation(RESPONSE_CUT)"]
    B -- "skipped at token spend ceiling" --> D["recordSummaryDegradation(SKIPPED_AT_CEILING)"]
    B -- "complete" --> S
    C --> S["BudgetPlan single slot (AtomicReference)"]
    D --> S
    S --> T["TruncationDetail.summaryDegradation"]
    T --> U{"hasFileGaps?"}
    U -- "yes" --> V["Coverage banner plus gap clauses"]
    U -- "no" --> W{"Switch on degradation"}
    W -- "RESPONSE_CUT" --> X["SUMMARY_CUT_NOTICE and shortened suffix"]
    W -- "SKIPPED_AT_CEILING" --> Y["SUMMARY_SKIPPED_NOTICE and skipped suffix"]
    W -- "NONE" --> Z["Markdown unchanged"]
Loading

Changes Overview

  • Files changed: 11
  • Lines added: +316
  • Lines removed: -282

Changed Files

File Change Summary
src/main/java/dev/thiagogonzaga/thrillhousebot/review/AbstractPrSuggestionGenerator.java Modified Disclosure builder passes SummaryDegradation.NONE for the new single enum slot.
src/main/java/dev/thiagogonzaga/thrillhousebot/review/DiffBudgetPlanner.java Modified BudgetPlan replaces two AtomicBoolean flags with one AtomicReference slot; constructor drops from 9 to 8 args.
src/main/java/dev/thiagogonzaga/thrillhousebot/review/FindingPipeline.java Modified Recording sites call recordSummaryDegradation with RESPONSE_CUT or SKIPPED_AT_CEILING; javadoc updated.
src/main/java/dev/thiagogonzaga/thrillhousebot/review/ReviewResult.java Modified TruncationDetail swaps the two booleans for the enum; isEmpty/hasFileGaps preserved; coverageGapClause and coverageGapBrief switch on the degradation.
src/main/java/dev/thiagogonzaga/thrillhousebot/review/SummaryDegradation.java Added New enum NONE/RESPONSE_CUT/SKIPPED_AT_CEILING modeling how the summary prose degraded, with rationale javadoc.
src/main/java/dev/thiagogonzaga/thrillhousebot/review/VerdictBuilder.java Modified Banner selection and truncationSuffixFor switch on SummaryDegradation instead of ordered else-if chains.
src/test/java/dev/thiagogonzaga/thrillhousebot/review/DiffBudgetPlannerTest.java Modified Migrates to the 8-arg constructor; consolidates four flag tests into three enum-slot tests for live recording, snapshots, and caller-supplied slots.
src/test/java/dev/thiagogonzaga/thrillhousebot/review/FindingPipelineTest.java Modified Recorder assertions now compare plan.summaryDegradation() to the matching enum constant; constructor arities updated.
src/test/java/dev/thiagogonzaga/thrillhousebot/review/FollowUpDeltaSummaryTest.java Modified Delta-comment fixtures pass enum constants for the summary degradation slot.
src/test/java/dev/thiagogonzaga/thrillhousebot/review/ReviewResultTest.java Modified TruncationDetail fixtures use enum constants; asserts null degradation normalizes to NONE and empty/file-gap guards hold.
src/test/java/dev/thiagogonzaga/thrillhousebot/review/VerdictBuilderTest.java Modified Plan constructions updated to 8 args; banner and suffix assertions check summaryDegradation() equals the matching constant.

Risk Assessment

Risk Count
🔴 Critical 0
🟠 High 0
🟡 Medium 0
🔵 Low 0

No new issues found in this PR, but the review cannot be approved until CI is confirmed green.

⚠️ CI Checks Status

Some checks are still pending or have failed:

Check Type Status Detail
trivy check-run ⏳ Pending -
changes check-run ⏳ Pending -
format check-run ⏳ Pending -
frontend check-run ⏳ Pending -
actionlint check-run ⏳ Pending -
test check-run ⏳ Pending -
dependency-review check-run ⏳ Pending -

Automated review by ThrillhouseBot. Reply with /review to re-run.

@thrillhousebot thrillhousebot Bot added java Pull requests that update java code tech-debt labels Aug 11, 2026
@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@sonarqubecloud

Copy link
Copy Markdown

@devops-thiago
devops-thiago merged commit abd76e5 into release/v0.6.0 Aug 11, 2026
14 checks passed
@devops-thiago
devops-thiago deleted the fix/527-summary-degradation-enum branch August 11, 2026 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

java Pull requests that update java code tech-debt

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant