Skip to content

feat: report clamped settings via §19 ConfigClamped (contract 1.9) - #46

Merged
ilpanich merged 1 commit into
mainfrom
claude/improvements-run5-benchmark-def-bazzei
Aug 10, 2026
Merged

feat: report clamped settings via §19 ConfigClamped (contract 1.9)#46
ilpanich merged 1 commit into
mainfrom
claude/improvements-run5-benchmark-def-bazzei

Conversation

@ilpanich

Copy link
Copy Markdown
Owner

Retrofit of contract 1.9's §19.2 rule 6 to this SDK, which merged before the rule existed.

Why

Two places in the contract require clamping rather than rejecting. Clamping is right — rejecting would break a caller whose configuration was merely optimistic, and honoring would let one client become the herd §16 exists to prevent. Doing it silently is the part that is wrong.

An operator who sets a 60-second decision-memo TTL believes their staleness bound is 60 seconds. It is five. Every conclusion they draw about how stale an allowed can be is wrong by a factor of twelve, and before this event nothing anywhere said so.

Scope here is narrower than in C#

This SDK's only caller-facing clamp is §17.1 rule 2's memo TTL. §16's attempt cap, base delay and delay cap are constants with no knob to raise — deliberately, per §16.1 — so there is nothing to report for them. That is why the event carries only decision_memo_ttl.

(The C# SDK is the opposite case: its three retry settings were publicly settable upward, which is what prompted the rule.)

report_clamp is called from the builder, not from DecisionMemo::new, because the telemetry sink is assembled in the same expression and construction is the only moment an operator can act on the report.

Three tests, two of them for what it must not do

Case Expected
60 s TTL exactly one event naming decision_memo_ttl, effective value rendering the 5 s cap
2 s TTL nothing — already inside the limit
disabled default nothing

That last one matters more than it looks: without it, every client ever built would fire a zero-to-zero "clamp", and an event that fires when nothing happened trains its reader to ignore it.

Verification

Gate Result
cargo test --all-features every binary green, 3 new
cargo clippy --all-targets --all-features -- -D warnings clean
cargo fmt --all --check clean
cargo doc --all-features --no-deps with RUSTDOCFLAGS=-D warnings clean

Re-vendors CONTRACT.md at 1.9.

Notes


Generated by Claude Code

Retrofit of contract 1.9's §19.2 rule 6 to this SDK, which merged before the
rule existed.

The only clamp this SDK applies is §17.1 rule 2's memo TTL — §16's parameters
are constants here, with no caller-facing knob to clamp, which is why the
event carries only decision_memo_ttl. That is the clamp that matters most
anyway: an operator who sets a 60-second TTL believes their staleness bound is
60 seconds. It is five, and before this event nothing anywhere said so.

report_clamp is called from the builder rather than from DecisionMemo::new,
because the telemetry sink is assembled in the same expression and construction
is the only moment an operator can act on the report.

Three tests, two of them for what it must NOT do:

  - a 60s TTL emits exactly one event naming decision_memo_ttl
  - a 2s TTL emits nothing — it was already inside the limit
  - the disabled default emits nothing, which matters because otherwise every
    client ever built would fire a zero-to-zero "clamp"

Gates: cargo test --all-features green, clippy --all-targets --all-features
-D warnings clean, fmt clean, cargo doc with RUSTDOCFLAGS=-D warnings clean.
@ilpanich
ilpanich merged commit 69ce8e3 into main Aug 10, 2026
13 checks passed
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.

2 participants