Repository navigation
Conversation
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: needs maintainer review before merge. What this changesAdds automatic text direction to authored HTML bodies, converted plain-text lines, and signatures across Gmail composition commands. Example: Reply with “Hi Dana,” followed by “תודה! אשלח את הדוח (PDF) עד יום שלישי.”
Review scores
ProductKind: Bug fix · Worth it: Yes · Fix scope: Complete Merge readiness✅ Ready for maintainer review Keep open: this PR fixes a demonstrated rendering bug that remains on main; no actionable defects were found, and passing current-head checks clear the previous CI blocker. Priority: P2 Before mergeNone. FindingsNone. Agent review detailsHow this fits togetherGmail compose commands combine caller-supplied bodies, notes, signatures, and quoted messages into MIME submitted through the existing Gmail send and draft APIs. flowchart LR
A[CLI bodies and notes] --> B[Shared text conversion]
B --> C[Signatures and quotes]
C --> D[MIME serialization]
D --> E[Gmail send and draft APIs]
E --> F[Mail client rendering]
Technical reviewBest possible solution: Land the shared direction handling while preserving supplied plain text, explicit inner direction, whole HTML documents, signatures, quoted content, and raw MIME. Do we have a high-confidence way to reproduce the issue? Current-main source exposes the unmarked authored-text path, corroborated by the contributor's before/after Gmail screenshots and failing-main/passing-branch live draft transcript; no target code was run during review. Is this the best way to solve the issue? The change fixes direction at the existing shared composition owners, with narrowly justified document detection and separator changes that preserve the demonstrated rendering and MIME contracts. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against f9052a583e87. Provenance checked
TestingProof path: shipped entry point. SecurityNone. EvidenceWhat I checked:
Likely related people:
Review metrics
LabelsLabel changes:
Label justifications:
Rating scale6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior. WorkflowClawSweeper edits this one comment on every review. Comment HistoryReview history (1 earlier review cycle)
Reviewed October 23, 2026, 1:46 AM ET / 05:46 UTC (Revision 2). |
The conversions between plain text and HTML that compose uses were spread over three files: composeText in gmail_compose.go, escapeTextToHTML in gmail_reply.go (though forward, signatures and drafts use it too), and htmlToPlainText with its helpers in gmail_send_signature.go. Move them into gmail_compose_text.go, next to the existing gmail_compose_text_test.go, before adding another conversion beside them. No behavior change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Give the text the author writes its own direction in the HTML part, so it reads correctly next to right-to-left text. Unmarked, a Hebrew body renders left to right and scrambled in Gmail Web and Apple Mail, and an English message quoted in a reply written in Gmail's Hebrew interface shows its punctuation at the wrong end, since that reply wraps everything in dir="rtl". Plain text gog turns into HTML (a --body above a quote or beside a draft's signature, a forward's --note, a plain-text --signature-file) now gets one <div dir="auto"> per line, a blank line <div dir="auto"><br></div>, as Gmail's mobile apps write it, one div to a line of HTML. dir="auto" gives each line the direction of its first letter, as Unicode and HTML do for plain text, where one wrapper would give a mixed message the direction of its first line. HTML the author gives (--body-html, --note-html, and gmail autoreply's --body-html) is trimmed, along with a leading byte order mark, and goes into one <div dir="auto"> before the signature and quote are added; dir attributes inside it still apply. HTML laid out as a whole document, opening with a doctype, an <html>, <head> or <body> tag, or an element that belongs in a document's head such as <style>, goes in as given, since a div around it would move its head into the body. The signature block is marked dir="auto" too. The text now ends in a block, so one <br> leaves a blank line after it, as in Gmail: before a reply's quote, where two would add a line, and after a forward's note, which loses its bare <div>. A document, which may end inline, and a reply with no text get two. A draft's plain body, converted for its signature, is trimmed first, as a reply's is, so a body file's final newline doesn't become a blank line. Text parts are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
a6fa1e6 to
5633912
Compare
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5633912 to
2d56428
Compare
|
@clawsweeper re-review |
|
🦞👀 Re-review progress:
|
What
People use gog in place of Gmail's own interface, so by default what gog writes should match what Gmail writes. Gmail's apps mark the direction of the text you write; gog writes yours into the HTML part with no direction at all, so it takes whatever direction surrounds it. That breaks in two ways:
תודה, דנה! אשלח את הדוח (PDF) עד יום שלישי.reads with its parts out of order and the period at the wrong end. Gmail Web doesn't take a direction from a message's language, even when it labels the message Hebrew.<div dir="rtl">, and gog's English text shows with its punctuation at the wrong end:.Thanks, Dana! I'll send the report (PDF) by Tuesday.Both show in Gmail Web; see the screenshots under Behavior proof.
Changes
This covers every command that composes a message:
gmail send(with or without--quote),reply,reply-all,forward,autoreply, andgmail drafts create,update,reply,reply-allandforward. The choices rest on the Unicode and HTML standards for text whose direction isn't known, on what Gmail's own apps write, and on delivered test messages in Gmail Web and Apple Mail.<div dir="auto">per line, with a blank line as<div dir="auto"><br></div>. That's a--bodyabove a quote or beside a draft's signature, a forward's--note, and a plain-text--signature-file.dir="auto"gives each line the direction of its first letter, as the standards do for plain text: the Unicode bidirectional algorithm decides direction separately for each paragraph, and in plain text a newline ends one; HTML appliesdir="auto"paragraph by paragraph in<pre>and<textarea>. Gmail's mobile apps write this markup, and Mastodon moved to the same paragraph-by-paragraph rule. One<div>around the whole body isn't enough: it takes the direction of its first line, and in a separate delivered test it left a Hebrew sentence underHi Dana,scrambled. Gmail Web marks the composer's own direction instead, which gog doesn't know.--body-html,--note-htmland their file forms) goes into one<div dir="auto">, added before the signature and the quote. gog doesn't split or rewrite the HTML it's handed, anddirattributes inside it still apply, so the paragraphs of a mixed-language message can carry their own.<div>to a whole HTML document: one that opens with a doctype or an<html>,<head>or<body>tag, or with what belongs in a document's head (a<base>,<link>,<meta>,<style>or<title>). Someone who hands over a whole document has laid it out themselves, so the conservative assumption is that it goes through as it is; a<div>around it would also move what belongs in its head, styles included, into the body. A quote or signature still follows it, as before.<div dir="auto" class="gmail_signature">, so it keeps its own direction whatever the body's. Gmail marks its signature block's direction too.<br>after the author's text, as Gmail writes it. The text now ends in a block, so a reply's former two<br>before its quote would add a blank line; with one, the spacing, and the text part Gmail rebuilds on send, are as before in the messages tested. A whole document, which may end in inline text, and a reply with no text get two. A forward's note follows the same rule, in place of its former bare<div>.Plain text you give goes into the text part unchanged, and a message with no HTML part, or one sent as is with
--raw-file, isn't touched. The first commit moves the compose text conversions, which were spread over three files (composeText,escapeTextToHTML, andhtmlToPlainTextwith its helpers), intogmail_compose_text.gobeside its tests, with no change in behavior.docs/gmail-workflows.mddescribes the marking.Open #1251 (
--html-from-text) also turns the author's plain text into HTML, withescapeTextToHTML; whichever of the two lands second should switch that call todirectedTextToHTML, so text converted on request gets the same per-line marking.Behavior proof
In Gmail Web
Replies and a message sent from one account to another with a build of
mainand with this branch, as Gmail Web shows the delivered copies: a Hebrew reply, a reply that mixes English and Hebrew lines, and a Hebrew message given as HTML. The last two rows are a reply started in Gmail's Hebrew interface, quoting an English reply from gog. For each of the four messages gog sent, from both builds (the Hebrew reply, the mixed reply, the Hebrew HTML message and the English reply), the text part Gmail rebuilt on send came out byte for byte the same.mainmain--body-html,main--body-html, this branchmainDrafts, read back with
gogLive against a personal Gmail account (
personalis an account alias); nothing is sent.proof_body_direction.py(below; Python 3 standard library plusgog) inserts a synthetic source message withgmail.users.messages.insert. It then saves adrafts replywith a plain body that mixes English and Hebrew lines, adrafts replywith an HTML body, adrafts forwardwith a plain note, adrafts createwith an HTML body and a plain-text--signature-file, and adrafts createwhose body is a whole HTML document; the other commands share these paths. Reading each draft back withgog gmail raw, it checks how the HTML part opens, up to where the quote opens, and, for the plain body and the plain note, that the text/plain part opens with the text as given and has no invisible direction characters (all after removing carriage returns). It prints HTML one block or<br>per line. At the end it runsgmail trashon every draft and source message it recorded; its last check counts the trash commands that succeeded.Run against a build of current
mainwithout this change (gog-main: the four HTML checks fail, exit 1), then a build of this branch (gog-branch: all nine checks pass, exit 0):proof_body_direction.pyTesting
TestComposedTextKeepsItsOwnDirectionchecks everything above the quote in the HTML part of a sent message, a draft and a reply: the author's text in its marked block exactly once, the signature block after it, one<br>before the quote, and a whole document unwrapped with its two. Its plain text has Windows line ends, a leading line break, a whitespace-only line and characters to escape.TestHTMLDocumentsAreNotWrappedcovers which HTML goes in as given (a doctype, an XML prolog,<html>,<HEAD>,<body>after a byte order mark and a comment,<style>,<meta>, a self-closing<link>) and which is wrapped (<header>, text before<html>, a paragraph from a file with a byte order mark).TestGmailForward_HTMLDocumentNotecovers a forward note given as a whole document, andTestApplyQuoteToBodiesWithoutTextOpensWithTwoBreaksa quoted reply with no text.gmailSignatureOpenconstant; two forward signature tests that differed only in the command are now one test over both),TestApplyQuoteToBodiesShowsPlainReplyInBothParts,TestQuoteLinesKeepTheirDirection, andTestRunGmailAutoReply_RepliesAndArchives, which now also checks the autoreply's HTML.dirfrom the lines, the wrapper or the signature; convert plain text the old way in replies, notes, drafts or signature files; or break the escaping, whitespace-only lines, Windows line ends, the line breaks between lines, either trimming, the byte order mark, the empty-input or document check, a document-detection rule (comments, byte order mark, leading text, doctype,<head>,<style>,<meta>,<link>, self-closing tags, exact tag names), any of the separator's cases, or the forward note's spacing.make cigreen.🤖 Generated with Claude Code