[PR #1293] [MERGED] fix(process): validate terminal byte totals against retained frames #2773

Closed
opened 2026-10-17 21:10:04 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/1293
Author: @kaoru0822-kitauji
Created: 10/9/2026
Status: ✅ Merged
Merged: 10/9/2026
Merged by: @kaoru0822-kitauji

Base: main ← Head: fix/process-capture-terminal-byte-accounting


📝 Commits (1)

  • 39eb058 fix(process): validate terminal byte totals against retained frames

📊 Changes

2 files changed (+48 additions, -2 deletions)

View changed files

📝 src/domain/process/processCaptureValidation.ts (+24 -2)
📝 tests/boundary/process/processTruncationAdapters.test.ts (+24 -0)

📄 Description

Summary

validateCoverage checked terminal retention only for retained_frames === frames.length, observed >= retained and retained_bytes <= budget. When a capture is deserialized from Evidence, it accepted:

  • any retained_bytes within budget, even if the retained frames hold a different number of bytes, and
  • observed_bytes > retained_bytes while observed_frames === retained_frames, which says bytes were lost although no frame was omitted.

So a malformed capture could claim truncated: false (truncation is derived from omitted frames) while its byte accounting says terminal data is missing, and comparisons would treat that terminal evidence as complete. The Codex review on #1284 flagged this (src/domain/process/processCaptureValidation.ts:155, "Validate terminal byte totals against retained frames"), and it was still present on main after the merge.

Change

Using the producers' own accounting (captureTerminalFrames and TerminalRenderer#capture, where whole frames are retained or omitted):

  • raw_terminal.retained_bytes must equal the sum of Buffer.byteLength(raw_data ?? data) over the retained frames, since the original PTY chunk is what the budget counts;
  • rendered_terminal.retained_bytes must equal the sum of serialized_state plus visible lines bytes over the retained rendered frames;
  • if no frame was omitted, observed_bytes must equal retained_bytes.

truncation_details was introduced by #1284, after #1263 added raw_data. Every capture that carries these details therefore also carries the original chunk bytes, so no existing valid capture changes status.

Verification

  • tests/boundary/process/processTruncationAdapters.test.ts (real PTY captures through CLI and MCP, run on this macOS host): every real capture still parses. New tampering assertions (raw retained_bytes: 0, raw observed_bytes + 1 with no omitted frame, rendered retained_bytes - 1) are rejected here and accepted on main. Both adapter cases fail without the fix.
  • All of tests/boundary/process/*.test.ts (160 passed, 2 Linux-only skipped)
  • npm run check:changed (510 passed)

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/1293 **Author:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Created:** 10/9/2026 **Status:** ✅ Merged **Merged:** 10/9/2026 **Merged by:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Base:** `main` ← **Head:** `fix/process-capture-terminal-byte-accounting` --- ### 📝 Commits (1) - [`39eb058`](https://github.com/morluto/rea/commit/39eb0587c95ad028bb961c539ad1f326a1e8d81c) fix(process): validate terminal byte totals against retained frames ### 📊 Changes **2 files changed** (+48 additions, -2 deletions) <details> <summary>View changed files</summary> 📝 `src/domain/process/processCaptureValidation.ts` (+24 -2) 📝 `tests/boundary/process/processTruncationAdapters.test.ts` (+24 -0) </details> ### 📄 Description ## Summary `validateCoverage` checked terminal retention only for `retained_frames === frames.length`, `observed >= retained` and `retained_bytes <= budget`. When a capture is deserialized from Evidence, it accepted: - any `retained_bytes` within budget, even if the retained frames hold a different number of bytes, and - `observed_bytes > retained_bytes` while `observed_frames === retained_frames`, which says bytes were lost although no frame was omitted. So a malformed capture could claim `truncated: false` (truncation is derived from omitted frames) while its byte accounting says terminal data is missing, and comparisons would treat that terminal evidence as complete. The Codex review on #1284 flagged this (`src/domain/process/processCaptureValidation.ts:155`, "Validate terminal byte totals against retained frames"), and it was still present on `main` after the merge. ## Change Using the producers' own accounting (`captureTerminalFrames` and `TerminalRenderer#capture`, where whole frames are retained or omitted): - `raw_terminal.retained_bytes` must equal the sum of `Buffer.byteLength(raw_data ?? data)` over the retained frames, since the original PTY chunk is what the budget counts; - `rendered_terminal.retained_bytes` must equal the sum of `serialized_state` plus visible `lines` bytes over the retained rendered frames; - if no frame was omitted, `observed_bytes` must equal `retained_bytes`. `truncation_details` was introduced by #1284, after #1263 added `raw_data`. Every capture that carries these details therefore also carries the original chunk bytes, so no existing valid capture changes status. ## Verification - `tests/boundary/process/processTruncationAdapters.test.ts` (real PTY captures through CLI and MCP, run on this macOS host): every real capture still parses. New tampering assertions (raw `retained_bytes: 0`, raw `observed_bytes + 1` with no omitted frame, rendered `retained_bytes - 1`) are rejected here and accepted on `main`. Both adapter cases fail without the fix. - All of `tests/boundary/process/*.test.ts` (160 passed, 2 Linux-only skipped) - `npm run check:changed` (510 passed) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-17 21:10:04 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#2773
No description provided.