fix(ws2): register @app.command(/new-task) so Slack slash command is acked

'the app did not respond': serve() registered @app.action/@app.event but NO
@app.command handler, so Bolt never acked the /new-task slash command within
Slack's ~3s deadline. Add an @app.command(/new-task) handler that ack()s first,
re-stamps type:slash_commands onto Bolt's inner command body (Bolt strips the
Socket Mode envelope type that _is_new_task_command/_discriminating_type expect),
then forwards to handle_event (AUTHZ-01 + new-task dispatch). The resulting
payload shape is the one already covered by test_new_task_calls_callback_*.
This commit is contained in:
Adam Moussa 2026-06-23 13:43:42 -04:00
parent 478bd7f90b
commit 0945d60338

View file

@ -523,6 +523,21 @@ class SlackListener:
def _on_mention(body: Mapping[str, Any]) -> None:
_forward(body)
# Slash commands (e.g. /new-task) MUST be ack()'d within ~3s or Slack
# shows "the app did not respond". Bolt delivers the INNER command
# payload (command / text / user_id / channel_id) WITHOUT the Socket
# Mode envelope's ``type``, so re-stamp ``type: "slash_commands"`` to
# match what handle_event's _is_new_task_command + _discriminating_type
# expect, then forward (handle_event runs AUTHZ-01 + the new-task
# dispatch). Ack FIRST so the 3s deadline is met even though start_task
# then runs the clarifier to the first gate synchronously.
@app.command(_NEW_TASK_COMMAND)
def _on_command(ack: Any, body: Mapping[str, Any]) -> None:
ack()
payload = dict(body)
payload.setdefault("type", "slash_commands")
_forward(payload)
handler = SocketModeHandler(app, self._app_token)
self._socket_handler = handler
handler.start()