Skip to content

[4.41/SL4b] Slack inbound mrkdwn normalization, channel.post thread ids, Socket Mode retries (remainder of #209) #283

Description

@patrick-chinchill

Summary

Remainder of #209, split per its Metadata (the full port came to about 2k changed lines; the split threshold is 1.5k). #209's first PR ports part (a): self-mention decoding, content-based is_mention, and bot author ids / email / is_system. This issue is part (b): inbound mrkdwn normalization, channel.post thread ids, and Socket Mode retries.

Starting point: branch wip/4.41-sl4-full (commit c0788056) holds the full #209 port, with full validation green on its base: 6710 passed, strict fidelity 733/733, pyrefly 0 errors. Part (b) is that branch's diff minus what the #209 part-(a) PR merged. Rebase or cherry-pick the (b) pieces listed below once that PR has landed, re-run the validation, and send the result through astra review. Nothing on that branch has been reviewed yet.

Upstream changes

  • e71bfead fix(slack): preserve first line of incoming code blocks (#843), chat@4.39.0
  • 44423bdc fix(slack): convert special mentions to readable text (#960), chat@4.41.1
  • c3118279 fix(slack): preserve channel id and normalize frequently hallucinated link format (#756), chat@4.37.0
  • 92530dd3 fix(slack): return replyable thread ID from channel posts (#720), chat@4.35.0
  • 0b63791b fix(slack): process Socket Mode retry envelopes instead of dropping them (#667), chat@4.33.0 (Slack half)

Scope (all already on wip/4.41-sl4-full)

  • adapters/slack/format.py: port convertSpecialMentions and convertMrkdwnWithCodeFences and their helpers (findAngleTokenEnd, findInlineCodeEnd, isOnBlockquoteLine, escapeLeadingBlockMarker), plus the #name (C…) rewrite and the inverted-link swap. The scanners are linear: a failed <…> scan is memoized, the newline search is bounded, and the blockquote check matches in place.
  • SlackFormatConverter.to_ast becomes parse_markdown(slack_mrkdwn_to_markdown(text)). This fixes the missing unescape, so &lt; now renders as <. Drop the Python-only regex extract_plain_text override; upstream markdown.ts has none.
  • Both parse paths: formatted = to_ast(text), then text = ast_to_plain_text(formatted) (upstream toPlainText(formatted)). [4.41/SL5] Slack inbound: pasted tables and alert attachments in message content #210 later swaps formatted for the assembled content.
  • post_channel_message: return slack:{channel}:{ts} when raw["ts"] is a str.
  • Socket Mode: stop dropping retry envelopes. Log "Processing socket mode retry" at info with retry_attempt, retry_reason and type, then route the event.
  • Tests:
    • tests/test_slack_format_primitives.py: every it that e71bfead (10), 44423bdc (7, including the it.each) and c3118279 (3) added, plus an adversarial 50k-character case.
    • tests/test_slack_format.py: the 6 e71bfead markdown.test.ts cases.
    • tests/test_slack_socket_mode.py: "processes retries like first deliveries (dedupe drops true duplicates)", replacing test_retry_attempt_is_skipped_but_acked.
    • Slack parse tests: "converts special mentions to readable text", "preserves special mention tokens in an inbound inline code span" and "preserves special mention tokens in an inbound code block".
    • Post-channel tests: "posts to channel without thread context", plus a Python case with no string ts.
  • docs/UPSTREAM_SYNC.md and the CHANGELOG Breaking/consumer-visible bullets for: special mentions and #general (C123), the kept first code line, message.text as plain text of formatted (list markers, #, > and backticks dropped), channel.post() ids, and processed socket retries.

Known gaps found while porting (not Slack-specific; record them or file separately)

  • The shared parse_markdown has no multi-backtick code spans and keeps a paragraph's leading space. Two markdown.test.ts assertions were adapted ("keeps a quoted fence inside the blockquote", "keeps trailing text after a code block as a paragraph").
  • The shared parse_markdown is quadratic on some inputs: 50k characters of `x or *a take 25–37 s. This predates the port, but every inbound Slack message goes through to_ast.

Notes

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions