Skip to content

Fix brainstorm invalid eval triage#46

Merged
El-Fitz merged 5 commits into
mainfrom
fix/brainstorm-eval-preview
Jun 17, 2026
Merged

Fix brainstorm invalid eval triage#46
El-Fitz merged 5 commits into
mainfrom
fix/brainstorm-eval-preview

Conversation

@El-Fitz

@El-Fitz El-Fitz commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Summary

  • harden brainstorm evaluation score parsing for common recoverable score shapes
  • capture bounded raw response previews for invalid structured brainstorm parse failures in JSON output and provider-failures artifacts
  • document the post-hardening L3 validation and next rerun path

Validation

  • cargo fmt --all -- --check
  • cargo test -p refinery_core -q
  • cargo test -p refinery_cli -q
  • cargo clippy -p refinery_core --all-targets -- -D warnings
  • cargo clippy -p refinery_cli --all-targets -- -D warnings

Notes

  • Live L3 validation still degraded after parser hardening; next rerun should inspect response_preview to distinguish malformed/empty/provider output from genuinely unhandled score JSON.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request hardens the brainstorm evaluation score parser to support various score formats (such as scaled text, nested objects, and fallback dimension scores) and introduces a bounded response_preview to provider failure records to capture raw response text for easier triage. Documentation, plans, and tests are updated to reflect these changes. A review comment correctly identified a bug in parse_score_text where spaces around a slash (e.g., "8 / 10") would cause the parser to incorrectly return the denominator as the score, and suggested a robust fix using starts_with('/').

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread crates/refinery_core/src/brainstorm.rs Outdated

if let Some((start, end)) = number_spans.first().copied() {
let after_first = lower[end..].trim_start();
if after_first.starts_with("out of") || after_first.starts_with("/10") {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If the score text contains spaces around the slash (e.g., "8 / 10" or "8.5 / 10"), after_first.starts_with("/10") will evaluate to false. This causes the parser to fall through and incorrectly return the denominator (10.0) as the score instead of the actual score (8.0 or 8.5).

Changing the check to after_first.starts_with('/') correctly handles any whitespace around the slash and supports other potential denominators (e.g., "/5").

            if after_first.starts_with("out of") || after_first.starts_with('/') {

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7243d0d800

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +347 to +353
if let Some(score_idx) = lower.rfind("score") {
if let Some((start, end)) = number_spans
.iter()
.copied()
.find(|(start, _)| *start >= score_idx)
{
return trimmed[start..end].parse::<f64>().ok();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Parse labeled scale text without taking the scale minimum

When a provider returns a string score that includes the scale after the label, e.g. "score":"Score (1-10): 8" or "Score 1-10: 8", this branch selects the first number after score and records 1.0 as a valid evaluation instead of the actual trailing score. Because the value passes the later 1-10 range check, the brainstorm panel and round histories are silently scored incorrectly rather than treating the response as invalid or using the final score.

Useful? React with 👍 / 👎.

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@El-Fitz, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 34 minutes and 38 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b439a6f6-ed7c-4ca2-aadf-eb535a3d208e

📥 Commits

Reviewing files that changed from the base of the PR and between 7243d0d and 5d51dce.

📒 Files selected for processing (1)
  • crates/refinery_core/src/brainstorm.rs
📝 Walkthrough

Walkthrough

Adds an optional response_preview field to BrainstormProviderFailure with a bounded truncation helper, refactors evaluation score parsing into new helper functions supporting more text formats and dimension averaging, propagates response_preview through the CLI JSON output and provider-failures.json artifact writer, and documents an L3 parser validation run.

Changes

Brainstorm evaluation score parser hardening and response_preview capture

Layer / File(s) Summary
BrainstormProviderFailure field and preview helper
crates/refinery_core/src/brainstorm.rs, crates/refinery_cli/src/commands/brainstorm.rs
BrainstormProviderFailure gains response_preview: Option<String>; INVALID_RESPONSE_PREVIEW_CHARS constant and invalid_response_preview truncation helper are introduced; ProviderFailureOutput gains matching optional field.
Evaluation score parsing refactor
crates/refinery_core/src/brainstorm.rs
Inline score extraction is replaced by parse_brainstorm_score, score_value_as_f64, parse_score_text, number_spans, and average_dimension_scores helpers; these accept formats like "8 out of 10", "8/10", "score: +8", and perform dimension averaging only when all required dimensions are present.
response_preview population in brainstorm loop
crates/refinery_core/src/brainstorm.rs
Invalid prompt-variant and invalid evaluation failures store a bounded response_preview; all other failure paths (provider errors, timeouts, join errors, empty proposals) set response_preview: None.
provider-failures.json and CLI JSON output
crates/refinery_core/src/brainstorm.rs, crates/refinery_cli/src/commands/brainstorm.rs
save_provider_failures conditionally emits response_preview into the file artifact; CLI ProviderFailureOutput construction copies response_preview from the failure struct.
Tests: preview truncation, score parsing, artifact output
crates/refinery_core/src/brainstorm.rs
Unit tests cover bounded preview truncation; expanded score-parsing tests cover accepted and rejected formats; async integration tests verify response_preview is captured and exported in provider-failures.json.
Docs: HANDOFF, L3 validation write-up, plan and todo updates
docs/HANDOFF.md, docs/brainstorms/2026-06-12-brainstorm-l3-parser-validation.md, docs/plans/2026-05-23-001-research-brainstorm-strategy-benchmarks-plan.md, todos/013-brainstorm-strategy-benchmarks.md
HANDOFF gains L3 validation context and a Next L3 Validation Runbook; a new L3 parser validation write-up records run results and decisions; plan and todo are updated with parser hardening completion notes and next-step guidance referencing response_preview.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Lightless-Labs/refinery#31: Modifies BrainstormProviderFailure and the CLI's provider-failure JSON output in the same files, directly preceding the response_preview field addition in this PR.
  • Lightless-Labs/refinery#40: Modifies brainstorm evaluation score parsing and parse_brainstorm_evaluation_response in the same file, overlapping with the score-parser refactor in this PR.

Poem

🐇 Hop, hop — the parser grows wise,
Catching "8 out of 10" with bright eyes.
A preview, now bounded and neat,
Tucks bad responses away, oh so sweet.
The failures.json tells the tale —
No invalid score shall ever prevail! 🌟

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title directly relates to the main changes: hardening brainstorm evaluation score parsing and capturing response previews for invalid evaluation triage, which are the core objectives of this PR.
Description check ✅ Passed The description clearly relates to the changeset by summarizing the three main aspects (parser hardening, response preview capture, and documentation) and includes validation steps and implementation notes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/brainstorm-eval-preview

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
crates/refinery_core/src/brainstorm.rs (1)

1431-1437: 💤 Low value

Test assertion uses byte length instead of char count.

The invalid_response_preview helper truncates by character count, but this test asserts on preview.len() (byte length). For this ASCII-only test case they're equivalent, but the assertion doesn't match the function's semantic contract.

Consider using .chars().count() for clarity:

♻️ Suggested change
-        assert_eq!(preview.len(), INVALID_RESPONSE_PREVIEW_CHARS);
+        assert_eq!(preview.chars().count(), INVALID_RESPONSE_PREVIEW_CHARS);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/refinery_core/src/brainstorm.rs` around lines 1431 - 1437, The test
`invalid_response_preview_is_bounded` is asserting on byte length using
`.len()`, but the `invalid_response_preview` function truncates by character
count, not bytes. Change the assertion from `assert_eq!(preview.len(),
INVALID_RESPONSE_PREVIEW_CHARS);` to use `preview.chars().count()` instead of
`preview.len()` to properly verify that the preview is bounded by the character
count specified by `INVALID_RESPONSE_PREVIEW_CHARS`, which matches the actual
semantic contract of the function.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@crates/refinery_core/src/brainstorm.rs`:
- Around line 1431-1437: The test `invalid_response_preview_is_bounded` is
asserting on byte length using `.len()`, but the `invalid_response_preview`
function truncates by character count, not bytes. Change the assertion from
`assert_eq!(preview.len(), INVALID_RESPONSE_PREVIEW_CHARS);` to use
`preview.chars().count()` instead of `preview.len()` to properly verify that the
preview is bounded by the character count specified by
`INVALID_RESPONSE_PREVIEW_CHARS`, which matches the actual semantic contract of
the function.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2fab4b42-408f-4753-822a-7f0c82538981

📥 Commits

Reviewing files that changed from the base of the PR and between c0c7ae3 and 7243d0d.

📒 Files selected for processing (6)
  • crates/refinery_cli/src/commands/brainstorm.rs
  • crates/refinery_core/src/brainstorm.rs
  • docs/HANDOFF.md
  • docs/brainstorms/2026-06-12-brainstorm-l3-parser-validation.md
  • docs/plans/2026-05-23-001-research-brainstorm-strategy-benchmarks-plan.md
  • todos/013-brainstorm-strategy-benchmarks.md
📜 Review details
🧰 Additional context used
📓 Path-based instructions (3)
**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.rs: Run cargo test --workspace to run all tests
Use cargo build --workspace to build all crates

Files:

  • crates/refinery_cli/src/commands/brainstorm.rs
  • crates/refinery_core/src/brainstorm.rs
docs/plans/**

📄 CodeRabbit inference engine (CLAUDE.md)

docs/plans/**: Update plan headers with enhancement dates using format 'Enhanced: YYYY-MM-DD (via /deepen-plan)'
Update plan headers with review dates using format 'Reviewed: YYYY-MM-DD (via /$SKILL / $COMMAND)'
Update plan headers with completion dates using format 'Completed: YYYY-MM-DD'
Add addendums to plans using format 'Addendum: YYYY-MM-DD — description of what was added and why'
Create a dedicated plan when picking up a milestone from a roadmap or general plan if the milestone does not have one

Files:

  • docs/plans/2026-05-23-001-research-brainstorm-strategy-benchmarks-plan.md
docs/HANDOFF.md

📄 CodeRabbit inference engine (CLAUDE.md)

Update docs/HANDOFF.md before compaction or at session end with project state, architecture gotchas, open work, and review process

Files:

  • docs/HANDOFF.md
🔇 Additional comments (19)
crates/refinery_core/src/brainstorm.rs (13)

137-146: LGTM!


282-289: LGTM!


319-325: LGTM!


327-336: LGTM!


338-367: LGTM!


369-410: LGTM!


412-423: LGTM!


662-702: LGTM!


864-912: LGTM!


1062-1113: LGTM!


1352-1378: LGTM!


1439-1566: LGTM!


1881-1942: LGTM!

crates/refinery_cli/src/commands/brainstorm.rs (2)

77-87: LGTM!


383-392: LGTM!

docs/HANDOFF.md (1)

5-5: LGTM!

Also applies to: 48-48, 62-65, 97-151, 158-159

docs/brainstorms/2026-06-12-brainstorm-l3-parser-validation.md (1)

1-99: LGTM!

docs/plans/2026-05-23-001-research-brainstorm-strategy-benchmarks-plan.md (1)

19-20: LGTM!

Also applies to: 183-183

todos/013-brainstorm-strategy-benchmarks.md (1)

7-7: LGTM!

Also applies to: 107-111

@El-Fitz

El-Fitz commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

Addressed CodeRabbit nitpick in 5d51dce by changing the bounded preview test to assert preview.chars().count() instead of byte length.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5d51dce4f3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +358 to +363
if let Some((start, end)) = number_spans
.iter()
.copied()
.find(|(start, _)| *start >= score_idx)
{
return trimmed[start..end].parse::<f64>().ok();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Skip scale bounds when parsing labeled score text

When the score string has a score label and a scale but no colon before the actual value, e.g. "Score (1-10) 8" or an incomplete "Score (1-10)", this fallback returns the first numeric span after score, so the scale minimum 1 passes the later 1-10 range check and is recorded as a real evaluation score. Fresh evidence since the earlier comment is that the current colon-handling fix still falls into this no-colon branch, silently corrupting brainstorm scores instead of using the trailing value or rejecting the response.

Useful? React with 👍 / 👎.

@El-Fitz El-Fitz added this pull request to the merge queue Jun 17, 2026
Merged via the queue into main with commit 8e89266 Jun 17, 2026
4 of 5 checks passed
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