Skip to content

feat(#241): render thinking, result, and system events in progress stream#270

Open
fullsend-ai-coder[bot] wants to merge 2 commits into
mainfrom
agent/241-render-event-stream-progress
Open

feat(#241): render thinking, result, and system events in progress stream#270
fullsend-ai-coder[bot] wants to merge 2 commits into
mainfrom
agent/241-render-event-stream-progress

Conversation

@fullsend-ai-coder

Copy link
Copy Markdown

Extend the progress parser to handle additional Claude Code stream-json event types beyond tool_use. The parser now emits progress for thinking content blocks (safe indicator, no content leaked), result events (completion status with subtype for errors), and system events (session initialization). Error results use ::warning:: in CI and StepWarn formatting. Sensitive data from thinking blocks and result messages is never surfaced.


Closes #241

Post-script verification

  • Branch is not main/master (agent/241-render-event-stream-progress)
  • Secret scan passed (gitleaks — c776c248ac9a91f10998ca7107e974a6c9d76514..HEAD)
  • Pre-commit hooks passed (authoritative run on runner)
  • Tests ran inside sandbox

…ream

Extend the progress parser to handle additional Claude Code stream-json
event types beyond tool_use. The parser now emits progress for thinking
content blocks (safe indicator, no content leaked), result events
(completion status with subtype for errors), and system events (session
initialization). Error results use ::warning:: in CI and StepWarn
formatting. Sensitive data from thinking blocks and result messages is
never surfaced.

Closes #241
@github-actions

Copy link
Copy Markdown

E2E tests did not run

E2E tests run automatically for org/repo members and collaborators on pull requests.

For other contributors, a maintainer must add the ok-to-test label after the latest push.

See E2E testing guide for details.

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 10, 2026

Copy link
Copy Markdown

🤖 Finished Review · ❌ Failure · Started 12:58 PM UTC · Completed 12:59 PM UTC
Commit: c776c24 · View workflow run →

@guyoron1

Copy link
Copy Markdown
Owner

/fs-review

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 10, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 3:57 PM UTC · Completed 4:05 PM UTC
Commit: d8e3df7 · View workflow run →

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review

Verdict: approve

Clean feature addition that extends the progress parser to handle thinking, result, and system events from the Claude Code stream-json output. The implementation correctly avoids leaking sensitive data from thinking blocks and result messages. Error-path sanitization via sanitizeOutput() is correctly applied where untrusted input (evt.Subtype) flows into GHA annotations. Test coverage is thorough with 7 new test cases covering happy paths, edge cases (missing subtype), and data leakage verification.

Findings

[sanitization-consistency] emitThinkingProgress does not call sanitizeOutput() on its message before emitting ::notice:: to stderr. Every other emit function (emitToolProgress, emitResultProgress, emitSystemProgress) sanitizes its output. While no untrusted input flows into this message today (only elapsed and toolCount), the invariant "all CI annotations are sanitized" is a defensive pattern worth maintaining. One-line fix: add msg = sanitizeOutput(msg) before the isCI check.
internal/runtime/claude_progress.go · low · sanitization-consistency

[json-tag-divergence] streamEvent.IsError uses json:"is_error,omitempty" while transcriptResult.IsError (line 32 of claude_transcript.go) uses json:"is_error" without omitempty. Since streamEvent is only deserialized (never serialized), this is functionally harmless, but the inconsistency could cause confusion or subtle bugs if the struct is ever marshaled — omitempty on a bool silently drops the field when false.
internal/runtime/claude_progress.go · low · json-tag-divergence

[test-gap] No test verifies that an assistant event with both a thinking block and a tool_use block in the same content array produces both a "Thinking" heartbeat and a tool progress update. The parseAssistantEvent switch handles this correctly, but a combined test would increase confidence.
internal/runtime/claude_progress_test.go · low · test-gap


Labels: PR adds new event type handling in internal runtime progress parser

Previous run

Review

Verdict: approve

Clean extension of the progress parser to handle thinking, result, and system events. The change is well-scoped, correctly handles sensitive content (thinking text and result bodies are never surfaced), and includes thorough test coverage for all new code paths.

What was reviewed

  • Correctness: Verified the ifswitch refactor preserves existing behavior. The renamed parseAssistantEvent has no stale references. Existing TestProgressParser continues to pass — the {"type":"result"} line in its input now triggers emitResultProgress but assertions are additive-safe. Thinking events correctly do not increment tool count. No test assertions were weakened.
  • Security: All GHA workflow command emissions (::notice::, ::warning::) were traced. evt.Subtype is the only user-controlled value interpolated into output — sanitizeOutput is applied in every code path. Computed values (elapsed, toolCount) are type-safe. Thinking content and result body are structurally excluded — streamEvent only deserializes Type, Subtype, and IsError.
  • Intent & coherence: Change traces to [RTK+Ponytail] fullsend run: render agent event stream live during execution #241 (render agent event stream). Scope is appropriate — extends the Claude Code-specific parser, which is internal to the Runtime implementation. The printer is already injected via the Runtime interface, so each runtime can emit progress through its own format.
  • Style: Naming follows existing patterns (emitXxxProgress, parseXxxEvent). Tests follow TestProgressParserXxx convention. Code organization is consistent.
  • Documentation: No stale references. All identifiers are unexported. No docs describe the progress output format.

Observations

Sanitization pattern: emitResultProgress and emitSystemProgress sanitize evt.Subtype individually before composing the message, while emitToolProgress sanitizes the full composed msg. Both approaches are correct — the new functions only have one untrusted input (Subtype), and the remaining components are computed values. The per-field approach is arguably more precise. Noting for consistency awareness, not a bug.

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added the ready-for-merge All reviewers approved — ready to merge label Jul 10, 2026
@guyoron1

Copy link
Copy Markdown
Owner

/fs-fix

@fullsend-ai-coder

fullsend-ai-coder Bot commented Jul 10, 2026

Copy link
Copy Markdown
Author

🤖 Finished Fix · ✅ Success · Started 5:38 PM UTC · Completed 5:50 PM UTC
Commit: d8e3df7 · View workflow run →

…Progress

Apply sanitizeOutput to the composed message instead of individual
fields, matching the pattern used in emitToolProgress. This ensures
consistency across all emit functions so future untrusted fields
are automatically covered.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@fullsend-ai-coder

Copy link
Copy Markdown
Author

🔧 Fix agent — iteration 1 (human-triggered)

Addressed reviewer observation about sanitization pattern consistency. Changed emitResultProgress and emitSystemProgress to sanitize the full composed message instead of individual fields, matching the existing emitToolProgress pattern.

Fixed (1):

  1. sanitization pattern inconsistency (internal/runtime/claude_progress.go): Moved sanitizeOutput from per-field (evt.Subtype) to full composed message in emitResultProgress and emitSystemProgress, matching the pattern used in emitToolProgress for consistency

Tests: passed

Updated by fullsend fix agent

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 10, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 5:51 PM UTC · Completed 5:59 PM UTC
Commit: d8e3df7 · View workflow run →

@fullsend-ai-review fullsend-ai-review Bot added ready-for-merge All reviewers approved — ready to merge enhancement New feature or request and removed ready-for-merge All reviewers approved — ready to merge labels Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request ready-for-merge All reviewers approved — ready to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[RTK+Ponytail] fullsend run: render agent event stream live during execution

1 participant