fix: use net diff size (additions − deletions) for push memory patch size enforcement - #49894
Conversation
…ditions Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅ |
|
✅ PR Code Quality Reviewer completed the code quality review. |
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. No ADR enforcement needed: PR #49894 does not have the 'implementation' label and has 0 new lines of code in business logic directories (threshold: 100). |
|
✅ Test Quality Sentinel completed test quality analysis. Test Quality Sentinel completed analysis: 83/100 score, all 9 tests are design-level behavioral contracts with 0% implementation tests. Ready for approval. |
There was a problem hiding this comment.
Pull request overview
Updates repo-memory patch enforcement to measure net byte growth rather than raw additions.
Changes:
- Calculates additions minus deletions, clamped to zero.
- Updates repo-memory validation messages and call sites.
- Adds unit coverage for diff-size calculation.
Show a summary per file
| File | Description |
|---|---|
actions/setup/js/repo_memory_patch_size.cjs |
Implements net diff-size calculation. |
actions/setup/js/repo_memory_patch_size.test.cjs |
Tests calculation behavior and Git invocation. |
actions/setup/js/push_repo_memory.cjs |
Uses and reports net diff size. |
actions/setup/js/safe_outputs_handlers.cjs |
Updates safe-output validation and messages. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Suppressed comments (1)
actions/setup/js/safe_outputs_handlers.cjs:1748
- The corresponding success-path test at
safe_outputs_handlers.test.cjs:2723still asserts that this message contains"patch additions". This wording change therefore makes the existing test fail; update the assertion to"patch diff".
message: `Memory validation passed: ${files.length} file(s), ${totalSizeKb} KB total content, ` + `${patchSizeKb} KB patch diff (${patchSizeBytes} bytes) (limit: ${effectiveMaxKb} KB / ${effectiveMaxPatchSize} bytes).`,
- Files reviewed: 4/4 changed files
- Comments generated: 1
- Review effort level: Balanced
|
@copilot patch size is computed in other JavaScript files. Find and reuse helper. |
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /tdd and /diagnosing-bugs — requesting changes on one critical test-file defect.
📋 Key Themes & Highlights
Key Issues
- Broken test file:
repo_memory_patch_size.test.cjsuses ES moduleimportsyntax in a CommonJS (.cjs) file. Node.js will throw a parse error and none of the tests will run, leaving the regression guard empty.
Positive Highlights
- ✅ Root cause correctly identified and fixed: net diff size (additions − deletions, clamped to 0) prevents false positives on full rewrites
- ✅ Good JSDoc explaining the new algorithm and its tradeoffs
- ✅ Test cases cover the key scenarios: new file, append, rewrite, shrink, multi-file, and header-line exclusion
- ✅ Clean rename (
getStagedPatchAdditionsSizeBytes→getStagedPatchDiffSizeBytes) applied consistently across all three call sites
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 34 AIC · ⌖ 10.7 AIC · ⊞ 7.1K
Comment /matt to run again
There was a problem hiding this comment.
The fix correctly changes raw additions counting to net diff bytes (additions − deletions, clamped to 0), which avoids false over-reporting when a file is completely regenerated with similar-sized content.
Code is clean, the logic is sound, and the test suite covers the key regression scenario (same-size rewrite), append-only, shrink/clamp-to-zero, multi-file, and header-line exclusion. Test pattern is consistent with the rest of the test suite.
🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 30 AIC · ⌖ 7.46 AIC · ⊞ 5.4K
🧪 Test Quality Sentinel Report✅ Test Quality Score: 83/100 — Excellent
📊 Metrics (9 tests)
Key Observations✅ All tests are behavioral contract tests — each verifies a user-facing guarantee:
✅ Comprehensive coverage of the bug fix: Test #4 explicitly validates the core issue — that a complete file rewrite with the same size should contribute ~0 bytes to the patch budget, not the entire new content.
Verdict
All 9 tests are design-level behavioral contracts. The bug fix is well-defended by edge-case and regression tests. The test inflation ratio reflects legitimate edge-case coverage, not artificial test bloat.
|
|
@copilot run pr-finisher skill |
There was a problem hiding this comment.
Verdict: Request changes — the net-diff redesign reopens the size guard to bypasses it was meant to prevent.
💡 Themes
- Cross-file masking: the net byte total is accumulated globally across the whole staged diff rather than per file, so an unrelated deletion in one file can offset a large addition in another, letting the reported patch size collapse toward zero while substantial new content is pushed.
- Same-size rewrite bypass: the net formula (
additions - deletions, clamped at 0) treats any equal-size full-file rewrite as ~0 bytes regardless of how much or how different the new content is, which is a much larger regression than the original false-positive it fixes (over-counting regenerated files). - Test coverage gap: the new unit tests validate single-file same-size rewrites well, but do not cover the multi-file masking scenario that is the main risk introduced by moving from per-line addition counting to a diff-wide net total.
The intent of the fix (avoid over-counting a benign same-size rewrite) is reasonable, but the implementation trades a false-positive for a false-negative that undermines the guard's actual security purpose (bounding pushed content size). Recommend computing net size per-file (flushing accumulators per diff --git boundary) and/or using additions directly for full-file replacements before merging.
🔎 Code quality review by PR Code Quality Reviewer · auto · 82.3 AIC · ⌖ 3.81 AIC · ⊞ 7.9K
Comment /review to run again
… git_patch_utils.cjs Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done in commit Moved both |
|
@copilot run pr-finisher skill |
…-file clamping in getPatchDiffSizeBytes Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
PR is ready to merge:
The 5 review threads still need to be dismissed/resolved by a maintainer (4 are outdated); I can't resolve them without |
|
@copilot Maintainer-ready pass: please run the Outstanding unresolved review threads (newest first):
All current checks on the latest commit are green. After confirming, a maintainer can resolve the threads and dismiss any stale github-actions review.
|
All 5 review threads are now resolved. CI is fully green on the latest commit ( |
|
Hey What's working well:
Why this matters: Previously, files that were completely regenerated with similar-sized content (e.g., regenerated JSON state) would report their entire file size toward the push limit, even if only a few bytes actually changed. This fix removes that false positive by using the net change instead.
|
Triage ResultCategory: bug | Risk: medium | Score: 78/100 (impact 40, urgency 22, quality 16) Recommended action: fast_track CI green (all checks success), clean mergeable state, sizable diff (251+/65-, 7 files) touching push-memory patch-size enforcement logic. Ready for expedited human review.
|
|
@copilot Please refresh this PR for maintainer review: update the branch if needed, rerun the Run: https://github.com/github/gh-aw/actions/runs/30806305280 Current status: latest checks are green and the PR appears mergeable, but please confirm the remaining cleanup is complete and summarize whether any maintainer action is still needed.
|
Refreshed now.
Remaining blockers: none found from the agent side. Maintainer action is only the normal final approval/merge step. |
max-patch-sizeenforcement for repo-memory pushes was measuring raw+line bytes fromgit diff --cached. When a memory file (e.g. JSON) is fully regenerated each run, git emits the entire old content as-lines and entire new content as+lines — causingpatchSizeBytesto equal the full file size regardless of how small the logical change was.Changes
repo_memory_patch_size.cjs— replacegetAddedPatchSizeBytesFromDiff(sums+lines) withgetPatchDiffSizeBytes(net:max(0, additions_bytes − deletions_bytes)); rename export togetStagedPatchDiffSizeBytespush_repo_memory.cjs/safe_outputs_handlers.cjs— update import + call site; update error/debug messages to reflect "diff" vs "additions"repo_memory_patch_size.test.cjs(new) — unit tests for append-only, complete rewrite (key regression), shrink/clamp, multi-file, header line exclusionrun: https://github.com/github/gh-aw/actions/runs/30787664739