1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
#+TITLE: Triage Intake — Personal Gmail Source
#+AUTHOR: Craig Jennings & Claude
#+DATE: 2026-05-26
# Source plugin for the triage-intake engine. See triage-intake.org for the
# contract and the Phase A-D orchestration. This file declares ONE source.
* Source: personal-gmail
:PROPERTIES:
:ORDER: 20
:ENABLED: mcp google-docs-personal present
:ANCHOR: epoch
:SUBAGENT_OVER: 50
:END:
** Scan
Personal Gmail unread in the inbox since the anchor:
#+begin_src text
mcp__google-docs-personal__listMessages q="is:unread in:inbox after:<anchor-epoch>" maxResults=100
#+end_src
⚠ *Express the cutoff as the literal UNIX epoch* — =after:1778856990=, not =after:YYYY/MM/DD=. Gmail's =after:YYYY/MM/DD= operator only supports day resolution; the =YYYY/MM/DD HH:MM:SS= form is NOT valid syntax — Gmail parses the space as a term separator, treats =HH:MM:SS= as a search term that never matches, and returns 0 results, silently masking unread mail. The engine supplies =<anchor-epoch>= because this source declares =ANCHOR: epoch=.
⚠ *Do NOT add =-category:promotions -category:social=.* That filter masked 67 promo+social messages across two runs (2026-05-04, 2026-05-06), both needing a follow-up sweep. Pull the full unfiltered set; the trash-leaning bias in Classify handles promotions and social directly.
** Classify
Bias: *trash-leaning* — personal Gmail is high noise volume.
- *Noise-trash:* newsletters, Substacks, retail/SaaS marketing, social digests, redundant aggregator digests (Notion/Miro daily), wrong-recipient mail, past-event calendar artifacts.
- *Noise-keep:* receipts, order confirmations, statements — low value but worth the audit trail.
- *FYI:* substantive personal mail with no action owed.
- *Action:* an explicit ask, a reply owed, a time-sensitive personal matter.
** Render
#+begin_example
**Personal Gmail — N unread.** <one-line classification summary>
- Action: <items, if any, with thread links>
- FYI: <items, if any>
- Noise: N trash candidates, M keep
#+end_example
Omit the block if zero unread.
** Actions
- trash :: =mcp__google-docs-personal__trashMessage= id=<message-id> (recoverable from Gmail Trash for 30 days)
- mark-read :: =mcp__google-docs-personal__modifyMessageLabels= id=<message-id> removeLabelIds=["UNREAD"]
- star+read :: =mcp__google-docs-personal__modifyMessageLabels= id=<message-id> addLabelIds=["STARRED"] removeLabelIds=["UNREAD"]
- attach-fetch:: =.ai/scripts/gmail-fetch-attachments.py --profile personal --message-id <message-id> --output-dir <PATH>=
|