Skip to content

feat(mail): draft to Gmail or a local Maildir, set per project; setup proposes mail backends - #1636

Merged
potiuk merged 5 commits into
apache:mainfrom
potiuk:setup/mail-backends-guidance
Oct 16, 2026
Merged

potiuk merged 5 commits into
apache:mainfrom
potiuk:setup/mail-backends-guidance

Conversation

@potiuk

@potiuk potiuk commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Maildir is now a real drafting backend. The security skills that draft mail (issue-import, issue-invalidate, issue-sync including the GHSA relay, cve-allocate) can now file their drafts into a local Maildir that Thunderbird or another mail client shows, as well as into Gmail. On Maildir they thread by In-Reply-To / References on the inbound Message-ID (PonyMail supplies it, or the root the tracker records). Before filing, they check for a draft already waiting with the new read-only maildir-draft-find. Before this, the Maildir tool existed but no skill could use it.
  • The drafting backend is set per project, and each person can override it. The project sets mail_create.backend in project.md; a person sets tools.mail_create in their own user.md. The rule is user.md, then project.md, then gmail, defined once in tools/gmail/draft-backends.md, which every draft site already links.
  • setup config proposes mail backends. Before this, config never mentioned them. For an ASF project, PonyMail and apache-projects are selected by default. The drafting choice is written to the project's configuration, or as a personal override in user.md once the user has seen the lines. Every install step (install.md 9c, 9d, 9e) now ends with a numbered what to do next list: run the commands, restart the agent, authenticate, verify. It says the claude.ai Gmail connector stays connected for reading only. Thunderbird's Repair Folder is documented for a draft that doesn't show up.

Type of change

  • Skill change (.claude/skills/<name>/) — eval fixtures updated below
  • Tool / bridge contract (tools/<system>/*.md)
  • Python package (tools/*/ with pyproject.toml)
  • Project template (projects/_template/)

Test plan

  • prek run --all-files passes
  • For Python packages touched: tools/maildir ruff, mypy and pytest pass (17 tests, 8 new for maildir-draft-find, including ~ expansion and bare Message-IDs)
  • For skill changes: new suites setup/step-config-mail 7/7 and security-issue-sync/step-draft-backend 5/5; re-run against the edited sections: setup/step-config-adversarial 5/5, setup/step-config-stamp 6/6, security-issue-import/step-0-preflight 3/3, security-issue-import/step-7-apply 3/3, security-issue-invalidate/step-5d-email-draft 2/2, security-issue-sync/step-ghsa-access-tier 5/5, security-cve-allocate/step-4-propose-updates 3/3. Self-eval only (Claude Code, Opus 5.5).
  • For skill behaviour changes: new eval fixtures included (12 cases across the two new suites)
  • Second read: roborev (codex, then gemini). Every finding was fixed in this PR: an apache-projects gap in the hand-over, the missing Gmail read path, Maildir offered but not wired up (the reason for the security-skill changes), ~ expansion, Message-ID parsing, and an empty-subject match. The last gemini pass on the branch is a Pass.

RFC-AI-0004 compliance

  • HITL — config writes a personal user.md override only after showing the lines; every MCP registration is printed for the user to run, never run by the agent
  • Vendor neutrality — drafting no longer requires Gmail; Maildir needs no account, credential or network
  • Write-access discipline — both drafting backends create drafts only; nothing is sent

Linked issues

None.

Notes for reviewers (optional)

  • tools/spec-loop/specs/adoption-and-setup.md (criterion 32) and adapters.md (criterion 6) describe the new behaviour. .last-sync is left where it was: it is 55 commits behind main for reasons unrelated to this PR, and bumping it here would claim those commits are synced.
  • Draft recap lines and the "Gmail draft ID" wording in the skills' recap sections still say Gmail; the Maildir recipe in draft-backends.md defines its own recap line.

Generative AI disclosure: drafted with Claude Code (Opus 5.5) and reviewed by the author.

🤖 Generated with Claude Code

@potiuk potiuk added family:setup setup-* skills capability:platform Framework / agent substrate skills (install, verify, doctor, override, status, setup bootstrap) labels Oct 15, 2026
@github-actions github-actions Bot added family:tools tools/* family:docs Docs, MISSION.md, READMEs contract:mail-source Tool capability: inbound-mail ingestion (mbox / IMAP / ...) contract:mail-create Tool capability: outbound mail composition (editable draft; sending is a separate human step) substrate:framework-dev Tool substrate: build / validate / eval the framework itself family:security security-* skills capability:intake Import external signal + sync tracker state capability:resolve Close-out: invalidate, dedupe, CVE allocate, announcement contract:mail-archive Tool capability: mailing-list / forum archive reads labels Oct 15, 2026
@potiuk potiuk changed the title feat(setup): propose mail backends in config and spell out next steps feat(mail): draft to Gmail or a local Maildir, set per project; setup proposes mail backends Oct 15, 2026
@potiuk potiuk added the enhancement New feature or request label Oct 15, 2026
@potiuk
potiuk force-pushed the setup/mail-backends-guidance branch from 1375ed8 to ce11568 Compare October 15, 2026 22:50
potiuk added a commit that referenced this pull request Oct 16, 2026
ruff 0.16.9 has segfaulted on CI runners while checking members whose
code the PR did not touch (vetted-ops on #1636, maildir on #1642),
failing prek for reasons unrelated to the change.

run-workspace-check.sh now treats an exit status above 128, a process
killed by a signal, as a crash rather than a finding, and runs that
member once more. A real finding (exit 1) is never retried, and a
second crash still fails the check.

Generated-by: Claude Code (Opus 5.5)
@potiuk
potiuk force-pushed the setup/mail-backends-guidance branch 4 times, most recently from df69e6f to b2ffcda Compare October 16, 2026 03:03
potiuk added a commit to Kaap10/magpie that referenced this pull request Oct 16, 2026
ruff 0.16.9 has segfaulted on CI runners while checking members whose
code the PR did not touch (vetted-ops on apache#1636, maildir on apache#1642),
failing prek for reasons unrelated to the change.

run-workspace-check.sh now treats an exit status above 128, a process
killed by a signal, as a crash rather than a finding, and runs that
member once more. A real finding (exit 1) is never retried, and a
second crash still fails the check.

Generated-by: Claude Code (Opus 5.5)
@potiuk
potiuk force-pushed the setup/mail-backends-guidance branch 2 times, most recently from 3698619 to 22eb59d Compare October 16, 2026 03:38
`setup config` now proposes the mail backends a mail-reading or
mail-drafting skill needs. For an ASF project it selects PonyMail and
apache-projects by default. For drafting it offers gmail-plaintext
(default) or the local Maildir backend for Thunderbird and other mail
clients, and never the claude.ai Gmail connector.

Each mail-backend install step now ends with a numbered "what to do
next" list: run the commands, restart the agent so the MCP tools load,
authenticate, verify. A new install Step 9e covers Maildir, including
Thunderbird's Repair Folder for a draft that does not show up; the
same note is in tools/maildir/README.md.

New eval suite: setup/step-config-mail (5 cases).

Generated-by: Claude Code (Opus 5.5)
…on override

The drafting backend is now Gmail or Maildir. The project sets it with
mail_create.backend in project.md; a person overrides it for themselves
with tools.mail_create in user.md. Every security skill that drafts mail
(issue-import, issue-invalidate, issue-sync, cve-allocate, the GHSA
relay) resolves it through draft-backends.md and, on Maildir, threads by
In-Reply-To / References on the inbound Message-ID.

tools/maildir gains maildir-draft-find, a read-only lookup the skills
use for the existing-draft check before filing a reply.

setup config records the drafting choice per project, or in the
person's user.md when the project's project.md is committed. It now
also checks for apache-projects when handing over the comdev install,
and says the claude.ai Gmail connector stays connected for reading.

New eval suite security-issue-sync/step-draft-backend (5 cases);
setup/step-config-mail grows to 7 cases.

Generated-by: Claude Code (Opus 5.5)
A drafts_path such as ~/Mail/<project>/Drafts reaches the tool
unexpanded when it is substituted into a command, so
maildir-draft-find found nothing and maildir-draft-create wrote under
./~ instead. Both now expand it.

maildir-draft-find also takes several Message-IDs per --message-id,
with or without angle brackets.

Generated-by: Claude Code (Opus 5.5)
maildir-draft-find normalised a subject such as "Re:" to an empty
string, which matched every draft in the Maildir.

Generated-by: Claude Code (Opus 5.5)
@potiuk
potiuk force-pushed the setup/mail-backends-guidance branch from 22eb59d to 5c2fed8 Compare October 16, 2026 03:51
@potiuk
potiuk merged commit 377ff91 into apache:main Oct 16, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

capability:intake Import external signal + sync tracker state capability:platform Framework / agent substrate skills (install, verify, doctor, override, status, setup bootstrap) capability:resolve Close-out: invalidate, dedupe, CVE allocate, announcement contract:mail-archive Tool capability: mailing-list / forum archive reads contract:mail-create Tool capability: outbound mail composition (editable draft; sending is a separate human step) contract:mail-source Tool capability: inbound-mail ingestion (mbox / IMAP / ...) enhancement New feature or request family:docs Docs, MISSION.md, READMEs family:security security-* skills family:setup setup-* skills family:tools tools/* substrate:framework-dev Tool substrate: build / validate / eval the framework itself

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant