Skip to content

feat(dashboard): surface system prompt in turn transcript#469

Merged
dcramer merged 5 commits into
mainfrom
feat/system-prompt-in-transcript
Jun 1, 2026
Merged

feat(dashboard): surface system prompt in turn transcript#469
dcramer merged 5 commits into
mainfrom
feat/system-prompt-in-transcript

Conversation

@sentry-junior
Copy link
Copy Markdown
Contributor

@sentry-junior sentry-junior Bot commented May 31, 2026

Prepend the system prompt as a synthetic system-role message to each turn's transcript in the dashboard. The message is assembled from buildSystemPrompt() at read time — no Redis storage changes, no piMessages bloat.

Reporting layer injection

readConversation now prepends a systemPromptMessage() to each exposed turn transcript. It is excluded from transcriptMessageCount (which already only counts user/assistant roles), so all existing stats stay correct.

UI: collapsed by default

New SystemMessageView component renders system messages behind a <details> disclosure, closed by default. The summary shows the role label + char count so the transcript stays scannable. This mirrors the existing ThinkingPartView pattern.

Forward-compatible placeholder

When the transcript source moves to traces the system message will arrive as a span attribute instead of a synthetic injection — this change adds nothing that would conflict with that migration.


View Session in Sentry

Prepend a synthetic system-role message to each turn's transcript at the
reporting layer so the dashboard can show the exact prompt the model received.
The message is assembled from buildSystemPrompt() at read time — no storage
changes needed — and is intentionally skipped from transcriptMessageCount.

In the UI, system messages render collapsed by default (same UX pattern as
thinking blocks) with a char count in the summary, so the transcript stays
scannable without the full prompt taking over the view.

This is a forward-compatible placeholder: when the transcript source moves to
traces the system message will arrive as a span attribute instead of a
synthetic injection.

Co-Authored-By: claude-opus-4-5 <noreply@anthropic.com>

Co-authored-by: David Cramer <david@sentry.io>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 31, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
junior-docs Ready Ready Preview, Comment May 31, 2026 11:16pm

Request Review

Co-Authored-By: claude-opus-4-5 <noreply@anthropic.com>

Co-authored-by: David Cramer <david@sentry.io>
…ntent

Replace the plain HighlightedCode fallback with the full groupTranscriptParts
→ TranscriptPartView pipeline so system message content goes through
TranscriptText → parseMarkdownBlocks → XML detection → StructuredMarkup.
This gives the system prompt the same collapsible XML tag renderer used for
user/tool messages that contain runtime context blocks.

Also remove the redundant TranscriptMessageShell wrapper: transcriptMessageClass
is now applied directly to the <details> element so the amber styling and the
disclosure are a single DOM node instead of two nested containers.

Co-Authored-By: claude-opus-4-5 <noreply@anthropic.com>

Co-authored-by: U039RR91S <david@sentry.io>
- Use StructuredMarkup directly with language:"xml" so the system prompt
  renders through the collapsible XML tree renderer instead of HighlightedCode.
  detectLanguage returns "markdown" for the system prompt (starts with plain
  text, not "<"), so bypassing it is the right call here.
- Replace rawText.length / "chars" with TextEncoder byte count + formatBytes,
  consistent with how the rest of the dashboard shows message sizes.

Co-Authored-By: claude-opus-4-5 <noreply@anthropic.com>

Co-authored-by: David Cramer <david@sentry.io>
detectLanguage was returning "markdown" for the system prompt because the
markdown heuristic (## headings, - bullets) fired before the XML check, and
the XML check required text to start with "<". The system prompt starts with
plain text but contains block-level XML elements.

Fix: add a block-level XML check before the markdown heuristic that requires
a matched open+close tag pair on their own lines. This makes the system prompt
naturally detected as "xml" without special-casing in the component layer.

With the detection fixed, SystemMessageView can use the same
groupTranscriptParts → TranscriptPartView → TranscriptText pipeline as every
other message kind, removing the direct StructuredMarkup bypass. The StructuredMarkup
import is also removed from TranscriptTurn.tsx.

Tests added for the new detection behaviour:
- mixed prose + block XML detected as xml (system prompt shape)
- unclosed block tag not detected as xml
- normal markdown without XML stays markdown

Co-Authored-By: claude-opus-4-5 <noreply@anthropic.com>
@dcramer dcramer marked this pull request as ready for review June 1, 2026 08:06
@dcramer dcramer merged commit d173314 into main Jun 1, 2026
16 checks passed
@dcramer dcramer deleted the feat/system-prompt-in-transcript branch June 1, 2026 08:07
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c05050a. Configure here.

const transcript = canExposeTranscript ? normalizedTranscript : [];
const transcript = canExposeTranscript
? [systemPromptMessage(), ...normalizedTranscript]
: [];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

System prompt skews trace fallback

Medium Severity

When summary.traceId and sessionRecord.traceId are missing, traceIdFromTranscript runs on the exposed transcript that now starts with the synthetic system message. That helper returns the first trace_id-like hex match in message text, so prompt content from buildSystemPrompt() is scanned before user or assistant messages and can supply a false ID or hide the real one in the turn log.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c05050a. Configure here.

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