Skip to content

fix(email): preserve long cron report delivery - #53264

Open
petrakersten wants to merge 1 commit into
NousResearch:mainfrom
petrakersten:petra/fix-email-platform-fixes
Open

fix(email): preserve long cron report delivery#53264
petrakersten wants to merge 1 commit into
NousResearch:mainfrom
petrakersten:petra/fix-email-platform-fixes

Conversation

@petrakersten

@petrakersten petrakersten commented Jun 26, 2026

Copy link
Copy Markdown

Summary

  • Mark the email gateway adapter as long-message-preserving so live cron delivery does not apply the 4K chat-platform truncation guard before calling send().
  • Keep this PR intentionally narrow: SMTP/465 support is already on current main, and outbound/send-only mode is now handled separately in fix(email): support send-only gateway mode #57605.

Test Plan

  • scripts/run_tests.sh tests/gateway/test_email.py -q

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/gateway Gateway runner, session dispatch, delivery platform/email Email (IMAP/SMTP) adapter labels Jun 26, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related: #27680 (canonical open PR for implicit-TLS SMTPS/465) and the already-merged #46084 (SMTP_SSL-465 + IPv4 fallback in the old gateway/platforms/email.py path). This PR re-applies the 465 fix in the relocated plugins/platforms/email/adapter.py and additionally adds an outbound-only gateway mode and long cron/report body splitting — a superset variant, not a duplicate. Cross-linking so the 465 overlap is visible to reviewers.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for narrowing this to the cron-delivery problem. The current-main premise is real: gateway/delivery.py:430-451 truncates Email output because EmailAdapter has no capability flag.

Problems

  • plugins/platforms/email/adapter.py:428 declares splits_long_messages=True, but EmailAdapter.send() forwards one unchanged body to _send_email() (plugins/platforms/email/adapter.py:893-905), which creates one MIMEText body (:949). gateway/delivery.py:409-412 defines this flag as native adapter chunking, so this bypasses the guard without providing the advertised bound.
  • tests/gateway/test_email.py:270-273 only asserts the flag; it does not exercise delivery routing or SMTP output.

Suggested changes

  • Implement bounded native email chunking, or use a distinct capability for direct long-body transports.
  • Add a DeliveryRouter → EmailAdapter regression that proves a >4K report reaches the SMTP path without the truncation footer.

Automated hermes-sweeper review.

Comment thread plugins/platforms/email/adapter.py Outdated
# Email can carry report-sized plaintext bodies directly. Mark it as a
# long-message-preserving adapter so cron/live delivery does not apply the
# 4K chat-platform truncation guard before calling send().
splits_long_messages = True

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

gateway/delivery.py:409-412 treats this flag as a promise that send() chunks the full payload. EmailAdapter currently sends one unchanged MIMEText body (send()_send_email()), so please either implement bounded native chunking here or use a distinct capability for direct long-body email delivery.

@teknium1 teknium1 added sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 15, 2026
@petrakersten
petrakersten force-pushed the petra/fix-email-platform-fixes branch from f50ef12 to d6cd777 Compare July 25, 2026 21:44
@petrakersten

Copy link
Copy Markdown
Author

Addressed the sweeper findings in the current head d6cd777c3: Email now advertises a distinct direct-body capability (preserves_long_messages) rather than native chunking, and DeliveryRouter→EmailAdapter coverage proves a >4K body reaches SMTP unchanged. Fresh verification: git diff --check clean; pytest tests/gateway/test_delivery.py tests/gateway/test_email.py -q → 123 passed.

@GottZ GottZ left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This was generated by AI during triage.

Summary

Two open PRs address the same long-email truncation cause: #53264 adds a transport-specific preservation capability to the delivery router, while #68900 reuses the native-chunking capability even though Email sends one intact MIME body rather than splitting it.

Related pull requests

  • #53264 related — (+39/-2) — preferred, but coverage still incomplete: the diff introduces preserves_long_messages, routes full bodies past the 4K chat truncation guard, and avoids falsely claiming native chunking. The keep_open review on #53264 is only partially addressed: the regression test proves the full body reaches EmailAdapter.send(), but because that method is monkeypatched, it does not prove the body reaches _send_email() or the SMTP/MIME path unchanged.
  • #68900 duplicate — (+14/-0) — duplicate with an inaccurate capability contract: it sets splits_long_messages=True although the adapter does not split messages, and its test only asserts that flag rather than exercising delivery routing or SMTP output. The contributor discussion also identifies it as a duplicate of earlier #62000.

Duplicates

#68900 substantially duplicates the long-email preservation fix pursued by #53264 and was also identified in contributor discussion as a duplicate of #62000.

Suggested consolidation

Merge #53264 after adding a regression that exercises DeliveryRouter through the real EmailAdapter.send() to the mocked SMTP/_send_email() boundary and verifies the >4K body remains unchanged; this preserves the more accurate transport capability while fully addressing the keep_open review. Close #68900 as a duplicate because its splits_long_messages flag misrepresents the adapter behavior and provides weaker coverage.

Complex graph

flowchart LR
    classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
    classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
    classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
    classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
    classDef best stroke-width:3px,stroke:#b45309
    classDef target stroke-width:3px,stroke:#4338ca
    subgraph Dup53264 ["PRs duplicating each other"]
        P53264["PR #53264 (open)"]
        P68900["PR #68900 (open)"]
    end
    class P53264 open
    class P68900 open
    class P53264 target
    click P53264 "https://github.com/NousResearch/hermes-agent/pull/53264"
    click P68900 "https://github.com/NousResearch/hermes-agent/pull/68900"
Loading

Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed or no verify verdict yet (state tag in the node label).

Cross-PR triage: Reviewed 2 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 5 kB of PR diffs, <1 kB of issue/PR text, 2 kB of discussion (4 comments), 1 verify verdict. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

@petrakersten
petrakersten force-pushed the petra/fix-email-platform-fixes branch from d6cd777 to 0a336fe Compare July 29, 2026 18:18
@petrakersten

Copy link
Copy Markdown
Author

Addressed the latest cross-PR review in head 0a336fe99: the DeliveryRouter regression now keeps the real EmailAdapter.send() path and mocks only _send_email, proving the complete >4K body crosses the executor handoff to the SMTP/MIME boundary unchanged. Rebased onto current origin/main; git diff --check is clean; uv run --extra dev pytest tests/gateway/test_delivery.py tests/gateway/test_email.py -q → 123 passed.

@petrakersten
petrakersten force-pushed the petra/fix-email-platform-fixes branch from 0a336fe to f089e29 Compare July 31, 2026 23:05

@GottZ GottZ left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This was generated by AI during triage.

Delta since our previous triage comment

@petrakersten’s update corrects the coverage gap identified in our previous comment: #53264 now keeps the real EmailAdapter.send() path and mocks only _send_email, and the diff verifies that a >4K body reaches that boundary unchanged. @teknium1 also supplied contributor-level confirmation that #68900 still misuses the native-chunking contract and lacks equivalent router-to-email coverage.

Changed pull requests

  • #53264 related — (+131/-2) — preferred, prior condition now satisfied: the current diff adds the distinct preserves_long_messages capability and exercises DeliveryRouter through the real EmailAdapter.send() path to mocked _send_email, explicitly addressing the keep_open review on #53264.
  • #68900 duplicate — (+244/-1) — duplicate with an incorrect capability contract: despite the keep_open review on #68900, its diff still declares splits_long_messages=True without implementing bounded splitting and tests only the flag; @teknium1’s contributor review confirms that mismatch, while #53264 implements the suggested distinct capability and end-to-end boundary regression.

Suggested consolidation

The recommendation advances from conditional to merge #53264 and close #68900 as a duplicate because the required regression is now present in #53264’s diff, notwithstanding the current backlog-lane classification.

Complex graph unchanged since our previous triage comment.

Cross-PR triage: Reviewed 2 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 19 kB of PR diffs, <1 kB of issue/PR text, 4 kB of discussion (7 comments), 0 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

@petrakersten

Copy link
Copy Markdown
Author

Rebased onto current origin/main and resolved the tests/gateway/test_delivery.py conflict by preserving the new upstream Windows UTF-8 regression coverage alongside this PR’s long-email delivery regressions. New head: 07417ba9b. Verification: git diff --check clean; pytest tests/gateway/test_delivery.py tests/gateway/test_email.py -q → 51 passed. GitHub readback now reports mergeable=true; remaining blocked state has no visible check runs and requires maintainer review/approval.

@petrakersten
petrakersten force-pushed the petra/fix-email-platform-fixes branch from 07417ba to 4c72208 Compare August 13, 2026 18:19
@petrakersten

Copy link
Copy Markdown
Author

Maintainer check-in: the branch is narrow, rebased, and the previous review findings have been addressed. We are reducing our actively maintained upstream queue and do not want to keep refreshing P3 contributions without a maintainer signal. If preserving long email delivery is useful upstream, we are happy to respond to review or reshape it. If there is no maintainer interest or direction by 3 September 2026, we will close it and retain the local mitigation.

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

Labels

comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have platform/email Email (IMAP/SMTP) adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants