Every slash command is unreachable, because nothing registers them with Discord #885

Closed
opened 2026-08-17 04:17:45 +00:00 by coilyco-ops · 0 comments
Member

Found by Angie (ENG, claude seat) while building #127's remaining half.

Every slash command this repository ships is unreachable

A slash command needs three parts. This repository has two.

  • Declared - JobCommands() returns echo, job-status, job-cancel, mcps, each validated at startup.
  • Handled - onInteraction is wired when SIRENS_ECHO_DISCORD_COMMANDS is on, and gates through access.Evaluate and the admission limiter like every other ingress.
  • Registered - nothing. discordCommands() renders the set and its only caller is command_test.go. No ApplicationCommandBulkOverwrite, no ApplicationCommandCreate, no registration API anywhere in the tree.

Discord shows a member no command nobody published. So with the switch on, the handler waits for interactions that cannot arrive, and with it off nothing changes. The surface is declared, validated, tested, handled, and invisible.

Two greps settle it:

$ grep -rn "discordCommands(" --include='*.go' .
internal/community/command_test.go:21:  if _, err := discordCommands(); err != nil {
internal/community/commanddiscord.go:16:func discordCommands() ([]*discordgo.ApplicationCommand, error) {

$ grep -rn "ApplicationCommandBulkOverwrite\|ApplicationCommandCreate" --include='*.go' internal/ cmd/
(nothing)

Why it went unnoticed

The gate reads as the reason nothing appears. SIRENS_ECHO_DISCORD_COMMANDS defaults false and neither lane sets it, so "the commands are off" is a true sentence that fully explains the observed absence - and it is not the reason. Turning the switch on would have changed nothing, and the next person to try it would have gone looking in the wrong place.

This is the same family as sirens-echo#621's unwired capabilities, with one difference worth naming: those had no production caller and this has a production handler. A green test over discordCommands() reads as a working surface.

What it needs

Publish the rendered set to Discord, gated on the existing switch, on discord.ready where the application id first exists.

Per guild rather than globally: a global command appears in every guild the bot is in, including ones the access policy refuses, where it would be visible, invocable, and answered not permitted here. That advertises a summon path this deployment does not offer, which is exactly the property docs/access-policy.reference.yaml was written to keep honest.

A bulk overwrite, so a command removed from the declaration disappears rather than lingering as an invocable ghost.

Scope

Registration only. Promoting an MCP prompt to a command is #884, and it needs a decision this does not.

Related - #127 (the parent), #884 (prompt promotion), #621 (the unwired-capability sweep this rhymes with).

Found by Angie (ENG, `claude` seat) while building #127's remaining half. ## Every slash command this repository ships is unreachable A slash command needs three parts. This repository has two. * **Declared** - `JobCommands()` returns `echo`, `job-status`, `job-cancel`, `mcps`, each validated at startup. * **Handled** - `onInteraction` is wired when `SIRENS_ECHO_DISCORD_COMMANDS` is on, and gates through `access.Evaluate` and the admission limiter like every other ingress. * **Registered** - **nothing.** `discordCommands()` renders the set and its only caller is `command_test.go`. No `ApplicationCommandBulkOverwrite`, no `ApplicationCommandCreate`, no registration API anywhere in the tree. Discord shows a member no command nobody published. So with the switch on, the handler waits for interactions that cannot arrive, and with it off nothing changes. The surface is declared, validated, tested, handled, and invisible. Two greps settle it: ``` $ grep -rn "discordCommands(" --include='*.go' . internal/community/command_test.go:21: if _, err := discordCommands(); err != nil { internal/community/commanddiscord.go:16:func discordCommands() ([]*discordgo.ApplicationCommand, error) { $ grep -rn "ApplicationCommandBulkOverwrite\|ApplicationCommandCreate" --include='*.go' internal/ cmd/ (nothing) ``` ## Why it went unnoticed The gate reads as the reason nothing appears. `SIRENS_ECHO_DISCORD_COMMANDS` defaults false and neither lane sets it, so "the commands are off" is a true sentence that fully explains the observed absence - and it is not the reason. Turning the switch on would have changed nothing, and the next person to try it would have gone looking in the wrong place. This is the same family as sirens-echo#621's unwired capabilities, with one difference worth naming: those had no production caller and this has a production *handler*. A green test over `discordCommands()` reads as a working surface. ## What it needs Publish the rendered set to Discord, gated on the existing switch, on `discord.ready` where the application id first exists. Per guild rather than globally: a global command appears in every guild the bot is in, including ones the access policy refuses, where it would be visible, invocable, and answered `not permitted here`. That advertises a summon path this deployment does not offer, which is exactly the property `docs/access-policy.reference.yaml` was written to keep honest. A bulk overwrite, so a command removed from the declaration disappears rather than lingering as an invocable ghost. ## Scope **Registration only.** Promoting an MCP prompt to a command is #884, and it needs a decision this does not. **Related** - #127 (the parent), #884 (prompt promotion), #621 (the unwired-capability sweep this rhymes with).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo#885
No description provided.