Optimize Zoekt search response payload
The Zoekt coordinating node returns the full Zoekt response format to Rails, which parses the entire JSON body in one shot. An [S3 incident (INC-7931)](https://gitlab.com/gitlab-com/gl-infra/production/-/work_items/21421) occurred when `Gitlab::Json.safe_parse` was introduced — its 100k JSON element limit was exceeded by normal group-level search results.
**Root cause:** Both standard and multi-match search send `max_file_match_results = 5,000` (or UNLIMITED for standard). Combined with the 5,000 line match window, the coordinating node can return thousands of file objects in a single response. Each file + line match contributes ~52 JSON elements (not ~20 as originally estimated), so the 100k limit is hit at ~1,900 files with 1 match each, or ~580 files with 5 matches each. Rails only needs ~200 results (10 pages × 20 per page) for the common case.
**Related:** https://gitlab.com/gitlab-com/gl-infra/production-engineering/-/work_items/28457
## Issues
### Short-term — reduce payload size
1. #591911 — Use `TotalLineMatchCount` / `TotalFileMatchCount` for accurate result counts (must land first)
2. #591910 — Cap `max_file_match_results` to `max(Cache::MAX_PAGES, current_page) * per_page` (200 for pages 1-10, scales for deeper pages)
### Medium-term — re-enable safe_parse
3. #591912 — Re-enable `Gitlab::Json.safe_parse` behind a derisk feature flag (blocked by #591910 and #591911)
### Medium-term — offset pagination (independent track)
4. #591915 — Support offset-based pagination in the coordinating node (standard search)
5. #591917 — Support offset-based pagination for multi-match search mode (blocked by #591915)
### Long-term — wire format optimization
6. #591913 — Redesign coordinating node response format for efficiency
## Dependency chain
```
#591911 (fix counts) ──blocks──► #591910 (cap results) ──blocks──► #591912 (safe_parse)
#591911 (fix counts) ──blocks──► #591912 (safe_parse)
#591915 (offset: standard) ──blocks──► #591917 (offset: multi-match)
```
- #591911 and #591910 are the critical path for re-enabling `safe_parse`
- #591915/#591917 (offset pagination) are an independent optimization track — no blocking dependency on #591910
- All risky changes are rolled out behind feature flags
## Element count formula
```
total_elements = 24 + 22*N + 30*N*M
```
- N = files, M = line matches per file (assuming 1 fragment, 1 branch)
- 24 = fixed overhead (envelope + result object)
- 22 per file = 10 kv-pairs + array appends
- 30 per line match = 10 kv-pairs + 1 fragment (4 kv-pairs) + array appends
epic