Skip to content

fix(truncate): pick a stable record path when arrays tie - #1770

Merged
Dumbris merged 1 commit into
smart-mcp-proxy:mainfrom
rudycelekli:fix/truncate-record-path-deterministic-20261023-01
Oct 26, 2026
Merged

Dumbris merged 1 commit into
smart-mcp-proxy:mainfrom
rudycelekli:fix/truncate-record-path-deterministic-20261023-01

Conversation

@rudycelekli

Copy link
Copy Markdown
Contributor

Bug

When a tool response is over the truncation limit, findArraysRecursive (internal/truncate/truncator.go) collects candidate record arrays by ranging over each JSON object, and chooseBestArray picks one. On a tie, chooseBestArray keeps whichever candidate came first. Go randomizes map iteration, so identical payloads with equally good sibling arrays get a different RecordPath on different calls. The read_cache handle minted for that response then pages a different array each time.

Trigger

An upstream tool returns, for example, {"zeta":[…20 rows], "alpha":[…20 rows], "mid":[…20 rows]} and the response is over the limit. content_forward.go calls Truncate on every such response. Repeated identical calls return record_path values of zeta, alpha, or mid depending on map order.

Fix

Object keys are now traversed in sorted order, so the tie-break is stable: the first key in sorted order wins. Non-tied selection is unchanged.

Verification

  • go test -count=1 -run TestTruncate_TiedArraysPickStableRecordPath ./internal/truncate/ passes. The test runs 50 calls on the payload above and expects alpha every time.
  • With truncator.go reverted (git stash push internal/truncate/truncator.go), the same test fails: call 0: record path "zeta", want "alpha".
  • go test -count=1 ./internal/truncate/ passes.
  • go vet ./internal/truncate/ is clean.
  • gofmt -l internal/truncate/ is clean.
  • I also ran go test -count=1 ./internal/server/ locally, but it hit the default 10-minute test timeout, which isn't a result either way. A narrower rerun failed at setup because of a local build-cache error. I'm relying on CI for that package.

Commands were run with GOFLAGS=-mod=readonly CGO_ENABLED=0.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@Dumbris Dumbris left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Verified: the PR test fails on main for the reason described and passes on this branch merged with main; race tests for the touched packages and CI lint (bare and server tags) are clean. Also built and tested together with the rest of this batch, independently reviewed, and cross-reviewed with a second model.

@Dumbris
Dumbris merged commit 4c7d2b2 into smart-mcp-proxy:main Oct 26, 2026
46 checks passed
@Dumbris

Dumbris commented Oct 26, 2026

Copy link
Copy Markdown
Member

Merged. Thank you, @rudycelekli! read_cache record paths are stable when sibling arrays tie.

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.

3 participants