Skip to content

fix(core): non-finite reset guards and docstring sweep (#1447) - #1514

Merged
tommasobolis merged 2 commits into
developfrom
chore/1447-docstrings-guards
Oct 30, 2026
Merged

tommasobolis merged 2 commits into
developfrom
chore/1447-docstrings-guards

Conversation

@tommasobolis

@tommasobolis tommasobolis commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

Part of #1447

#1447 is split across four PRs. #1510 carries Closes #1447 and the full item table, so merge it last:

Summary

  • Non-finite reset headers (fix): parse_retry_after() and retry_after() return None for a value that parses as a float but isn't finite (inf, -inf, nan, 1e400), on both Retry-After and the x-token-reset/x-ratelimit-reset fallback. Before, Retry-After: nan reached the transport's retry sleep as NaN, and time.sleep/asyncio.sleep both reject that with ValueError. inf was capped at the 30 s ceiling. Both now fall through to the jittered backoff, as an HTTP-date value already did.
  • Window.fraction_used (fix): remaining is clamped into [0, limit] before the division, so a header too large for a float can't overflow it. The result is unchanged for every in-range value.
  • ADR citations: the UngovernedMcpServer / governance-default citations in session.py, mcp.py, discovery.py, publication.py, models.py and donkey.py now cite ADR 0017, which superseded ADR 0013 (tools: decide how discover() and binding treat MCP servers the gateway does not front #1150). donkey.py keeps one "ADR 0013, rules kept by ADR 0017" where the history matters.
  • session.py: removed the dead _check_approvals(), since describe() already refuses a require_approval() name that matches no tool. The _bind_tool docstring says so. Its vulture entry is gone, and the two tests that called it now await tools.describe().
  • Discovery caching docstrings: resolve(), live_tools() and agent_card() no longer say "no cache". Nothing is cached in discovery itself, but the registry's lookups are, for registry_cache_ttl_s, and refresh() drops them.
  • PublicationAssetType: the docstring now covers what Exchange records for mcp and agent, that a2a-agent isn't an Exchange type, and that api means REST/HTTP/SOAP.
  • ExchangeRegistry.warm() / search(governed=) wording: these reads are answered (feat(tools): donkey.tools.warm() to pre-fill the discovery cache #1324). What isn't built is the environment-wide governed-state index, and donkey.tools.warm() pre-fills discovery instead. API Manager has no bulk policy read (§6, Verify whether applied policies can be fetched in bulk per environment #54). The _verify.blocked guard stays, because acceptance group 5 asserts it.
  • ConfigWarning: the docstring lists every case that raises it: a misplaced config entry, an env switch that relaxes a check, a non-loopback serve() host, and a wait_for_gateway_approval() over 2 minutes. It's kept to two lines so core/errors.py stays within its 1030-line budget (test_oversized_core_modules_only_shrink).

Test plan

  • nox -s typecheck-and-lint test-3.11 new-dependencies commit-identities (passed, after rebasing on e7859253)
  • New tests:
    • test_errors.py: inf, -inf, nan and 1e400 on retry-after and on x-token-reset all give retry_after is None, and parse_retry_after() returns None for each.
    • test_budget.py::test_fraction_used_clamps_before_it_divides
  • test_toolset_approval.py: the two former _check_approvals() tests run through describe(). The rebase on feat(hitl)!: settle the Approvals API: per-client registry, typed errors (#1423) #1497 kept its registry fixture.
  • nox (every session): not run locally; CI runs it
  • python scripts/verify_frameworks.py: n/a, no adapters or extras changed

ADR needed?

  • No: this PR changes none of those.

Acceptance-harness impact

None. The group 5 warm() test asserts only that it is blocked, which is unchanged, and no acceptance test matches the reworded docstrings or blocked text.

Migration note

TokenBudgetExceeded.retry_after, RequestRateLimitExceeded.retry_after and GatewayApprovalPending.retry_after are None, not inf/nan, when the gateway sends a non-finite reset. Code that already handles None needs no change. The private ToolSet._check_approvals() is removed; describe() does the same check.

Post-deploy steps

None.

tommasobolis and others added 2 commits October 30, 2026 11:56
…on_used divides (#1447)

retry_after() and parse_retry_after() return None for inf, -inf, nan and
1e400 instead of inf or 0.0. Window.fraction_used clamps remaining into
[0, limit] before dividing, so a header too large for a float no longer
raises OverflowError.

Part of #1447

Co-authored-by: Cursor <cursoragent@cursor.com>
- Cite ADR 0017 for the ungoverned-binding guard (ADR 0013 is superseded).
- Remove the dead ToolSet._check_approvals and its vulture entry; describe()
  already refuses an unmatched require_approval() name.
- Discovery.resolve()/live_tools()/agent_card(): nothing is cached there,
  but the registry's lookups are.
- PublicationAssetType records agent as well as mcp; ConfigWarning names
  every emitter; warm() and search(governed=) say the reads are answered
  and the index is what is not built.

Part of #1447

Co-authored-by: Cursor <cursoragent@cursor.com>
@tommasobolis
tommasobolis merged commit 570bd38 into develop Oct 30, 2026
52 checks passed
@tommasobolis
tommasobolis deleted the chore/1447-docstrings-guards branch October 30, 2026 11:28
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