Skip to content

analysis pagination can exceed the capability retained-result limit #1225

Description

@andreasronge

Summary

Large analysis collection pages can pass the snapshot query's encoded-JSON byte check and then fail at the Kernel capability boundary with provider_result_limit, because the dispatcher measures retained BEAM size instead.

This keeps the debugging evidence layer unavailable on exactly the map-heavy runs that most need analysis.

Historical evidence

The original inspection-analysis-v2 API forced limit: 100. Two independent 40-turn live runs reproduced the failure for model_exchanges while smaller runs and sibling collections succeeded. Those exchanges are derived from paired capability-input / capability-output records, so bypassing the analysis profile requires reimplementing its correlation logic.

The old API no longer exists. Current analysis/read accepts a caller-controlled limit from 1 through 100 and exposes cursors. That removed the literal "no caller control" defect, but not the boundary mismatch.

Current cause on main

  • InspectionQuery and TraceLog fit pages using byte_size(Jason.encode!(page)).
  • InspectionSnapshot applies a retained-size check only to the singular terminal result.
  • Dispatcher checks every successful capability result with RetainedSize.bytes_with_cap/2 against capability_result_bytes.

A map-heavy page may therefore be accepted by its source owner and rejected only after returning from the capability callback. Lisp projection cannot recover because the capability never returns a value.

Expected contract

A requested page limit is an item-count upper bound. Before a snapshot publishes a page, the complete returned page, including snapshot metadata, must fit both:

  1. its encoded JSON byte ceiling; and
  2. the retained-size ceiling enforced by the dispatcher.

If the requested prefix does not fit, pagination returns the largest non-empty fitting prefix and an advancing cursor. If one individual item cannot fit, the query returns result_limit_exceeded without a stalled cursor.

Scope

  • Use one shared encoded-and-retained result-budget policy.
  • Apply it to private inspection and canonical trace pagination.
  • Apply the same policy to bounded RunAnalysis singular and aggregate results.
  • Keep the dispatcher as the final authority.
  • Do not raise limits, truncate fields, change cursor identity, widen authority, or add chunking for an intrinsically oversized individual item.

Acceptance

  • A network-free 40-exchange cumulative-conversation fixture reproduces the old provider_result_limit failure before the fix.
  • Default analysis/read returns a non-empty bounded page and cursor after the fix.
  • Following cursors recovers every exchange exactly once.
  • limit: 1 succeeds when the individual item fits.
  • Every returned page fits both encoded and retained ceilings.
  • Existing individually-oversized-item failures remain stable.
  • Equivalent canonical trace pagination cannot outrun the dispatcher boundary.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions