Skip to content

fix(llm): reduce Pi RPC message update logs - #578

Merged
zzwong merged 7 commits into
mainfrom
fix/pi-rpc-message-update-log-size
Aug 31, 2026
Merged

fix(llm): reduce Pi RPC message update logs#578
zzwong merged 7 commits into
mainfrom
fix/pi-rpc-message-update-log-size

Conversation

@zzwong

@zzwong zzwong commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Summary

Reduce Pi RPC diagnostic log growth by omitting a redundant cumulative root message from validated streaming message_update records.

This changes log serialization only. Pi stdout parsing, model response assembly, structured output, final usage, session IDs, and tool evidence continue to use the original event stream.

Problem

Pi streaming updates carry the cumulative assistant message twice: once as the root message and again as assistantMessageEvent.partial. The existing log normalizer compacts the nested partial, but retaining the root copy still makes repeated updates grow with the entire response-so-far.

Change

For a known Pi assistant streaming event, the normalizer now omits the root message only when the retained event fields and five compact metadata fields have the expected JSON types and the root is byte-for-byte identical to the original cumulative partial. The persisted update keeps the event delta fields and compact assistant metadata (role, provider, model, api, and stopReason).

The exact original line is retained when that projection is malformed or unrecognized, the role is not assistant, or the root and partial differ. Cumulative content, usage, timestamps, and optional message fields are deliberately outside this projection check so the normalizer does not duplicate Pi's evolving message schema. Final message_end and agent_end records are unchanged.

Before and After

Before, each normalized streaming update retained both the cumulative root message and compact partial metadata. After, validated redundant updates retain only the incremental event fields and compact metadata.

A deterministic local experiment generated 106 synthetic Pi 0.83-shaped events, including 100 cumulative updates. The normalized JSONL measured:

  • Before: 169,469 bytes
  • After: 33,077 bytes
  • Difference: 136,392 bytes (80.48% smaller)

This synthetic result demonstrates the repeated-field effect; it is not a production benchmark or a retention target.

Compatibility and Risk

  • The parser still consumes the original stdout line, so model responses and structured output are unchanged.
  • Completed runs retain final content and usage in their final Pi events.
  • Non-Pi adapters do not use this normalization path.
  • Normalized diagnostic logs are not intended to be replayed as a complete Pi RPC stream.
  • In failed or truncated runs that never emit a final event, partial-only usage is not retained by the existing compact-update projection.
  • Exact raw equality is conservative: semantically equal objects with different JSON encoding retain the root and receive less size reduction rather than risk data loss.
  • Cumulative fields outside the five-key diagnostic projection are intentionally discarded even if their contents are nonstandard; malformed retained fields instead preserve the exact original line.

This does not change log retention, stale-run recovery, pruning, compression, response parsing, or response semantics.

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Repo scaffolding / maintenance

Checklist

  • I have read the contributing guide
  • My change follows the project structure and conventions
  • make tidy passes
  • make lint passes
  • make test passes
  • make build passes

Testing

  • go test ./internal/llmadapters -run '^Test(PiRPCLogStripsCumulativeStreamingPartials|NormalizePiRPCLogLineCompactsAllKnownPiAssistantEvents|NormalizePiRPCLogLinePreservesOriginalForProjectionFailures|NormalizePiRPCLogLineCompactsProjectionWithMalformedCumulativeFields|NormalizePiRPCLogLineCompactsStringProjectionFieldsWithoutPolicyChecks)$' -count=1
  • go test ./internal/llmadapters ./internal/benchmark
  • make check

The focused regression covers all nine Pi streaming event shapes, exact delta and five-key metadata preservation, exact-line fallback for every rejected projection class, the deliberate cumulative-field boundary, and final-event content/usage and session preservation.

Related Issues

None. This is a focused follow-up to the existing Pi RPC log normalization behavior.

monit-reviewer
monit-reviewer previously approved these changes Aug 31, 2026

@monit-reviewer monit-reviewer 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.

Automated PR Review

Reviewed commit: aeb8f637e7e3
Profile: pi-codex-monit-reviewer - Posting as: monit-reviewer

Summary

Reviewer Findings
go:implementation-tests 1
architecture:solid-reviewer-agnostic 0
go:implementation-tests (1 finding)

Minor - internal/llmadapters/pi_rpc.go:773

The raw-byte equality guard is a deliberate data-retention boundary, but the tests only cover roots with different values. Add a regression case where root message and assistantMessageEvent.partial decode to the same object but use different key order or whitespace, and assert the exact original line is retained. That prevents a future semantic-equality refactor from silently dropping a non-byte-identical root.

Reviewer Coverage

  • go:implementation-tests — complete (broad); skipped: none; constraints: Repository file-range reads returned unrelated/truncated content after the pinned diff, so surrounding context was unavailable; review is based on the complete pinned diff.
  • architecture:solid-reviewer-agnostic — complete (broad); skipped: none; constraints: CR tools are read-only, so I inspected the implementation and tests but did not execute make check or other verification commands. Review was scoped to the two assigned files and relevant repository architecture guidance.
Inspected files (2)
  • internal/llmadapters/pi_rpc.go
  • internal/llmadapters/pi_rpc_test.go

0 PR discussion threads considered. 0 summarized; 0 resolved.


Completed in 3m 03s | $0.09 | openai-codex/gpt-5.6-terra, openai-codex/gpt-5.6-sol | cr dev
Field Value
Model openai-codex/gpt-5.6-terra, openai-codex/gpt-5.6-sol
Reviewers go:implementation-tests, architecture:solid-reviewer-agnostic
Engine pi_rpc · openai-codex/gpt-5.6-terra, openai-codex/gpt-5.6-sol
Reviewed by cr · monit-reviewer
Duration 3m 03s wall · 3m 43s compute
Cost $0.09
Tokens 11.5k in / 2.5k out

Per-workstream usage

  • orchestrator-selection — openai-codex/gpt-5.6-terra
    • In: 5.9k
    • Out: 244
    • Cache read: 2.8k
    • Cache create: 0
    • Cost: $0.02
    • Duration: 6s
  • go:implementation-tests — openai-codex/gpt-5.6-terra
    • In: 986
    • Out: 1.6k
    • Cache read: 11.8k
    • Cache create: 0
    • Cost: $0.02
    • Duration: 48s
  • architecture:solid-reviewer-agnostic — openai-codex/gpt-5.6-sol
    • In: 3.0k
    • Out: 539
    • Cache read: 51.7k
    • Cache create: 0
    • Cost: $0.04
    • Duration: 2m 42s
  • orchestrator-rollup — openai-codex/gpt-5.6-terra
    • In: 1.6k
    • Out: 150
    • Cache read: 2.8k
    • Cache create: 0
    • Cost: $0.01
    • Duration: 5s

Comment thread internal/llmadapters/pi_rpc.go

@monit-reviewer monit-reviewer 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.

Automated PR Review

Reviewed commit: a77505a8c93e
Profile: pi-codex-monit-reviewer - Posting as: monit-reviewer

Summary

Reviewer Findings
go:implementation-tests 0
architecture:solid-reviewer-agnostic 0

Reviewer Coverage

  • go:implementation-tests — complete (constrained); skipped: none; constraints: Review limited to the two assigned changed Go files; no test execution tools are available.
  • architecture:solid-reviewer-agnostic — complete (constrained); skipped: none; constraints: Repository tools are read-only, so I could not run tests, lint, or builds. Review scope was limited to the two assigned files.
Inspected files (2)
  • internal/llmadapters/pi_rpc.go
  • internal/llmadapters/pi_rpc_test.go

1 PR discussion threads considered. 1 summarized; 1 resolved.


Completed in 2m 07s | $0.07 | openai-codex/gpt-5.6-terra, openai-codex/gpt-5.6-sol | cr dev
Field Value
Model openai-codex/gpt-5.6-terra, openai-codex/gpt-5.6-sol
Reviewers go:implementation-tests, architecture:solid-reviewer-agnostic
Engine pi_rpc · openai-codex/gpt-5.6-terra, openai-codex/gpt-5.6-sol
Reviewed by cr · monit-reviewer
Duration 2m 07s wall · 2m 16s compute
Cost $0.07
Tokens 7.7k in / 1.8k out

Per-workstream usage

  • go:implementation-tests — openai-codex/gpt-5.6-terra
    • In: 1.1k
    • Out: 589
    • Cache read: 15.9k
    • Cache create: 0
    • Cost: $0.01
    • Duration: 35s
  • architecture:solid-reviewer-agnostic — openai-codex/gpt-5.6-sol
    • In: 5.4k
    • Out: 1.2k
    • Cache read: 20.0k
    • Cache create: 0
    • Cost: $0.05
    • Duration: 1m 37s
  • orchestrator-rollup — openai-codex/gpt-5.6-terra
    • In: 1.2k
    • Out: 57
    • Cache read: 2.8k
    • Cache create: 0
    • Cost: $0.00
    • Duration: 3s

@zzwong
zzwong marked this pull request as ready for review August 31, 2026 21:26
@zzwong
zzwong merged commit e8e2ae4 into main Aug 31, 2026
10 checks passed
@zzwong
zzwong deleted the fix/pi-rpc-message-update-log-size branch August 31, 2026 21:26
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