While merging #6229 into current main, both sides turned out to have independently implemented GET /v1/commands, which the router rejected at runtime:
Overlapping method route. Handler for `GET /v1/commands` already exists
They are not duplicates. They are two different contracts, and the one that shipped is the thinner of the two.
What shipped (main, 70cda6e43, #6178)
CommandCatalogEntry in runtime_api.rs carries name, aliases, summary, usage, subcommands, takes_arguments, kind, binding, discovery, hidden, shadowed_by, shadowed_aliases. It includes user-registered commands and shadowing, which the other does not.
What the branch had, and main does not
runtime_api/commands.rs (removed in the merge, recoverable at 060711b2f1) projected a richer composer/palette contract. Its test asserted every row carries:
| Field |
Main's equivalent |
description (localized, with a locale on the response naming the resolved pack) |
summary — English only, by design |
requires_argument |
— |
requires_required_argument |
takes_arguments (boolean, does not distinguish optional from mandatory) |
composer_wants_trailing_space |
— |
palette_runs_directly |
— |
show_in_empty_discovery |
— |
unlisted |
hidden |
Its stated purpose was to let a native composer reproduce slash completion without re-parsing usage — e.g. /profile sets requires_required_argument: true and palette_runs_directly: false, a distinction takes_arguments flattens.
The decision that is open
Main's summary is deliberately English: "English source text; localizing is the client's surface." The branch's description is localized server-side with a resolved-locale marker. Those are incompatible policies for the same field and someone has to choose. That is a public API contract decision, not a merge mechanic, which is why I did not fold them together while resolving conflicts.
What I did instead: kept main's handler (shipped, and #6178 is closed against it), removed the branch's duplicate route, module and test, and wrote this down so the capability is not silently lost. Everything is recoverable from 060711b2f1.
Suggested resolution
Add the argument-shape and composer fields to main's CommandCatalogEntry — they are additive and nothing depends on their absence — and decide the localization policy separately, since that one is a real fork:
- server-localized
description + locale, or
- English
summary and the client owns localization.
The second is what main documents today; the first is what a native composer would rather consume. Worth deciding once rather than per-client.
While merging #6229 into current
main, both sides turned out to have independently implementedGET /v1/commands, which the router rejected at runtime:They are not duplicates. They are two different contracts, and the one that shipped is the thinner of the two.
What shipped (main,
70cda6e43, #6178)CommandCatalogEntryinruntime_api.rscarriesname,aliases,summary,usage,subcommands,takes_arguments,kind,binding,discovery,hidden,shadowed_by,shadowed_aliases. It includes user-registered commands and shadowing, which the other does not.What the branch had, and main does not
runtime_api/commands.rs(removed in the merge, recoverable at060711b2f1) projected a richer composer/palette contract. Its test asserted every row carries:description(localized, with alocaleon the response naming the resolved pack)summary— English only, by designrequires_argumentrequires_required_argumenttakes_arguments(boolean, does not distinguish optional from mandatory)composer_wants_trailing_spacepalette_runs_directlyshow_in_empty_discoveryunlistedhiddenIts stated purpose was to let a native composer reproduce slash completion without re-parsing
usage— e.g./profilesetsrequires_required_argument: trueandpalette_runs_directly: false, a distinctiontakes_argumentsflattens.The decision that is open
Main's
summaryis deliberately English: "English source text; localizing is the client's surface." The branch'sdescriptionis localized server-side with a resolved-locale marker. Those are incompatible policies for the same field and someone has to choose. That is a public API contract decision, not a merge mechanic, which is why I did not fold them together while resolving conflicts.What I did instead: kept main's handler (shipped, and #6178 is closed against it), removed the branch's duplicate route, module and test, and wrote this down so the capability is not silently lost. Everything is recoverable from
060711b2f1.Suggested resolution
Add the argument-shape and composer fields to main's
CommandCatalogEntry— they are additive and nothing depends on their absence — and decide the localization policy separately, since that one is a real fork:description+locale, orsummaryand the client owns localization.The second is what main documents today; the first is what a native composer would rather consume. Worth deciding once rather than per-client.