Skip to content

rust(fix): tell callers when get_data returned decimated data - #774

Open
rowenwu wants to merge 2 commits into
mainfrom
rowen/get-data-sample-rate-guidance
Open

rust(fix): tell callers when get_data returned decimated data#774
rowenwu wants to merge 2 commits into
mainfrom
rowen/get-data-sample-rate-guidance

Conversation

@rowenwu

@rowenwu rowenwu commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

What

get_data recommended decimation for exactly the work the underlying API warns against, and never reported what rate it actually applied. Together those let an agent compute statistics on plot data and report them as fact.

sift/data/v2/data.proto documents that sample_ms applies LTTB, and that 0 "is recommended for external data analysis where full fidelity is required, as opposed to plotting where downsampling is typically sufficient." The tool description said the reverse and never named the algorithm.

Why it matters

LTTB selects shape-defining extremes rather than representative samples, so second-moment and trend statistics drawn from decimated output are wrong. Measured on one channel over one throttle window, raw against a 10 Hz pull:

raw 100 Hz LTTB 10 Hz
mean 1355.52 1347.56 (−0.6%)
standard deviation 26.67 89.00 (+234%)
slope per 100s +23.74 −17.11 (sign flip)

The error depends on where bucket boundaries fall relative to the analysis window, so it cannot be corrected after the fact. Bucketing the raw series and comparing each returned sample against its bucket, 50.3% matched the bucket minimum and 49.8% the maximum, which is LTTB working as designed.

Changes

Guidance. sample_ms is documented as 0 unless the data will be used exclusively to generate a visualization, with LTTB named and the consequence stated. An oversized result is answered by narrowing the time range or the channel set, not by decimating. The two prompt flows that told the agent to pick a rate to suit the run length now pass 0, since both end in statistics.

Reporting. Metadata.sampled_ms arrives on every data page and was being dropped. The result now carries sample_ms_applied and decimated, always present so raw and unchecked cannot be confused, and the next_step text says plainly that a decimated file cannot be analysed.

The rate is tracked as a range rather than a single value because the API ignores sample_ms for data types it cannot sample: one request can come back decimated for a double channel and raw for a string one. Reporting whichever page landed last would describe half the file, so a mixed result reports the decimated half and sets mixed_sample_rates.

Verification

cargo test -p sift_mcp — 511 pass, 3 new:

  • get_data_reports_the_applied_sample_rate — a decimated pull reports its rate and sets decimated
  • get_data_reports_raw_when_nothing_was_decimated — a raw pull reports itself as raw, rather than as "no rate reported"
  • get_data_flags_a_file_that_mixes_decimated_and_raw_channels — a mixed file reports the decimated half and flags the mix

cargo clippy -p sift_mcp --all-targets is clean apart from one pre-existing warning in report_templates.

Note for reviewers

This changes agent behaviour, not just documentation. Anything downstream that assumed get_data would decimate by default for large pulls will now receive raw samples unless it asks otherwise.

The tool description recommended decimation for exactly the work the API
warns against, and the result never said what rate was applied. Together
those let an agent compute a standard deviation on plot data and report it
as fact.

Guidance. `sample_ms` is now documented as 0 unless the data will be used
exclusively to draw a picture, with LTTB named and the consequence spelled
out: counts, means, standard deviations and trends taken off decimated
output are wrong, and the error depends on where bucket boundaries fall, so
it cannot be corrected afterwards. An oversized result is answered by
narrowing the time range or the channel set, not by decimating. The two
prompt flows that told the agent to pick a rate to suit the run length now
pass 0, since both end in statistics.

Reporting. `Metadata.sampled_ms` arrives on every data page and was being
dropped. `get_data` now surfaces `sample_ms_applied` and `decimated`, always
present so raw and unchecked cannot be confused, and the next_step text says
plainly that a decimated file cannot be analysed.

The rate is tracked as a range rather than a single value because the API
ignores `sample_ms` for data types it cannot sample: one request can come
back decimated for a double channel and raw for a string one. Reporting
whichever page landed last would describe half the file, so a mixed result
reports the decimated half and sets `mixed_sample_rates`.
@rowenwu
rowenwu marked this pull request as ready for review September 3, 2026 19:40
@rowenwu
rowenwu removed the request for review from solidiquis September 4, 2026 00:36
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.

1 participant