Skip to content

Take toolregistry 0.19 and toolregistry-server 0.7 - #193

Merged
rajeeja merged 3 commits into
mainfrom
bump-toolregistry-0.19
Oct 23, 2026
Merged

rajeeja merged 3 commits into
mainfrom
bump-toolregistry-0.19

Conversation

@rajeeja

@rajeeja rajeeja commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator

Both released today. toolregistry 0.19.0 carries the union fix we have been
waiting on (Oaklight/ToolRegistry#269, our #165), and the pair changes three
things that reach clients.

The union fix is real

A heterogeneous union now renders as anyOf instead of silently dropping
branches. The floor moves to 0.19.0 / 0.7.0.

But we still do not serve upstream's rendering

lat_spec is annotated tuple | float | list[Any] | None. tuple and list
both render as array, so 0.19 emits the array branch twice, with untyped
items:

anyOf: [ {array, items:{}}, {number}, {array, items:{}} ]

A duplicated branch is noise in a payload we measure, and untyped items say
less than we know. _type_untyped_unions now replaces that rendering rather
than only filling an absence:

anyOf: [ {number}, {array, items:{number}} ]

Core tool specification 36271 → 36143 bytes, so no budget moves.

Two behaviour changes in toolregistry-server 0.7

Unknown tool is now a protocol error. -32602 instead of a
CallToolResult with isError. This is the correct reading — isError is for
a tool that ran and failed; an unknown name means nothing ran — so the test
asserts the new contract instead of pinning the old one.

0.7 infers its own annotations, and got two wrong. It marked
manage_session and resume_workflow as readOnlyHint=True. Neither is
read-only:

Tool What it actually does
manage_session resets session state, clears artifacts
resume_workflow runs pending workflow steps

Nine tools we had deliberately left unrated came back carrying hints. A client
reading readOnlyHint may auto-approve on the strength of it.

Our shim deferred to any annotation already present, which handed the decision
to whoever guessed first. It now asserts our rating where we have one and
clears the field where we have not. Absence is the honest answer for a tool
nobody rated; an inferred hint is a claim no one checked, and a wrong
safe-to-run claim is the one failure direction that costs a user something.

TestUpstreamInferenceDoesNotOverruleUs pins both halves and names those two
tools specifically, so a future release making the same guess fails here rather
than in a client. Reverting the fix fails 3 tests (verified).

Verification

1540 passed, 1 skipped, 44 deselected, 1 xfailed

Does not close #165

That checklist also asks to remove the workaround entirely. The
duplicate-branch rendering above means it still earns its place — I have
updated the issue with what 0.19 did and did not fix.

Both released today. 0.19 carries the union fix we have been waiting on
(Oaklight/ToolRegistry#269, our #165), and the pair changes three things
that reach clients.

The union fix is real: a heterogeneous union now renders as `anyOf`
instead of silently dropping branches. The floor moves to 0.19.0 so an
older registry cannot be resolved, because the schema repair that used
to cover for it is no longer shaped the same way.

What we serve for `lat_spec` still is not upstream's rendering, though.
The annotation is `tuple | float | list[Any] | None`, and `tuple` and
`list` both render as `array`, so 0.19 emits the array branch twice with
untyped items:

    anyOf: [ {array, items:{}}, {number}, {array, items:{}} ]

A duplicated branch is noise in a payload we measure, and untyped items
say less than we know. `_type_untyped_unions` now replaces that rendering
rather than only filling an absence, and serves the canonical form:

    anyOf: [ {number}, {array, items:{number}} ]

The core tool specification goes 36271 -> 36143 bytes as a result, so no
budget moves.

Two behaviour changes in toolregistry-server 0.7:

- An unknown tool name is now a JSON-RPC -32602 rather than a
  `CallToolResult` with `isError`. That is the correct reading --
  `isError` is for a tool that ran and failed, and an unknown name means
  nothing ran -- so the test asserts the new contract instead of pinning
  the old one.

- 0.7 infers annotations of its own, and marked `manage_session` and
  `resume_workflow` `readOnlyHint=True`. Neither is read-only:
  `manage_session` resets session state and clears artifacts,
  `resume_workflow` runs pending steps. Nine tools we had deliberately
  left unrated came back carrying hints, and a client reading
  `readOnlyHint` may auto-approve on the strength of it.

  Our shim deferred to any annotation already present, which handed the
  decision to whoever guessed first. It now asserts our rating where we
  have one and clears the field where we have not. Absence is the honest
  answer for a tool nobody rated; an inferred hint is a claim no one
  checked, and a wrong safe-to-run claim is the one failure direction
  that costs a user something.

`TestUpstreamInferenceDoesNotOverruleUs` pins both halves, and names
`manage_session` and `resume_workflow` specifically so a future release
making the same guess fails here rather than in a client.

1540 passed, 1 skipped, 44 deselected, 1 xfailed.

Does not close #165: the checklist there also asks to drop the
workaround entirely, and the duplicate-branch rendering above means it
still earns its place. Updated there with what 0.19 did and did not fix.
The lockfile audit went red on this branch while it was green on main
three days ago, with the same pillow 12.3.0 pinned in both. Nothing here
pulled it in: 44 advisories against 12.3.0 were published in between, 5
of them Critical, all fixed in 13.0.0.

pillow arrives transitively through bokeh and matplotlib under uxarray's
viz extra, so there is nothing of ours to re-point. `uv lock
--upgrade-package pillow` moves that one package and nothing else.

Carried on this branch rather than in its own PR because the audit is a
required check and this branch cannot merge while it is red. The
plotting tests pass on 13.0.0, which is the part of pillow this server
actually uses.
Clearing pillow exposed two more the scanner had not reached: PYSEC-2026-4320
against certifi 2026.7.22, which is a 9.1 Critical, and four against
virtualenv 21.14.7 including a 7.8 High. Both published in the same window
as the pillow set.

certifi is the trust store every outbound HTTPS call in this server uses --
Globus Compute submission, Globus transfers, remote dataset reads -- so a
Critical there is not a transitive detail. virtualenv arrives through the
dev toolchain.

Each moves to its first fixed release and nothing else resolves differently.
@rajeeja
rajeeja merged commit 79d2d95 into main Oct 23, 2026
14 checks passed
@rajeeja
rajeeja deleted the bump-toolregistry-0.19 branch October 23, 2026 19:37
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.

Remove lat_spec schema workaround after ToolRegistry releases union fix

1 participant