Skip to content

feat(pebble): send ntfy title as native UTF-8 via RFC 2047#74

Merged
max-tet merged 1 commit into
mainfrom
feat/ntfy-utf8-title
May 18, 2026
Merged

feat(pebble): send ntfy title as native UTF-8 via RFC 2047#74
max-tet merged 1 commit into
mainfrom
feat/ntfy-utf8-title

Conversation

@ClaydeCode
Copy link
Copy Markdown
Owner

Summary

  • Background: fix(pebble): ASCII-coerce ntfy title; disambiguate STT against KB folders #73 stopped the silent UnicodeEncodeError on the ntfy Title header by ASCII-coercing the title (em dash → `-`, smart quotes → `'`, etc.). Correct in the moment, but lossy — emoji disappear, German umlauts (`Müller`) collapse to `?`, and Claude has to mentally avoid Unicode in summaries.
  • Change: Send the title as native UTF-8. httpx still serialises header values as latin-1, but ntfy accepts RFC 2047 encoded-words (`=?utf-8?[bq]?...?=`) and decodes them server-side. Encoding happens at header-construction time via stdlib `email.header.Header`.
  • Preserved: `NotificationPayload.title` keeps the raw Unicode string. The `pebble.notify_title` OTel span attribute also keeps the raw Unicode, so traces stay readable. ASCII titles pass through verbatim — no wire overhead, no behaviour change for framework fallback titles (`Pebble: timeout`, etc.).
  • Rejected alternative: ntfy's JSON publish endpoint would side-step header encoding entirely, but it changes the request shape and loses the natural headers↔kwargs mapping. RFC 2047 is a stdlib one-liner.

Test plan

  • `uv run pytest` — 371 passed (3 new round-trip tests for em dash, emoji, German umlauts; plus a Unicode clamp test)
  • Round-trip verification in tests: encoded header is ASCII-only AND `decode_header` returns the original string
  • Manual after deploy: pebble that produces a title like `"Müller — Notiz gespeichert"` should arrive on the watch with characters intact, and `data/logs/traces.jsonl` should show `pebble.notify_ok=true` plus the raw title in `pebble.notify_title`

🤖 Generated with Claude Code

#73 stopped the silent UnicodeEncodeError on the ntfy Title header by
ASCII-coercing the title (em dash → "-", smart quotes → "'", etc.) —
correct in the moment but lossy: emoji disappear, German umlauts
("Müller") collapse to "?", and Claude has to mentally avoid Unicode
when summarising a Pebble outcome.

Switch to standards-based UTF-8 instead. httpx still serialises header
values as latin-1, but ntfy accepts RFC 2047 encoded-words
(=?utf-8?[bq]?...?=) and decodes them server-side. Encoding happens at
the point of header construction via stdlib email.header.Header; the
stored NotificationPayload.title and the pebble.notify_title OTel span
attribute both keep the raw Unicode so logs and traces stay readable.
ASCII titles pass through verbatim — no wire overhead, no behaviour
change for the framework fallback titles ("Pebble: timeout", etc.).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@max-tet max-tet merged commit 290181a into main May 18, 2026
3 checks passed
@max-tet max-tet deleted the feat/ntfy-utf8-title branch May 18, 2026 08:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants