Table of Contents generated with DocToc
Every drafted email that relates to a tracking issue should attach to the original inbound Gmail thread — the thread whose threadId was recorded when the tracker was imported. The Gmail API threads most reliably when a draft carries a threadId; other mail clients (Thunderbird, Outlook, Apple Mail, the recipient's own client) commonly fall back to subject-based threading via the MIME In-Reply-To / References headers and the subject line.
Whether threadId is actually available to the skills depends on the drafting backend the user has configured — see draft-backends.md:
| Backend | threadId attach | Subject fallback |
|---|---|---|
oauth_curl (opt-in) | yes — guaranteed | n/a (always attaches) |
claude_ai_mcp (default) | no — the MCP does not plumb it through | always |
The two threading paths available to the skills, in preferred order:
threadId-attached draft — the first-choice path. Requires the oauth_curl backend. Use whenever the inbound threadId is known and the user has configured that backend.claude_ai_mcp backend; also the fallback on oauth_curl when the threadId cannot be resolved.The call shape (signature, kwargs, no-send rule) per backend lives in operations.md — Drafting backends; the rules on which thread to use and what the other fields look like live here.
threadId when known. Whatever the recipient change — a reporter reply, an ASF-security relay request, a PMC credit question, a follow-up asking for a PoC — the draft should attach to the inbound tracker's threadId. A triager reading the Gmail conversation view should see every exchange on a single tracker in one place; if threading breaks, that history scatters across two conversations.Re: <root subject>, never a fabricated new one. Gmail‘s own threading survives without matching subjects when threadId is set, but other clients commonly fall back to subject-based threading. A drifted subject looks like a broken conversation on half the world’s mail readers. The root subject is the subject of the first message on the inbound thread — not the last reply's subject line, which Gmail may have displayed with a prefix trim.To: may differ from the original correspondents. It is fine to address a draft to a specific person (an ASF security-team member who relayed the report, a named PMC member, an individual reporter) even if the original inbound root was addressed to a list. Threading does not require recipient overlap; it requires threadId or (as the fallback) a matching subject plus the right In-Reply-To / References headers.threadId is unavailablethreadId is the first-choice path, but the skills must also work in cases where it cannot be resolved or the backend does not support it:
tools.gmail.draft_backend: claude_ai_mcp (the default). The claude.ai Gmail MCP does not accept threadId on create_draft; every draft created via this backend uses the subject-matched path. See draft-backends.md for the one-time switch to the oauth_curl backend.../github/issue-template.md for the field role).threadId in that field is stale (the thread was deleted or archived out of the user's Gmail search index).threadId (rare, but possible if the user has moved the thread between accounts).In these cases, create the draft with threadId omitted but with the matching subject line from the inbound message. Gmail will start a new conversation on the sender‘s side, but most other clients (and Gmail’s own subject-fallback behaviour on the recipient's side) will still thread the reply by subject. This is not as good as a threadId-attached draft, but it is substantially better than either fabricating a new subject or not drafting at all.
Surface the degraded threading in the skill's proposal so the user knows which path the draft took:
threadId (via oauth_curl backend).” — the good case.claude_ai_mcp backend — threadId not supported). Gmail shows it as a new conversation server-side; the recipient's client will most likely thread it via the Re: <subject> match.” — the default-backend case.threadId was unavailable because <reason>).” — oauth_curl backend but threadId missing for some other reason.When the fallback kicks in, record the reason on the tracker's status comment so the next sync run can see why a new Gmail thread appeared. Do not silently drop to fallback — it changes the shape of the conversation the reporter sees.
When fallback is not appropriate. Some cases genuinely warrant stopping rather than drafting on a mismatched subject. Examples:
threadId nor a matching subject to use (typically when the tracker has never been linked to any inbound thread at all — a bug, usually a missed import step). Stop and surface it; drafting with no thread context at all is worse than no draft.When the inbound report arrives via an ASF forwarder rather than directly from the external reporter, the drafting shape changes slightly (different To: / Cc:, relay-specific body language) but the threading rules above are unchanged: prefer threadId; fall back to the inbound subject when it is not available. See asf-relay.md.