Debate statements displayed as long paragraphs instead of bullet points in UI#352
Debate statements displayed as long paragraphs instead of bullet points in UI#352Naman-kr404 wants to merge 5 commits intoAOSSIE-Org:mainfrom
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe PR updates debate statement rendering to display as bullet points instead of prose, modifies the backend prompt to request bullet-point format, and adds defensive validation and null-safety handling to judgment popup components. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~35 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@backend/services/debatevsbot.go`:
- Around line 172-185: The hard-coded "Maximum 5 bullets" in pointInstruction
causes cross-phase semantics issues; change the instruction generation to be
phase-aware by removing the global limit from pointInstruction and instead
generate or append a scoped bullet-count constraint only when appropriate (e.g.,
pass a maxBullets parameter or a boolean allowMultipleBullets into the function
that builds pointInstruction and similar strings at the other occurrence around
lines 251-283), and for the question/answer phase (the
single-question/single-answer flow driven by the frontend) ensure the generator
does not enforce multiple bullets—use a nil/0 or explicit maxBullets=1 to
enforce one bullet per turn. Ensure you update all occurrences (pointInstruction
and the other instruction string) to use this parameterized builder so phase
semantics remain consistent.
In `@frontend/src/Pages/DebateRoom.tsx`:
- Around line 682-689: The renderer currently treats any occurrence of "- "
inside msg.text as bullets; change it to detect bullets only at line starts by
checking msg.text.split('\n') for lines whose trimmed start begins with "- ".
When rendering, split only on newline boundaries, filter lines that start with a
leading hyphen (use trimmed start detection), strip the leading "- " from each
bullet line (e.g., remove /^\s*-\s+/), and render those as <li> items; keep the
existing whitespace-pre-line fallback when no line-start bullets are found.
Reference: msg.text in DebateRoom.tsx and the list rendering branch.
- Around line 4-5: The page imports Textarea but still renders <Input> at render
time, causing Input to be undefined; restore the original import by uncommenting
the Input import or replace the <Input> usage with <Textarea> consistently.
Locate the import line that currently comments out Input and either re-enable
"Input" in the import statement or update the JSX where Input is used (search
for "Input" and the render around line where <Input> appears) to use Textarea
props/handlers instead; ensure the component name and any props (value,
onChange, placeholder, className) match the chosen component to avoid prop
mismatches.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 3749fc52-56da-4604-8e7a-790207082101
⛔ Files ignored due to path filters (1)
frontend/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (3)
backend/services/debatevsbot.gofrontend/package.jsonfrontend/src/Pages/DebateRoom.tsx
backend/services/debatevsbot.go
Outdated
| pointInstruction := ` | ||
| STRICT OUTPUT FORMAT: | ||
| - Write ONLY bullet points. | ||
| - Each bullet point MUST start with "- ". | ||
| - Each bullet MUST be on a NEW LINE. | ||
| - Do NOT place multiple bullets on the same line. | ||
| - Maximum 5 bullets. | ||
|
|
||
| Correct format example: | ||
| - First argument supporting your stance | ||
| - Second argument responding to the opponent | ||
| - Third argument with reasoning | ||
| - Fourth argument strengthening your case | ||
| ` |
There was a problem hiding this comment.
Scope the bullet-count rule by debate phase.
Applying Maximum 5 bullets to every response changes cross-examination semantics: the bot is now allowed to ask several questions in one "question" turn or spread one answer across several bullets. frontend/src/Pages/DebateRoom.tsx Lines 517-527 still drives that phase as one question / one answer per turn, so this can make the next turn ambiguous.
💡 Suggested fix
pointInstruction := `
STRICT OUTPUT FORMAT:
- Write ONLY bullet points.
- Each bullet point MUST start with "- ".
- Each bullet MUST be on a NEW LINE.
- Do NOT place multiple bullets on the same line.
- Maximum 5 bullets.
...
`
+
+singleBulletInstruction := `
+STRICT OUTPUT FORMAT:
+- Write ONLY one bullet point.
+- The bullet point MUST start with "- ".
+- Do NOT add extra prose before or after it.
+`
...
switch strings.ToLower(currentPhase) {
case "opening statement":
phaseInstruction = "This is the Opening Statement phase..."
case "cross examination":
phaseInstruction = "This is the Cross Examination phase..."
...
}
+
+formatInstruction := pointInstruction
+if strings.EqualFold(currentPhase, "Cross Examination") {
+ formatInstruction = singleBulletInstruction
+}
return fmt.Sprintf(
`You are %s, a %s-level debate bot arguing %s the topic "%s".
...
%s
Based on the debate transcript below, continue the discussion in the %s phase by responding directly to the user’s message.
...
`,
...
- pointInstruction,
+ formatInstruction,
...
)Also applies to: 251-283
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@backend/services/debatevsbot.go` around lines 172 - 185, The hard-coded
"Maximum 5 bullets" in pointInstruction causes cross-phase semantics issues;
change the instruction generation to be phase-aware by removing the global limit
from pointInstruction and instead generate or append a scoped bullet-count
constraint only when appropriate (e.g., pass a maxBullets parameter or a boolean
allowMultipleBullets into the function that builds pointInstruction and similar
strings at the other occurrence around lines 251-283), and for the
question/answer phase (the single-question/single-answer flow driven by the
frontend) ensure the generator does not enforce multiple bullets—use a nil/0 or
explicit maxBullets=1 to enforce one bullet per turn. Ensure you update all
occurrences (pointInstruction and the other instruction string) to use this
parameterized builder so phase semantics remain consistent.
| {msg.text.includes("- ") ? ( | ||
| <ul className="list-disc pl-5 space-y-1"> | ||
| {msg.text.split(/\n|-\s+/).filter(Boolean).map((point, i) => ( | ||
| <li key={i}>{point.trim()}</li> | ||
| ))} | ||
| </ul> | ||
| ) : ( | ||
| <div className="whitespace-pre-line">{msg.text}</div> |
There was a problem hiding this comment.
Detect bullets only at line starts.
includes("- ") plus split(/\n|-\s+/) is too broad: a normal message like A - B will be rendered as a list, and bullet content that contains " - " will be split into extra <li> items. Because this renderer is shared for both user and bot messages, that will misformat regular debate text.
💡 Suggested fix
-{msg.text.includes("- ") ? (
- <ul className="list-disc pl-5 space-y-1">
- {msg.text.split(/\n|-\s+/).filter(Boolean).map((point, i) => (
- <li key={i}>{point.trim()}</li>
- ))}
- </ul>
-) : (
- <div className="whitespace-pre-line">{msg.text}</div>
-)}
+{(() => {
+ const lines = msg.text
+ .split("\n")
+ .map((line) => line.trim())
+ .filter(Boolean);
+
+ const bulletPoints = lines
+ .filter((line) => /^-\s+/.test(line))
+ .map((line) => line.replace(/^-\s+/, ""));
+
+ return bulletPoints.length > 0 && bulletPoints.length === lines.length ? (
+ <ul className="list-disc pl-5 space-y-1">
+ {bulletPoints.map((point, i) => (
+ <li key={i}>{point}</li>
+ ))}
+ </ul>
+ ) : (
+ <div className="whitespace-pre-line">{msg.text}</div>
+ );
+})()}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@frontend/src/Pages/DebateRoom.tsx` around lines 682 - 689, The renderer
currently treats any occurrence of "- " inside msg.text as bullets; change it to
detect bullets only at line starts by checking msg.text.split('\n') for lines
whose trimmed start begins with "- ". When rendering, split only on newline
boundaries, filter lines that start with a leading hyphen (use trimmed start
detection), strip the leading "- " from each bullet line (e.g., remove
/^\s*-\s+/), and render those as <li> items; keep the existing
whitespace-pre-line fallback when no line-start bullets are found. Reference:
msg.text in DebateRoom.tsx and the list rendering branch.
|
The bullet rendering improvement looks useful for readability. Since the frontend renderer already detects bullet structures, would it be safer to handle formatting entirely on the frontend instead of enforcing output structure in the prompt? |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@backend/services/debatevsbot.go`:
- Around line 172-185: The Opening Statement prompt currently comments out the
deterministic bullet template (pointInstruction) and injects a literal "// %s"
into prompts, causing the model to return paragraphs; restore the strict output
format by re-enabling the pointInstruction multi-line string (the commented
block) and use it when building the prompt instead of injecting "// %s" — update
the code paths that construct Opening Statement prompts (references:
pointInstruction, Opening Statement prompt construction in debatevsbot.go and
any places noted around lines ~172, ~203, ~220, ~260, ~279) so the prompt
concatenates or formats with pointInstruction to force "- " bullet lines rather
than leaving the template commented out or interpolated as a literal.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 8368e52f-5999-419d-b5bb-69f403f5e7b9
📒 Files selected for processing (2)
backend/services/debatevsbot.gofrontend/src/Pages/DebateRoom.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- frontend/src/Pages/DebateRoom.tsx
backend/services/debatevsbot.go
Outdated
| // pointInstruction := ` | ||
| // STRICT OUTPUT FORMAT: | ||
| // - Write ONLY bullet points. | ||
| // - Each bullet point MUST start with "- ". | ||
| // - Each bullet MUST be on a NEW LINE. | ||
| // - Do NOT place multiple bullets on the same line. | ||
| // - Maximum 5 bullets. | ||
|
|
||
| // Correct format example: | ||
| // - First argument supporting your stance | ||
| // - Second argument responding to the opponent | ||
| // - Third argument with reasoning | ||
| // - Fourth argument strengthening your case | ||
| // ` |
There was a problem hiding this comment.
Re-enable deterministic bullet formatting for Opening Statement; current prompt can regress to paragraph rendering.
frontend/src/Pages/DebateRoom.tsx (Lines 681-684) only renders list items when lines use - . Here, strict formatting is commented out and // %s is injected literally into prompts, so bullet structure is not reliably produced.
💡 Suggested fix
@@
- // pointInstruction := `
-// STRICT OUTPUT FORMAT:
-// - Write ONLY bullet points.
-// - Each bullet point MUST start with "- ".
-// - Each bullet MUST be on a NEW LINE.
-// - Do NOT place multiple bullets on the same line.
-// - Maximum 5 bullets.
-
-// Correct format example:
-// - First argument supporting your stance
-// - Second argument responding to the opponent
-// - Third argument with reasoning
-// - Fourth argument strengthening your case
-// `
+ pointInstruction := `
+STRICT OUTPUT FORMAT:
+- Write ONLY bullet points.
+- Each bullet point MUST start with "- ".
+- Each bullet MUST be on a NEW LINE.
+- Do NOT place multiple bullets on the same line.
+`
@@
%s
%s
-// %s
+%s
%s
@@
- // pointInstruction,
+ pointInstruction,
limitInstruction, baseInstruction,
@@
%s
-// %s
Based on the debate transcript below, continue the discussion in the %s phase by responding directly to the user’s message.
@@
- // pointInstruction,Also applies to: 203-205, 220-220, 260-260, 279-279
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@backend/services/debatevsbot.go` around lines 172 - 185, The Opening
Statement prompt currently comments out the deterministic bullet template
(pointInstruction) and injects a literal "// %s" into prompts, causing the model
to return paragraphs; restore the strict output format by re-enabling the
pointInstruction multi-line string (the commented block) and use it when
building the prompt instead of injecting "// %s" — update the code paths that
construct Opening Statement prompts (references: pointInstruction, Opening
Statement prompt construction in debatevsbot.go and any places noted around
lines ~172, ~203, ~220, ~260, ~279) so the prompt concatenates or formats with
pointInstruction to force "- " bullet lines rather than leaving the template
commented out or interpolated as a literal.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
frontend/src/Pages/DebateRoom.tsx (1)
725-732:⚠️ Potential issue | 🟠 MajorOnly render a list when every non-empty line is actually a bullet.
This still triggers on any
"- "substring, so normal text likeA - Bor mixed prose plus bullets gets split into bogus<li>items. Because this renderer is shared across all phases and both senders, it will misformat regular debate text.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/Pages/DebateRoom.tsx` around lines 725 - 732, The current renderer treats any "- " substring as a list; update the conditional that decides between rendering a list vs plain text (where msg.text is used) to only render the <ul> when every non-empty line in msg.text actually starts with a bullet marker (e.g., matches /^\s*-\s+/). To fix, split msg.text by newlines, filter out empty lines, check that every remaining line matches the bullet-prefix regex, and only then render the list (trim and strip the leading "- " when mapping to <li>); otherwise render the plain whitespace-pre-line text as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@frontend/src/components/JudgementPopup.tsx`:
- Around line 137-142: The current check for isUserBotFormat uses "'user' in
openingStatement" which can throw if openingStatement is a primitive (e.g.,
string); update the guard to ensure openingStatement is an object before using
the in operator (e.g., verify typeof openingStatement === 'object' &&
openingStatement !== null and optionally !Array.isArray(openingStatement)) and
then test "'user' in openingStatement"; apply this change where openingStatement
and isUserBotFormat are defined to safely handle malformed
JudgmentDataUserBot/JudgmentDataForAgainst payloads.
In `@frontend/src/Pages/DebateRoom.tsx`:
- Around line 633-645: The fallback verdict object creates a false-positive
winner by setting verdict.winner to "Unknown"; update the fallback used where
judgment is parsed (the verdict object built from judgment) to set winner to an
empty string "" instead, and make the subsequent error-fallback logic that
renders JudgementPopup rely on an empty winner to indicate "no result" (keep
references to verdict.winner, judgment, and the JudgementPopup consumer in mind
when changing the fallback).
---
Duplicate comments:
In `@frontend/src/Pages/DebateRoom.tsx`:
- Around line 725-732: The current renderer treats any "- " substring as a list;
update the conditional that decides between rendering a list vs plain text
(where msg.text is used) to only render the <ul> when every non-empty line in
msg.text actually starts with a bullet marker (e.g., matches /^\s*-\s+/). To
fix, split msg.text by newlines, filter out empty lines, check that every
remaining line matches the bullet-prefix regex, and only then render the list
(trim and strip the leading "- " when mapping to <li>); otherwise render the
plain whitespace-pre-line text as before.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e4134f5d-65d5-4be3-b3a8-f852a4a02002
📒 Files selected for processing (3)
frontend/src/Pages/DebateRoom.tsxfrontend/src/components/JudgementPopup.tsxfrontend/tsconfig.app.tsbuildinfo
✅ Files skipped from review due to trivial changes (1)
- frontend/tsconfig.app.tsbuildinfo
| // Some judge responses can be partial/malformed; keep rendering with safe fallbacks | ||
| const openingStatement = (judgment as Partial<JudgmentDataUserBot>).opening_statement as | ||
| | JudgmentDataUserBot['opening_statement'] | ||
| | JudgmentDataForAgainst['opening_statement'] | ||
| | undefined; | ||
| const isUserBotFormat = Boolean(openingStatement && 'user' in openingStatement); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's find and examine the specific file and lines in question
find . -name "JudgementPopup.tsx" -type fRepository: AOSSIE-Org/DebateAI
Length of output: 107
🏁 Script executed:
# Once found, read the relevant section around lines 137-142
cat -n frontend/src/components/JudgementPopup.tsx | sed -n '130,150p'Repository: AOSSIE-Org/DebateAI
Length of output: 1171
🏁 Script executed:
# Also check the type definitions to understand what opening_statement can be
rg "opening_statement" --type ts --type tsx -B 2 -A 2Repository: AOSSIE-Org/DebateAI
Length of output: 90
🏁 Script executed:
# Check the JudgmentDataUserBot and JudgmentDataForAgainst types to understand the structure
ast-grep --pattern 'type JudgmentDataUserBot = $_'Repository: AOSSIE-Org/DebateAI
Length of output: 1846
🏁 Script executed:
ast-grep --pattern 'type JudgmentDataForAgainst = $_'Repository: AOSSIE-Org/DebateAI
Length of output: 1896
Guard the in check before probing malformed payloads.
On line 142, 'user' in openingStatement will throw a TypeError if opening_statement is a string, number, or other primitive instead of an object. The && operator only guards against falsy values, so truthy primitives like non-empty strings will pass through and crash on the in operator. This defeats the stated goal of safe fallbacks for partial/malformed payloads.
Suggested fix
- const isUserBotFormat = Boolean(openingStatement && 'user' in openingStatement);
+ const isUserBotFormat =
+ typeof openingStatement === 'object' &&
+ openingStatement !== null &&
+ 'user' in openingStatement;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Some judge responses can be partial/malformed; keep rendering with safe fallbacks | |
| const openingStatement = (judgment as Partial<JudgmentDataUserBot>).opening_statement as | |
| | JudgmentDataUserBot['opening_statement'] | |
| | JudgmentDataForAgainst['opening_statement'] | |
| | undefined; | |
| const isUserBotFormat = Boolean(openingStatement && 'user' in openingStatement); | |
| // Some judge responses can be partial/malformed; keep rendering with safe fallbacks | |
| const openingStatement = (judgment as Partial<JudgmentDataUserBot>).opening_statement as | |
| | JudgmentDataUserBot['opening_statement'] | |
| | JudgmentDataForAgainst['opening_statement'] | |
| | undefined; | |
| const isUserBotFormat = | |
| typeof openingStatement === 'object' && | |
| openingStatement !== null && | |
| 'user' in openingStatement; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@frontend/src/components/JudgementPopup.tsx` around lines 137 - 142, The
current check for isUserBotFormat uses "'user' in openingStatement" which can
throw if openingStatement is a primitive (e.g., string); update the guard to
ensure openingStatement is an object before using the in operator (e.g., verify
typeof openingStatement === 'object' && openingStatement !== null and optionally
!Array.isArray(openingStatement)) and then test "'user' in openingStatement";
apply this change where openingStatement and isUserBotFormat are defined to
safely handle malformed JudgmentDataUserBot/JudgmentDataForAgainst payloads.
| verdict: { | ||
| winner: "Unknown", | ||
| reason: | ||
| typeof (judgment as any)?.verdict?.reason === "string" | ||
| ? (judgment as any).verdict.reason | ||
| : "Judgment data missing/invalid.", | ||
| congratulations: | ||
| typeof (judgment as any)?.verdict?.congratulations === "string" | ||
| ? (judgment as any).verdict.congratulations | ||
| : "", | ||
| opponent_analysis: | ||
| typeof (judgment as any)?.verdict?.opponent_analysis === "string" | ||
| ? (judgment as any).verdict.opponent_analysis |
There was a problem hiding this comment.
Don't fabricate a winner in the invalid-judgment fallback.
Line 634 sets winner: "Unknown". JudgementPopup treats any non-empty verdict.winner as a real result, so malformed payloads will currently surface as Unknown Wins! instead of the intended unavailable/default state. Leave winner empty here, and align the error fallback below for the same reason.
💡 Minimal fix
- winner: "Unknown",
+ winner: "",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| verdict: { | |
| winner: "Unknown", | |
| reason: | |
| typeof (judgment as any)?.verdict?.reason === "string" | |
| ? (judgment as any).verdict.reason | |
| : "Judgment data missing/invalid.", | |
| congratulations: | |
| typeof (judgment as any)?.verdict?.congratulations === "string" | |
| ? (judgment as any).verdict.congratulations | |
| : "", | |
| opponent_analysis: | |
| typeof (judgment as any)?.verdict?.opponent_analysis === "string" | |
| ? (judgment as any).verdict.opponent_analysis | |
| verdict: { | |
| winner: "", | |
| reason: | |
| typeof (judgment as any)?.verdict?.reason === "string" | |
| ? (judgment as any).verdict.reason | |
| : "Judgment data missing/invalid.", | |
| congratulations: | |
| typeof (judgment as any)?.verdict?.congratulations === "string" | |
| ? (judgment as any).verdict.congratulations | |
| : "", | |
| opponent_analysis: | |
| typeof (judgment as any)?.verdict?.opponent_analysis === "string" | |
| ? (judgment as any).verdict.opponent_analysis |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@frontend/src/Pages/DebateRoom.tsx` around lines 633 - 645, The fallback
verdict object creates a false-positive winner by setting verdict.winner to
"Unknown"; update the fallback used where judgment is parsed (the verdict object
built from judgment) to set winner to an empty string "" instead, and make the
subsequent error-fallback logic that renders JudgementPopup rely on an empty
winner to indicate "no result" (keep references to verdict.winner, judgment, and
the JudgementPopup consumer in mind when changing the fallback).
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
frontend/src/components/JudgementPopup.tsx (1)
137-142:⚠️ Potential issue | 🔴 CriticalGuard the
incheck before probing malformed payloads.If
opening_statementis a truthy primitive from a malformed judge response,'user' in openingStatementthrows before the fallback logic runs. That turns the new defensive path back into a render crash.💡 Minimal fix
- const isUserBotFormat = Boolean(openingStatement && 'user' in openingStatement); + const isUserBotFormat = + typeof openingStatement === 'object' && + openingStatement !== null && + !Array.isArray(openingStatement) && + 'user' in openingStatement;In JavaScript/TypeScript, does using the `in` operator on a primitive value such as a string or number throw a TypeError? Please cite MDN or the ECMAScript spec.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/components/JudgementPopup.tsx` around lines 137 - 142, The current runtime check uses "'user' in openingStatement" which will throw if openingStatement is a primitive; change the isUserBotFormat computation to first ensure openingStatement is a non-null object (e.g., typeof openingStatement === 'object' && openingStatement !== null) before using the in operator, so update the isUserBotFormat expression that references openingStatement (and types JudgmentDataUserBot / opening_statement) to perform this guarded check and keep existing fallbacks intact.frontend/src/Pages/DebateRoom.tsx (1)
725-732:⚠️ Potential issue | 🟠 MajorOnly parse bullets from line-start markers.
includes("- ")plussplit(/\n|-\s+/)is still too broad: a normal turn likeA - Bor any sentence containing" - "will be broken into multiple<li>items. Because this renderer is shared by both user and bot messages, regular questions/answers can be reformatted as lists by accident.💡 Minimal fix
- {msg.text.includes("- ") ? ( - <ul className="list-disc pl-5 space-y-4"> - {msg.text.split(/\n|-\s+/).filter(Boolean).map((point, i) => ( - <li key={i}>{point.trim()}</li> - ))} - </ul> -) : ( - <div className="whitespace-pre-line">{msg.text}</div> -)} + {(() => { + const lines = msg.text + .split("\n") + .map((line) => line.trim()) + .filter(Boolean); + + const bulletPoints = lines + .filter((line) => /^-\s+/.test(line)) + .map((line) => line.replace(/^-\s+/, "")); + + return bulletPoints.length > 0 && + bulletPoints.length === lines.length ? ( + <ul className="list-disc pl-5 space-y-4"> + {bulletPoints.map((point, i) => ( + <li key={i}>{point}</li> + ))} + </ul> + ) : ( + <div className="whitespace-pre-line">{msg.text}</div> + ); + })()}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/Pages/DebateRoom.tsx` around lines 725 - 732, The current check msg.text.includes("- ") and split(/\n|-\s+/) incorrectly breaks inline " - " into bullets; instead detect bullet lists only when lines start with a dash and split by lines. Replace the condition with a multiline-start test (e.g. /^\s*-\s+/m.test(msg.text)) and change the splitting logic to split on '\n', filter lines that match /^\s*-\s+/, and strip the leading dash/whitespace when producing list items (update the rendering block around msg.text in DebateRoom.tsx accordingly).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@frontend/src/components/JudgementPopup.tsx`:
- Around line 709-713: The header currently appends "Wins!" to any non-empty
verdict.winner, causing "Draw" to render as "Draw Wins!"; update the render
logic in JudgementPopup.tsx (the expression using (judgment as
any)?.verdict?.winner) to branch: if verdict.winner === 'Draw' render a plain
"Draw" (or a suitable draw label), otherwise render `${winner} Wins!`, ensuring
you reference the same judgment.verdict.winner field and keep null/undefined
handled as the existing 'Result unavailable' fallback.
---
Duplicate comments:
In `@frontend/src/components/JudgementPopup.tsx`:
- Around line 137-142: The current runtime check uses "'user' in
openingStatement" which will throw if openingStatement is a primitive; change
the isUserBotFormat computation to first ensure openingStatement is a non-null
object (e.g., typeof openingStatement === 'object' && openingStatement !== null)
before using the in operator, so update the isUserBotFormat expression that
references openingStatement (and types JudgmentDataUserBot / opening_statement)
to perform this guarded check and keep existing fallbacks intact.
In `@frontend/src/Pages/DebateRoom.tsx`:
- Around line 725-732: The current check msg.text.includes("- ") and
split(/\n|-\s+/) incorrectly breaks inline " - " into bullets; instead detect
bullet lists only when lines start with a dash and split by lines. Replace the
condition with a multiline-start test (e.g. /^\s*-\s+/m.test(msg.text)) and
change the splitting logic to split on '\n', filter lines that match /^\s*-\s+/,
and strip the leading dash/whitespace when producing list items (update the
rendering block around msg.text in DebateRoom.tsx accordingly).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 56866d0f-e016-4c91-83d5-04a9c0d9e6d4
⛔ Files ignored due to path filters (1)
frontend/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (4)
backend/services/debatevsbot.gofrontend/package.jsonfrontend/src/Pages/DebateRoom.tsxfrontend/src/components/JudgementPopup.tsx
✅ Files skipped from review due to trivial changes (2)
- backend/services/debatevsbot.go
- frontend/package.json
| <p className='mt-4 text-3xl font-bold'> | ||
| {judgment.verdict.winner} Wins! | ||
| {(judgment as any)?.verdict?.winner | ||
| ? `${(judgment as any).verdict.winner} Wins!` | ||
| : 'Result unavailable'} | ||
| </p> |
There was a problem hiding this comment.
Handle draw verdicts separately.
backend/controllers/debatevsbot_controller.go:228-250 already treats "Draw" as a real outcome, but this header appends Wins! to any non-empty winner. A tie will therefore render as Draw Wins!, which is incorrect.
💡 Minimal fix
- <p className='mt-4 text-3xl font-bold'>
- {(judgment as any)?.verdict?.winner
- ? `${(judgment as any).verdict.winner} Wins!`
- : 'Result unavailable'}
- </p>
+ {(() => {
+ const winner =
+ typeof (judgment as any)?.verdict?.winner === 'string'
+ ? (judgment as any).verdict.winner.trim()
+ : '';
+ const normalizedWinner = winner.toLowerCase();
+ const allowedWinners = new Set([
+ 'user',
+ 'bot',
+ 'for',
+ 'against',
+ player1Name.toLowerCase(),
+ player2Name.toLowerCase(),
+ ]);
+ const verdictTitle =
+ normalizedWinner === 'draw'
+ ? 'Draw'
+ : allowedWinners.has(normalizedWinner)
+ ? `${winner} Wins!`
+ : 'Result unavailable';
+
+ return <p className='mt-4 text-3xl font-bold'>{verdictTitle}</p>;
+ })()}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <p className='mt-4 text-3xl font-bold'> | |
| {judgment.verdict.winner} Wins! | |
| {(judgment as any)?.verdict?.winner | |
| ? `${(judgment as any).verdict.winner} Wins!` | |
| : 'Result unavailable'} | |
| </p> | |
| {(() => { | |
| const winner = | |
| typeof (judgment as any)?.verdict?.winner === 'string' | |
| ? (judgment as any).verdict.winner.trim() | |
| : ''; | |
| const normalizedWinner = winner.toLowerCase(); | |
| const allowedWinners = new Set([ | |
| 'user', | |
| 'bot', | |
| 'for', | |
| 'against', | |
| player1Name.toLowerCase(), | |
| player2Name.toLowerCase(), | |
| ]); | |
| const verdictTitle = | |
| normalizedWinner === 'draw' | |
| ? 'Draw' | |
| : allowedWinners.has(normalizedWinner) | |
| ? `${winner} Wins!` | |
| : 'Result unavailable'; | |
| return <p className='mt-4 text-3xl font-bold'>{verdictTitle}</p>; | |
| })()} |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@frontend/src/components/JudgementPopup.tsx` around lines 709 - 713, The
header currently appends "Wins!" to any non-empty verdict.winner, causing "Draw"
to render as "Draw Wins!"; update the render logic in JudgementPopup.tsx (the
expression using (judgment as any)?.verdict?.winner) to branch: if
verdict.winner === 'Draw' render a plain "Draw" (or a suitable draw label),
otherwise render `${winner} Wins!`, ensuring you reference the same
judgment.verdict.winner field and keep null/undefined handled as the existing
'Result unavailable' fallback.
Addressed Issues:
Fixes #351
Screenshots/Recordings:
Before

Displaying these arguments in paragraph format makes the debate harder to read and follow, especially when multiple arguments are presented in a single response.
After

Summary by CodeRabbit
New Features
Bug Fixes