Skip to content

fix(adapters): bump telegramify-markdown to 1.3.3 for blockquote escaping#1340

Merged
Wirasm merged 3 commits into
coleam00:devfrom
truffle-dev:fix/telegramify-markdown-1.3.3
May 19, 2026
Merged

fix(adapters): bump telegramify-markdown to 1.3.3 for blockquote escaping#1340
Wirasm merged 3 commits into
coleam00:devfrom
truffle-dev:fix/telegramify-markdown-1.3.3

Conversation

@truffle-dev
Copy link
Copy Markdown
Contributor

@truffle-dev truffle-dev commented Apr 22, 2026

Summary

  • Problem: Telegram adapter crashes with 400: can't parse entities: Character '.' is reserved on every blockquote that contains a MarkdownV2 special character on the same line. Bot retries as plain text, so users get the content, but every workflow-start banner that quotes a workflow's description: loses formatting and logs telegram.markdownv2_failed.
  • Why it matters: Workflow notifications are how operators see what Archon is doing live; silently degraded formatting on every banner is bad UX and noisy in operator metrics.
  • What changed: Bumped telegramify-markdown from ^1.3.0 (resolving to 1.3.2) to ^1.3.3 in packages/adapters/package.json; refreshed bun.lock; added a regression test in packages/adapters/src/chat/telegram/markdown.test.ts.
  • What did NOT change (scope boundary): No production code in packages/adapters/ was modified. No other package was touched. No new dependencies, no exports changed.

Root Cause

packages/adapters pinned telegramify-markdown@^1.3.0, resolving to 1.3.2. That version escapes the > blockquote marker (Telegram MarkdownV2 supports > natively) and double-escapes any other special character on the same line:

import telegramify from 'telegramify-markdown';
telegramify('> blockquote.', 'escape');
// 1.3.2: "\\> blockquote\\\\.\n"   → literal: \> blockquote\\.   (rejected)
// 1.3.3: "> blockquote\\.\n"       → literal: > blockquote\.    (accepted)

Upstream fix: skitsanos/telegramify-markdown@1.3.3.

UX Journey

Before

Operator                            Archon                          Telegram API
────────                            ──────                          ────────────
runs workflow ─────────────────▶    builds banner with blockquote
                                    telegramify('> a.', 'escape')
                                    → "\\> a\\\\.\n"
                                    posts to Telegram ───────────▶  400: Character '.' reserved
                                    ◀───────────────────────────── (rejection)
                                    retries as plain text ───────▶  accepted (no formatting)
sees plain-text banner ◀──────────  notification arrives, formatting lost

After

Operator                            Archon                          Telegram API
────────                            ──────                          ────────────
runs workflow ─────────────────▶    builds banner with blockquote
                                    telegramify('> a.', 'escape')
                                    → "> a\\.\n"          [1.3.3]
                                    posts to Telegram ───────────▶  200 OK
sees formatted banner ◀───────────  notification arrives, blockquote intact

Architecture Diagram

No production module changes — dependency floor bump + regression test only.

Connection inventory:

From To Status Notes
packages/adapters telegramify-markdown (npm) modified floor bumped 1.3.0 → 1.3.3 in package.json + bun.lock

Label Snapshot

  • Risk: risk: low
  • Size: size: XS
  • Scope: adapters
  • Module: adapters:telegram

Change Metadata

  • Change type: bug
  • Primary scope: adapters

Linked Issue

Validation Evidence (required)

bun test src/chat/telegram/markdown.test.ts   # 25 pass, 0 fail
bun run check:bundled                          # bundled-defaults.generated.ts is up to date
bun run type-check                             # all 10 packages: exit 0
bun run lint                                   # clean
bun x prettier --check .                       # All matched files use Prettier code style!
bun run --filter '*' test                      # all 10 packages: exit 0
  • Evidence provided: stash-bisect verified — reverting the bump locally produces a failing assertion in the new regression test ('> hi\\\\.\n' returned vs '> hi\\.\n' expected).
  • All commands run on the PR HEAD (d25252f).

Security Impact (required)

  • New permissions/capabilities? No
  • New external network calls? No
  • Secrets/tokens handling changed? No
  • File system access scope changed? No

Compatibility / Migration

  • Backward compatible? Yestelegramify-markdown 1.3.2 → 1.3.3 is a patch release. Only the over-escape behaviour for >-prefixed lines changes; Telegram accepts the new (correct) output where it rejected the old.
  • Config/env changes? No
  • Database migration needed? No

Human Verification (required)

  • Verified scenarios:
    • '> blockquote.''> blockquote\\.\n' (single-char same-line)
    • '> a.b-c!''> a\\.b\\-c\\!\n' (multi-char same-line, broadened in d25252f)
    • '> first.\n> second?''> first\\.\n> second?\n' (multi-line; ? correctly passes through, not in MarkdownV2's reserved set)
  • Edge cases checked:
    • Blockquotes without special characters: output identical to 1.3.2; existing tests still pass.
    • Non-blockquote content with special characters: 1.3.3 changes only the >-line escaping path.
    • bun.lock floor: confirmed telegramify-markdown@1.3.3 resolves under the new ^1.3.3 constraint with no transitive downgrade.
  • What was not verified: live Telegram API send — I do not have a Telegram bot token available. Verified rendered string shape only; the upstream library tests verify Telegram acceptance.

Side Effects / Blast Radius (required)

  • Affected subsystems/workflows: packages/adapters/src/chat/telegram only — workflows that emit Telegram notifications (workflow-start banners, error notifications, run-summary messages).
  • Potential unintended effects: any consumer that depended on the old over-escape behaviour would see different output. None expected — the old shape was rejected by Telegram, so any caller receiving it had to fall back to plain text already.
  • Guardrails/monitoring for early detection: the new regression test asserts the 1.3.3 shape verbatim; if a future floor relaxation re-introduces the double-escape, CI fails.

Rollback Plan (required)

  • Fast rollback command/path: git revert <merge-commit-sha> — single commit, three files (package.json, bun.lock, one test file).
  • Feature flags or config toggles: none — telegramify-markdown is a direct dependency, no toggle layer.
  • Observable failure symptoms: telegram.markdownv2_failed log lines reappear in operator metrics; blockquote-bearing notifications drop back to plain text.

Risks and Mitigations

  • Risk: a downstream consumer of convertToTelegramMarkdown may have been depending on the over-escaped output as a workaround.
    • Mitigation: the only in-tree consumer is the Telegram adapter's send path, which always sent the over-escaped output to Telegram (which rejected it). No callers of the function exist outside the adapter.
  • Risk: telegramify-markdown 1.3.3 introduces a different bug.
    • Mitigation: floor pinned at 1.3.3 (caret allows future patch+minor); upstream changelog frames this as a targeted fix to the over-escape path. The new regression test asserts the exact expected output, so any future regression in the relevant code path is caught at CI time.

Summary by CodeRabbit

  • Chores

    • Updated dependency versions for improved compatibility and stability
  • Tests

    • Enhanced test coverage for markdown conversion reliability

Review Change Stack

…ping

telegramify-markdown 1.3.2 escapes the `>` blockquote marker (which
Telegram MarkdownV2 supports natively) and double-escapes any other
special character on the same line, so any blockquote ending in a
period (or containing `.`, `!`, `-`, etc.) is rejected by the Bot
API with "Character '.' is reserved and must be escaped". The bot
falls back to plain text and logs telegram.markdownv2_failed.

Upstream fixed both bugs in 1.3.3. Bumping the floor to ^1.3.3 and
adding a regression test on the canonical "> hi." case so the
behaviour can't silently regress if the dependency loosens later.

Fixes coleam00#1102
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 22, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ee7cf316-bd21-4fb6-8595-66683e620ba2

📥 Commits

Reviewing files that changed from the base of the PR and between d25252f and 622e410.

📒 Files selected for processing (1)
  • packages/adapters/src/chat/telegram/markdown.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/adapters/src/chat/telegram/markdown.test.ts

📝 Walkthrough

Walkthrough

Updated telegramify-markdown from ^1.3.0 to ^1.3.3 and added tests ensuring blockquote > markers are preserved while MarkdownV2 special characters inside blockquotes are escaped exactly once (single-line and multi-line cases).

Changes

Adapters: Telegram blockquote fix

Layer / File(s) Summary
Dependency upgrade
packages/adapters/package.json
Bumped telegramify-markdown from ^1.3.0 to ^1.3.3 to pull in upstream blockquote escaping fix.
Blockquote regression tests
packages/adapters/src/chat/telegram/markdown.test.ts
Added describe('blockquotes', ...) tests asserting > markers are preserved and special characters inside blockquotes are escaped exactly once, including multi-line blockquotes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I nibbled on code where blockquotes once tripped,
Dots learned to hide with one gentle skip,
Tests line the burrow to guard every line,
Versions aligned and the outputs now shine,
I twirl my whiskers and munch on a sign.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: bumping telegramify-markdown to fix blockquote escaping issues.
Description check ✅ Passed The PR description is comprehensive and complete, covering all required template sections with substantive detail: summary with problem/why/what/boundary, UX journey before/after, architecture diagram with connection inventory, labels, change metadata, linked issue, validation evidence, security impact, compatibility, human verification, side effects/blast radius, rollback plan, and risks/mitigations.
Linked Issues check ✅ Passed The PR fully addresses issue #1102 requirements: bumps telegramify-markdown from ^1.3.0 to ^1.3.3, updates bun.lock, and adds a comprehensive regression test covering blockquote escaping with special characters.
Out of Scope Changes check ✅ Passed All changes are strictly in-scope: dependency version bump in package.json, lockfile update, and regression test additions. No production code modifications or unrelated changes are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/adapters/src/chat/telegram/markdown.test.ts (1)

70-78: Regression test is tight and well-documented.

The exact-match assertion (vs. toContain) is the right choice here — it pins down both the unescaped > marker and the single-escaped ., which is exactly what 1.3.2 got wrong. The inline comment referencing #1102 is helpful for future bumps.

Optional: consider extending coverage with one or two additional cases to harden the guard (e.g., multiple special chars on a blockquote line, or a multi-line blockquote), since the upstream escaping bug could plausibly regress on shapes not covered by '> hi.' alone. Not a blocker.

Optional: broaden blockquote coverage
     describe('blockquotes', () => {
       // Regression: telegramify-markdown 1.3.2 escaped the `>` marker and
       // double-escaped any other special character on the same line, which
       // Telegram rejected with "Character '.' is reserved and must be
       // escaped". 1.3.3 fixes both. See coleam00/Archon#1102.
       test('escapes special chars exactly once inside blockquotes', () => {
         expect(convertToTelegramMarkdown('> hi.')).toBe('> hi\\.\n');
       });
+
+      test('escapes multiple special chars exactly once on a blockquote line', () => {
+        expect(convertToTelegramMarkdown('> a.b-c!')).toBe('> a\\.b\\-c\\!\n');
+      });
     });

Please verify the exact expected output for the additional case against 1.3.3 before committing it.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/adapters/src/chat/telegram/markdown.test.ts` around lines 70 - 78,
Add a couple more assertions to the existing blockquote test for
convertToTelegramMarkdown (the test titled 'escapes special chars exactly once
inside blockquotes') to cover additional shapes: one case with multiple special
characters on a single blockquote line (e.g., '> hi.!$') and one multi-line
blockquote (e.g., '> first.\n> second?') and assert the exact escaped output
matches the behavior in telegramify-markdown 1.3.3; update the test expectations
to the exact single-escape results for each case and run/verify against 1.3.3
before committing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/adapters/src/chat/telegram/markdown.test.ts`:
- Around line 70-78: Add a couple more assertions to the existing blockquote
test for convertToTelegramMarkdown (the test titled 'escapes special chars
exactly once inside blockquotes') to cover additional shapes: one case with
multiple special characters on a single blockquote line (e.g., '> hi.!$') and
one multi-line blockquote (e.g., '> first.\n> second?') and assert the exact
escaped output matches the behavior in telegramify-markdown 1.3.3; update the
test expectations to the exact single-escape results for each case and
run/verify against 1.3.3 before committing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 87dcad04-e382-4ff2-997b-3e0c52a14149

📥 Commits

Reviewing files that changed from the base of the PR and between 7ea3214 and ce35e7a.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (2)
  • packages/adapters/package.json
  • packages/adapters/src/chat/telegram/markdown.test.ts

…ti-line cases

Addresses review nit on coleam00#1340. 1.3.2's bug regressed both on multiple
special characters on one line and on multi-line blockquotes, so pinning
those shapes down adds real confidence against a future re-regression.

Expected outputs verified against telegramify-markdown 1.3.3:
- `> a.b-c!` escapes `.`, `-`, `!` exactly once, `>` marker unescaped.
- `> first.\n> second?` escapes `.` once, `?` passes through (not in
  Telegram MarkdownV2's reserved set), `>` marker unescaped on both lines.
@truffle-dev
Copy link
Copy Markdown
Contributor Author

Broadened blockquote coverage with two verified cases. Expected outputs confirmed against telegramify-markdown@1.3.3 before committing.

  1. '> a.b-c!''> a\.b\-c\!\n' (multi-char same-line). d25252f
  2. '> first.\n> second?''> first\.\n> second?\n' (multi-line, ? passes through since it's not in Telegram MarkdownV2's reserved set). d25252f

@Wirasm
Copy link
Copy Markdown
Collaborator

Wirasm commented Apr 27, 2026

Hi @truffle-dev — thanks for opening this PR.

This repository uses a PR template at .github/pull_request_template.md with several required sections. A few of them appear to be empty or placeholder here:

  • UX Journey
  • Architecture Diagram
  • Label Snapshot
  • Change Metadata
  • Compatibility / Migration
  • Human Verification
  • Side Effects / Blast Radius
  • Rollback Plan
  • Risks and Mitigations

Could you fill those out (even briefly)? The template helps reviewers understand scope, risk, and rollback — it speeds up review significantly.

If a section genuinely doesn't apply, just write "N/A" in it rather than leaving it blank.

@truffle-dev
Copy link
Copy Markdown
Contributor Author

Filled in. UX Journey, Architecture Diagram (no production module changes, dependency floor bump only), Label Snapshot, Change Metadata, Compatibility, Human Verification, Side Effects, Rollback, Risks all populated against the actual change. Existing Problem/Root-Cause/Validation kept and slotted into Summary + Validation Evidence.

@truffle-dev
Copy link
Copy Markdown
Contributor Author

Friendly check-in. 18 days since the PR template was filled in per the review request. Happy to rebase against dev if it's drifted, or split if any of the trailer additions would be easier reviewed separately.

@Wirasm
Copy link
Copy Markdown
Collaborator

Wirasm commented May 18, 2026

Review Summary

Verdict: ready-to-merge

Dependency bump for telegramify-markdown (^1.3.0^1.3.3) with regression tests for blockquote escaping (#1102). The change is clean and well-scoped — no risk to existing functionality.

Blocking issues

None.

Suggested fixes

None — the code itself is solid. One optional nit (see below).

Minor / nice-to-have

  • packages/adapters/src/chat/telegram/markdown.test.ts:69-74: The regression comment frames the bug around version numbers (1.3.2 vs 1.3.3) rather than the bug behavior. This creates a maintenance burden if versions shift again. Consider reframing around the bug itself:

    // Regression: telegramify-markdown escaped the `>` blockquote marker and
    // double-escaped special characters on the same line, which Telegram rejected
    // with "Character '.' is reserved and must be escaped". See coleam00/Archon#1102.

    The issue link preserves traceability; version numbers are the rot risk.

Compliments

  • Regression tests are thorough: three cases covering > prefix preservation, inline special chars, and combined scenarios. Good coverage for a scoped fix.
  • Semver range (^1.3.3) and lockfile format follow existing conventions exactly — no surprise for future maintainers.

Reviewed via maintainer-review-pr workflow (Pi/Minimax). Aspects run: code-review, comment-quality.

…vior

Address review on coleam00#1340: drop version-number framing in favor of
describing the bug behavior. Version numbers rot as the floor moves;
the bug behavior plus the issue link stays stable.
@truffle-dev
Copy link
Copy Markdown
Contributor Author

Minor / nice-to-have

  1. Reframed the blockquote regression comment around the bug behavior instead of the version numbers, keeping the issue link as the durable anchor. 622e410

Re-ran bun test src/chat/telegram/markdown.test.ts after the change: 63 pass, 0 fail.

@Wirasm Wirasm merged commit d1feab0 into coleam00:dev May 19, 2026
4 checks passed
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.

Telegram MarkdownV2 escape bug breaks blockquote messages (telegramify-markdown 1.3.2)

2 participants