Skip to content

feat: add report turn navigator and restore standards column - #230

Merged
arunSunnyKVS merged 1 commit into
KeyValueSoftwareSystems:masterfrom
jithin23-kv:feat/report-turn-navigator
Aug 3, 2026
Merged

feat: add report turn navigator and restore standards column#230
arunSunnyKVS merged 1 commit into
KeyValueSoftwareSystems:masterfrom
jithin23-kv:feat/report-turn-navigator

Conversation

@jithin23-kv

@jithin23-kv jithin23-kv commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Problem

The report's "View more details" transcript had no way to jump to a specific turn on long multi-turn attacks. The Executive Summary risk pill had no explanation of how it's calculated. The evaluator standards mapping (OWASP/ATLAS/NIST/EU AI Act) had been dropped from the per-test detail cards during an earlier header redesign. Reports using the openai-compatible provider showed a redundant model label (e.g. openai-compatible/deepseek/deepseek-chat).

Solution

  • Added a left-side turn navigator rail in the transcript view: click a turn number to jump to it, and the active step highlights via scroll-spy as you scroll.
  • The turn list now scrolls inside its own bounded panel instead of the whole page (falls back to full, unscrolled content for print/PDF).
  • Removed the duplicated inline "Attacker | Turn N" / "Agent | Turn N" labels in favor of a single "Turn N" heading per turn.
  • Kept the existing auto-scroll-to-first-flagged-turn behavior working inside the new scrollable panel.
  • Added a hover tooltip to the risk pill explaining it's calculated from default internal thresholds.
  • Restored the Standards column (OWASP/ATLAS/NIST/EU AI Act mappings) next to Confidence in each per-test card.
  • modelLabel() now drops the openai-compatible prefix and shows just the model name, since it's a generic custom-baseURL wrapper, not a real vendor identity.

Changes

  • core/src/report/render.ts — turn navigator rail, turn heading, scrollable transcript panel + scroll-spy, risk-pill tooltip, standards column
  • core/src/execute/aggregate.tsmodelLabel() openai-compatible handling
  • core/tests/orchestrator.equivalence.test.ts — new test for openai-compatible model label

Issue

N/A

How to test

  1. npm run build
  2. Generate a report (opfor run --config <any config>), or re-render an existing .opfor/reports/*/*-report.json through renderReport()
  3. Open the generated report HTML
  4. In Executive Summary, hover the risk pill (e.g. "Low Risk") — tooltip should read "Indicates the overall risk status calculated from default internal thresholds"
  5. Open "View more details" on any multi-turn evaluator result — confirm the left turn rail appears, clicking a number scrolls to that turn, and scrolling within the transcript panel updates the active step
  6. If any turn is judge-flagged (failingTurns), opening the card should auto-scroll to it
  7. Confirm the Standards column (e.g. owasp-llm: LLM01, atlas: AML.T0051) appears next to Confidence in each per-test card
  8. Run a scan with provider: "openai-compatible" and confirm the Attacker/Judge Model fields show just the model name, not openai-compatible/<model>

Screenshots

N/A — run locally to view, or see the attached preview report

Summary by CodeRabbit

  • New Features
    • Improved multi-turn transcript navigation with structured turn headings, sticky navigation, active-turn tracking, click-to-scroll links, and automatic scrolling to flagged turns.
    • Evaluator standards are now displayed in result metadata and detail cards.
    • Risk badges include explanatory information on hover.
  • Improvements
    • Simplified model labels for OpenAI-compatible providers while preserving other provider formats.
    • Updated transcript layouts for mobile and print viewing.

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The change formats openai-compatible model labels and expands report rendering with evaluator standards, descriptive risk metadata, and navigable multi-turn transcripts.

Changes

Model label formatting

Layer / File(s) Summary
Model label formatting and coverage
core/src/execute/aggregate.ts, core/tests/orchestrator.equivalence.test.ts
modelLabel omits the openai-compatible provider prefix. Tests cover attacker, fallback judge, and explicitly configured judge labels.

Report rendering updates

Layer / File(s) Summary
Evaluator metadata and risk descriptions
core/src/report/render.ts
Result details render formatted evaluator standards beside confidence metadata. Risk badges include explanatory titles.
Structured transcript navigation
core/src/report/render.ts
Multi-turn transcripts use deterministic anchors, structured role headings, a navigation rail, active-turn tracking, flagged-turn scrolling, and responsive print and mobile styles.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant TurnNavigationRail
  participant TranscriptContent
  participant IntersectionObserver
  User->>TurnNavigationRail: Click a turn
  TurnNavigationRail->>TranscriptContent: Scroll to the turn anchor
  IntersectionObserver->>TranscriptContent: Observe the visible turn
  TranscriptContent-->>TurnNavigationRail: Update the active turn
Loading

Possibly related PRs

Suggested reviewers: arunsunnykvs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the primary report changes: the turn navigator and restored standards column.
Description check ✅ Passed The description follows the repository template and provides clear problem, solution, changes, testing, issue, and screenshot information.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@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 (2)
core/src/report/render.ts (2)

760-783: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding tests for the new pure rendering helpers.

turnHeading, roleLabel, renderTurn, and the standards column construction are pure string-building functions with clear inputs and outputs. The PR objectives mention new coverage for model-label formatting but no test file is included for this rendering layer. A small snapshot or string-assertion test for these functions would catch regressions in the transcript markup or standards formatting without much setup effort.

Do you want me to draft a starter test file for these functions?

🤖 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 `@core/src/report/render.ts` around lines 760 - 783, Add focused tests for the
pure rendering helpers turnHeading, roleLabel, and renderTurn, including
assertions for transcript markup and model-label formatting. Also test the
standards column construction around formatStandardsLabel, covering both
rendered standards output and its absent/empty case, using string assertions or
snapshots without changing production behavior.

617-676: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider extracting the shared prompt/tool-call markup between renderTurn and singleTurnTranscript.

renderTurn (Lines 635-676) and singleTurnTranscript (Lines 679-711) render nearly identical prompt and tool-call markup. This change widens the gap between them: renderTurn now adds a turn heading and an anchor id, while singleTurnTranscript keeps the old flat layout. A shared helper that accepts an optional id/heading would remove the duplication and prevent the two paths from drifting further out of sync on future edits (for example, a future style or label change applied to one function but missed in the other).

♻️ Sketch of a shared helper
-function renderTurn(turn: TurnViewModel, failingTurns: Set<number>, id: string): string {
-  const bubbleClass = failingTurns.has(turn.turnIndex)
-    ? "agent-bubble turn-highlight"
-    : "agent-bubble";
-  const heading = turnHeading(turn.turnIndex);
-  ...
-}
-
-function singleTurnTranscript(detail: DetailCard): string {
-  ...
-}
+function renderTurnBody(
+  detail: DetailCard,
+  bubbleClass: string,
+  heading: string
+): string {
+  if (detail.kind === "prompt") {
+    return `
+      ${heading}
+      <div class="turn-row attacker-row">
+        ${roleLabel(ATTACKER_ICON, "Attacker")}
+        <pre>${esc(truncate(detail.prompt, 8000))}</pre>
+      </div>
+      <div class="turn-row agent-row">
+        <div class="${bubbleClass}">
+          ${roleLabel(AGENT_ICON, "Agent")}
+          <pre>${esc(truncate(detail.response, 8000))}</pre>
+        </div>
+      </div>`;
+  }
+  // ... shared tool-call branch
+}
+
+function renderTurn(turn: TurnViewModel, failingTurns: Set<number>, id: string): string {
+  const bubbleClass = failingTurns.has(turn.turnIndex) ? "agent-bubble turn-highlight" : "agent-bubble";
+  return `<div class="turn" id="${id}">${renderTurnBody(turn.detail, bubbleClass, turnHeading(turn.turnIndex))}</div>`;
+}
+
+function singleTurnTranscript(detail: DetailCard): string {
+  return `<div class="turn">${renderTurnBody(detail, "agent-bubble", "")}</div>`;
+}

Also applies to: 679-711

🤖 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 `@core/src/report/render.ts` around lines 617 - 676, Extract the duplicated
prompt/tool-call transcript markup from renderTurn and singleTurnTranscript into
a shared helper, such as a helper accepting the turn, failing-turn styling, and
optional heading/id inputs. Update both callers to use it, preserving
renderTurn’s turn heading and anchor id while keeping singleTurnTranscript’s
flat layout, and retain the existing escaping, truncation, labels, and error
rendering behavior.
🤖 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 `@core/src/report/render.ts`:
- Around line 760-783: Add focused tests for the pure rendering helpers
turnHeading, roleLabel, and renderTurn, including assertions for transcript
markup and model-label formatting. Also test the standards column construction
around formatStandardsLabel, covering both rendered standards output and its
absent/empty case, using string assertions or snapshots without changing
production behavior.
- Around line 617-676: Extract the duplicated prompt/tool-call transcript markup
from renderTurn and singleTurnTranscript into a shared helper, such as a helper
accepting the turn, failing-turn styling, and optional heading/id inputs. Update
both callers to use it, preserving renderTurn’s turn heading and anchor id while
keeping singleTurnTranscript’s flat layout, and retain the existing escaping,
truncation, labels, and error rendering behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 16d16737-fbf4-4049-a326-9bd888ff7839

📥 Commits

Reviewing files that changed from the base of the PR and between 254cd24 and f9a2e6f.

📒 Files selected for processing (3)
  • core/src/execute/aggregate.ts
  • core/src/report/render.ts
  • core/tests/orchestrator.equivalence.test.ts

@arunSunnyKVS
arunSunnyKVS merged commit 04d0690 into KeyValueSoftwareSystems:master Aug 3, 2026
8 checks passed
@jithin23-kv
jithin23-kv deleted the feat/report-turn-navigator branch August 3, 2026 11:06
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.

2 participants