Libra CodeHub

CedarCopilot/cedar-mail

Branch: staging

fix(slack): list rendering in notifications , space after lists + real numbered lists

merged#2521CedarCopilot

CedarCopilot wants to merge 0 commits into staging from fix/slack-richtext-list-paragraph-spacing

Live on prod, no production signal yetTimeline and evidence
  1. Opened
    Aug 18, 2026, 2:34 PM
  2. Merged
    Aug 18, 2026, 5:01 PM
  3. Live on prod
    Aug 18, 2026, 5:01 PM
  4. Observed 2 days
    Aug 18, 2026, 5:01 PM
  5. Pipelines steady after this deploy
    Aug 18, 2026, 5:01 PM
  6. Unobserved

    Live on prod, no production signal yet

    Aug 21, 2026, 4:49 AM

Behaviors Libra is checking

Emoji and bold Markdown headings following lists render with exactly one separator rather than a doubled blank gap.Inconclusivelow confidence

OTEL fallback found no prod spans matching markdownToSlackRichText / Slack rich_text_section since deploy.

prod, checked Aug 21, 2026, 3:49 AM
A paragraph or attendee line following a bullet list in a Slack notification receives one blank-line gap whether or not the source Markdown includes a blank line.Inconclusivelow confidence

OTEL fallback found no prod spans matching markdownToSlackRichText / Slack rich_text_section since deploy.

prod, checked Aug 21, 2026, 3:50 AM
Markdown ordered-list runs in Slack notifications render as a single native numbered list so items display 1, 2, 3 instead of bullets or repeated 1s.Inconclusivelow confidence

OTEL fallback found no prod spans matching markdownToSlackRichText / Slack rich_text_list since deploy.

prod, checked Aug 21, 2026, 4:49 AM

Libra has verdicts on 0 of 3 tracked behaviors on prod; 3 are still being checked. Libra checks hourly for 3 days after each deploy.

Two related fixes to markdownToSlackRichText, both surfaced by the Willem / Listen Labs meeting-prep thread in #weewee-meetingprep (2026-08-18). This function backs every Cedar Slack notification (via buildBlockKitBlocksnotify-user, slack-bot-chat, user-slack-notifier).

1. Paragraphs glued under bullet lists

Root cause: the renderer only inserted a blank-line spacer when the previous block was a paragraph. After a bullet list the blank line was dropped, so any sentence/attendee line following bullets rendered glued to the last bullet.

Fix: section() inserts a spacer when the previous block is a rich_text_list. Covers both the blank-line and no-blank-line source shapes; does not double-space consecutive bullets.

Evidence (real renderer, list → blank → paragraph): BULLET, paragraph (glued) → BULLET, spacer, paragraph (gap restored).

2. Numbered lists rendered as bullets

Root cause: every ordered (1.) item was rendered as a bullet , a workaround for the "1. 1. 1." artifact you get from one single-item ordered list per item. So a meeting-prep "say this to open" agenda script that the model correctly wrote as 1. 2. 3. came out as bullets ("can these be numbered?").

Fix: group consecutive ordered items into a single style:'ordered' rich_text_list so Slack numbers them 1, 2, 3. A blank line between ordered items stays a no-op so the run keeps counting; bullet lists never merge into an ordered run.

Tests

pnpm --filter @zero/server exec vitest run src/services/notifications/__tests__/markdown-to-slack-richtext.test.ts , 27 pass, including:

  • paragraph after a list (with/without a blank line) gets a spacer (LSP)
  • consecutive bullets with a blank line → still one spacer (LSL)
  • ordered items → one ordered list numbered 1/2/3, no 1. 1. 1., keeps counting across a blank line
  • a bullet does not merge into an ordered run

Blast radius

Shared renderer , all Slack notifications, all orgs. Both changes make rendering match what agents already write (gaps where content was glued; numbers where the agent wrote a numbered list). Existing bullet/paragraph behavior is unchanged and covered by pre-existing tests.

🤖 Generated with Claude Code

Show production surfaces and changed-file mapping

Production surfaces

Libra has not measured any production surfaces for this change yet.

Changed files → surfaces

  • apps/server/src/services/notifications/__tests__/markdown-to-slack-richtext.test.tsno production surface mapped
  • apps/server/src/services/notifications/markdown-to-slack-richtext.tsno production surface mapped