Task has had a Priority field since the orchestration types shipped. It's an integer, lower means more urgent, and until now nothing in the codebase ever read it. Every list_task call returned items in whatever order the underlying query happened to produce, not random, exactly, but not meaningful either. The gap got found the way these things usually do: two Tasks with priority numbers that contradicted their own intended order, and nothing anywhere to notice.
The obvious fix wasn't available
The natural instinct is to let a caller pass orderBy on list_task and be done with it. That runs straight into an interface boundary: MCPList, the method behind every list_* tool, is part of MCPModule, an exported interface with at least one real external implementer. Adding a parameter to a required interface method breaks every implementation that isn't Module[T] itself. Not a theoretical concern; this project has hit the identical shape before and settled it the same way each time: extend around the interface, never through it.
So the fix isn't a parameter. It's a property of the module itself, set once, at registration:
smeldr.NewModule((*Task)(nil),
smeldr.At("/tasks"),
smeldr.Repo(repo),
smeldr.DefaultListOrder("Priority", false),
)
MCPList's own signature never changes. It just returns its items in a more useful order, for the two types that ask for one. Every other registered type, every type that predates this option, keeps behaving exactly as it always has.
Wiring it exposed a second bug already sitting there
Before wiring Task/Goal up, the plan was to test the fix against an in-memory repository, the same one the test suite leans on everywhere. The sort came back unchanged. Not "wrong order," completely unsorted, as if the field weren't there at all.
It wasn't a wiring mistake. The sort helper backing MemoryRepo only ever compared string fields; anything else silently became an empty string, and every item with an empty key sorts as equal to every other. Priority is an int. The moment the fix actually got tested rather than assumed correct, it turned out "wire the existing sort through" wasn't sufficient on its own: the sort itself needed to understand a number.
That's a narrower fix than it sounds: one new function, used only by the sort path, extending it to also compare integer fields. The half-dozen other places in the codebase that resolve a field by name, looking up a slug, an ID, a status, are all correctly string-only by design and never touch this new code at all.