@aitne-sh/aitne 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +295 -479
  2. package/agent-assets/agent-profiles/_safety.md +17 -2
  3. package/agent-assets/agent-profiles/routine-fetch-window.md +75 -40
  4. package/agent-assets/agent-profiles/wiki-agent.md +19 -0
  5. package/agent-assets/docs/features/messaging/bang-commands.md +161 -0
  6. package/agent-assets/docs/features/messaging/overview.md +3 -0
  7. package/agent-assets/docs/features/wiki/commands.md +222 -0
  8. package/agent-assets/docs/features/wiki/overview.md +145 -0
  9. package/agent-assets/docs/getting-started/03-what-can-this-do.md +18 -0
  10. package/agent-assets/docs/glossary.md +34 -0
  11. package/agent-assets/docs/guides/budget-and-cost-for-wiki.md +123 -0
  12. package/agent-assets/docs/guides/build-your-wiki.md +99 -0
  13. package/agent-assets/docs/guides/explore-with-trace-and-connect.md +169 -0
  14. package/agent-assets/docs/guides/maintain-wiki-health.md +168 -0
  15. package/agent-assets/docs/guides/multiple-wikis-for-multiple-domains.md +192 -0
  16. package/agent-assets/docs/guides/pause-the-agent.md +10 -3
  17. package/agent-assets/docs/guides/use-an-existing-obsidian-vault.md +156 -0
  18. package/agent-assets/docs/reference/cli-commands.md +24 -1
  19. package/agent-assets/docs/troubleshooting/wiki-ingest-full-blocked.md +96 -0
  20. package/agent-assets/docs/troubleshooting/wiki-write-failed.md +82 -0
  21. package/agent-assets/skills/context/SKILL.md +288 -17
  22. package/agent-assets/skills/external-services/SKILL.delegated.claude.md +2 -2
  23. package/agent-assets/skills/external-services/SKILL.delegated.codex.md +3 -3
  24. package/agent-assets/skills/external-services/SKILL.delegated.gemini.md +6 -6
  25. package/agent-assets/skills/external-services/SKILL.md +5 -3
  26. package/agent-assets/skills/external-services/SKILL.native.claude.md +49 -58
  27. package/agent-assets/skills/external-services/SKILL.native.codex.md +50 -58
  28. package/agent-assets/skills/external-services/SKILL.native.gemini.md +53 -56
  29. package/agent-assets/skills/mail/SKILL.md +5 -5
  30. package/agent-assets/skills/mail/SKILL.native.claude.md +57 -65
  31. package/agent-assets/skills/mail/SKILL.native.codex.md +73 -75
  32. package/agent-assets/skills/mail/SKILL.native.gemini.md +80 -75
  33. package/agent-assets/skills/management-task-register/SKILL.md +3 -3
  34. package/agent-assets/skills/notion/SKILL.native.claude.md +78 -82
  35. package/agent-assets/skills/notion/SKILL.native.codex.md +78 -80
  36. package/agent-assets/skills/notion/SKILL.native.gemini.md +91 -90
  37. package/agent-assets/skills/observations/SKILL.md +104 -14
  38. package/agent-assets/skills/roadmap/SKILL.md +19 -0
  39. package/agent-assets/skills/schedule/SKILL.md +44 -3
  40. package/agent-assets/skills/today/SKILL.md +25 -5
  41. package/agent-assets/skills/travel-time/SKILL.md +9 -0
  42. package/agent-assets/skills/wiki/wiki-ask/SKILL.md +32 -0
  43. package/agent-assets/skills/wiki/wiki-compile/SKILL.md +126 -0
  44. package/agent-assets/skills/wiki/wiki-connect/SKILL.md +75 -0
  45. package/agent-assets/skills/wiki/wiki-graduate/SKILL.md +45 -0
  46. package/agent-assets/skills/wiki/wiki-ingest/SKILL.md +182 -0
  47. package/agent-assets/skills/wiki/wiki-lint/SKILL.md +90 -0
  48. package/agent-assets/skills/wiki/wiki-trace/SKILL.md +72 -0
  49. package/agent-assets/skills/wiki/wiki-vault-rules/SKILL.md +145 -0
  50. package/agent-assets/task-flows/_partials/calendar-acquire.google_calendar.md +28 -9
  51. package/agent-assets/task-flows/_partials/calendar-acquire.outlook_calendar.md +26 -9
  52. package/agent-assets/task-flows/_partials/mail-acquire.gmail.md +51 -24
  53. package/agent-assets/task-flows/_partials/mail-acquire.outlook_mail.md +46 -16
  54. package/agent-assets/task-flows/_partials/notion-acquire.notion.md +29 -9
  55. package/agent-assets/task-flows/message.received.dm.md +35 -2
  56. package/agent-assets/task-flows/message.received.dm.native.claude.md +25 -26
  57. package/agent-assets/task-flows/message.received.dm.native.codex.md +30 -24
  58. package/agent-assets/task-flows/message.received.dm.native.gemini.md +36 -36
  59. package/agent-assets/task-flows/message.received.dm_first.md +43 -4
  60. package/agent-assets/task-flows/message.received.dm_first.native.claude.md +20 -20
  61. package/agent-assets/task-flows/message.received.dm_first.native.codex.md +22 -19
  62. package/agent-assets/task-flows/message.received.dm_first.native.gemini.md +28 -24
  63. package/agent-assets/task-flows/routine.fetch_window.md +51 -36
  64. package/agent-assets/task-flows/routine.morning_routine.md +12 -3
  65. package/agent-assets/task-flows/routine.morning_routine_initial.md +22 -1
  66. package/agent-assets/task-flows/scheduled.dm.md +477 -0
  67. package/agent-assets/task-flows/wiki.ask.md +11 -0
  68. package/agent-assets/task-flows/wiki.compile.md +28 -0
  69. package/agent-assets/task-flows/wiki.connect.md +12 -0
  70. package/agent-assets/task-flows/wiki.ingest_url.md +35 -0
  71. package/agent-assets/task-flows/wiki.lint.md +13 -0
  72. package/agent-assets/task-flows/wiki.trace.md +13 -0
  73. package/agent-assets/wiki-seeds/schemas/output.md +12 -0
  74. package/agent-assets/wiki-seeds/schemas/raw.md +13 -0
  75. package/agent-assets/wiki-seeds/schemas/wiki.md +12 -0
  76. package/agent-assets/wiki-seeds/taxonomy.md +13 -0
  77. package/package.json +21 -41
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: mail
3
- description: Load when the task touches Gmail and Gmail is in native mode bound to Claude (`nativeBackend === "claude"`). Use Claude's hosted Gmail connector directly; the daemon does not proxy Gmail. Non-Gmail accounts (IMAP/Outlook/iCloud/Yahoo) keep the direct `/api/mail/*` surface.
3
+ description: Load when the task touches Gmail and Gmail is in native mode bound to Claude (`nativeBackend === "claude"`). Use the in-session Gmail connector your harness exposes directly; the daemon does not proxy Gmail. Non-Gmail accounts (IMAP/Outlook/iCloud/Yahoo) keep the direct `/api/mail/*` surface.
4
4
  allowed-tools:
5
5
  - Bash(curl *)
6
6
  - Read
7
7
  ---
8
8
 
9
- # Mail (native — Claude Gmail connector)
9
+ # Mail (native — in-session Gmail connector)
10
10
 
11
11
  > **Refusal directive — read first.** Gmail is in `native` mode bound to
12
12
  > Claude. Do **NOT** call any of:
@@ -17,10 +17,11 @@ allowed-tools:
17
17
  > - `/api/mail/<gmail-account-id>/*` (per-account 410 inside the mail
18
18
  > handler; the daemon returns `{"error":"integration_native"}`)
19
19
  >
20
- > Reach Gmail through the `mcp__claude_ai_Gmail__*` MCP tools this
21
- > session already holds. The 410 is a contract, not an outage — the
22
- > route gate enforces native-mode exclusivity per
23
- > `INTEGRATION_NATIVE_MODE_DESIGN.md` §9.
20
+ > Reach Gmail through the in-session Gmail connector your harness exposes.
21
+ > Your tool menu lists every available tool at session startpick the
22
+ > Gmail one. The 410 is a contract, not an outage — the route gate
23
+ > enforces native-mode exclusivity per `INTEGRATION_NATIVE_MODE_DESIGN.md`
24
+ > §9.
24
25
 
25
26
  To confirm Gmail's current binding, read the `<integration_modes>`
26
27
  block in the system prompt (it carries `gmail="native"` and the
@@ -28,62 +29,49 @@ block in the system prompt (it carries `gmail="native"` and the
28
29
  fallback file `~/.personal-agent/integrations.md` shows the same
29
30
  information.
30
31
 
31
- ## Gmail — Claude's hosted Gmail connector (native MCP)
32
+ ## Gmail — in-session connector
32
33
 
33
- Tool namespace: `mcp__claude_ai_Gmail__`
34
+ The exact tool names depend on which Gmail connector your harness has
35
+ loaded. Inspect your tool menu at session start and pick the matching
36
+ capability. Capability-to-intent mapping you should look for:
34
37
 
35
- ### Read-class tools (`requiredCapabilities` floor)
38
+ ### Read-class capabilities (`requiredCapabilities` floor)
36
39
 
37
- | Capability | Tool | Use |
40
+ | Capability | What to do | How to use |
38
41
  |---|---|---|
39
- | `search` | `mcp__claude_ai_Gmail__search_threads` | List / search threads. Pass a Gmail query (`q="newer_than:1d in:inbox -label:Promotions"`). |
40
- | `read` | `mcp__claude_ai_Gmail__get_thread` | Fetch a full thread's messages by `threadId`. |
41
- | `label` | `mcp__claude_ai_Gmail__list_labels` | Enumerate available labels (label IDs are stable per user). |
42
+ | `search` | Search / list Gmail threads | Pass a Gmail query string (e.g. `q="newer_than:1d in:inbox -label:Promotions"`). |
43
+ | `read` | Fetch a single thread's messages | Pass the `threadId` returned by search. |
44
+ | `label` | Enumerate available labels | Read-only listing labels typically have stable IDs per user. |
42
45
 
43
- Canonical search call:
46
+ Canonical search → read flow:
44
47
 
45
- ```
46
- mcp__claude_ai_Gmail__search_threads(
47
- q="newer_than:1d in:inbox -label:Promotions",
48
- maxResults=50
49
- )
50
- ```
51
-
52
- Canonical read call (after the search returns `threadId`s):
53
-
54
- ```
55
- mcp__claude_ai_Gmail__get_thread(threadId="<id>")
56
- ```
48
+ 1. Search recent inbox threads with a Gmail-style query, capping result
49
+ count to a reasonable number (≈50 for hourly windows).
50
+ 2. For each interesting thread id, fetch the full thread to read its
51
+ messages.
57
52
 
58
- ### Draft-class tools (reversible — write-class, not destructive)
53
+ ### Draft-class capabilities (reversible — write-class, not destructive)
59
54
 
60
- | Capability | Tool | Confirmation |
55
+ | Capability | What to do | Confirmation |
61
56
  |---|---|---|
62
- | `draft` | `mcp__claude_ai_Gmail__create_draft` | Autonomous — drafts are inert until the user sends from the Gmail web UI. Prefer drafts over direct send. |
63
- | `draft` | `mcp__claude_ai_Gmail__list_drafts` | Read. |
57
+ | `draft` | Create or list drafts | Autonomous — drafts are inert until the user sends from the Gmail web UI. Prefer drafts over direct send. |
64
58
 
65
59
  Reply-thread chaining for drafts uses the same RFC-2822 headers documented in
66
- the direct-mode `mail` skill — Claude's connector exposes
67
- `inReplyTo` / `references` fields on `create_draft`. Fetch the thread, copy
60
+ the direct-mode `mail` skill — most connectors expose `inReplyTo` /
61
+ `references` fields on their create-draft function. Fetch the thread, copy
68
62
  the last message's `Message-Id` into `inReplyTo`, append it to `references`.
69
63
 
70
- ### Destructive tools (require explicit user confirmation)
71
-
72
- Per the registry's `gmail.backendConnectors.claude.destructiveTools`:
73
-
74
- - `mcp__claude_ai_Gmail__label_message`
75
- - `mcp__claude_ai_Gmail__label_thread`
76
- - `mcp__claude_ai_Gmail__unlabel_message`
77
- - `mcp__claude_ai_Gmail__unlabel_thread`
78
- - `mcp__claude_ai_Gmail__create_label`
79
-
80
- Claude's hosted Gmail connector deliberately ships **no** send / forward /
81
- delete / trash / archive surface. The destructive set here is restricted to
82
- label mutations and label-taxonomy edits. Apply the same
83
- destructive-confirm contract as delegated mode: summarise the plan
84
- ("apply label `urgent` to 4 threads"), wait for the user's explicit OK,
85
- then issue the call. The absolute-block layer
86
- (`docs/design/09-safety-cost.md` §6) continues to fire regardless of
64
+ ### Destructive capabilities (require explicit user confirmation)
65
+
66
+ Per the registry's `gmail.backendConnectors.claude.destructiveTools`, any
67
+ tool that mutates a thread's or message's labels — or modifies the user's
68
+ label taxonomy — counts as destructive in native:claude mode (the hosted
69
+ Gmail connector deliberately ships no send / forward / delete / trash /
70
+ archive surface, so the destructive set is restricted to label mutation
71
+ and label-taxonomy edits). Apply the same destructive-confirm contract as
72
+ delegated mode: summarise the plan ("apply label `urgent` to 4 threads"),
73
+ wait for the user's explicit OK, then issue the call. The absolute-block
74
+ layer (`docs/design/09-safety-cost.md` §6) continues to fire regardless of
87
75
  mode — secret-file reads, recursive deletes, and privilege escalation are
88
76
  denied in every posture.
89
77
 
@@ -101,7 +89,7 @@ routing decision is per account `kind`:
101
89
 
102
90
  | Selected account `kind` | Path |
103
91
  |---|---|
104
- | `gmail` | native MCP tools above |
92
+ | `gmail` | in-session Gmail connector (as above) |
105
93
  | `outlook` / `icloud` / `yahoo` / `imap` | direct: `/api/mail/<acct>/*` — see the base body for endpoint reference, account-resolution rules (§1), draft-vs-send contract, RFC-2822 reply-thread shape |
106
94
 
107
95
  Only the Gmail branch leaves the direct-mode surface. Account
@@ -119,25 +107,29 @@ verbatim; do **not** compute the hash yourself (LLM-side hashes drift
119
107
  between runs and from the delegated-sync-worker's hash, breaking
120
108
  `delegated → native` flip dedup).
121
109
 
110
+ **Batch when you have more than one thread.** A single-curl
111
+ `POST /api/observations/batch` accepting up to 200 items is the
112
+ preferred shape — see the `observations` skill for the envelope. The
113
+ single-item form below is for the rare "one new thread surfaced" case.
114
+
122
115
  ```bash
123
116
  curl -s -X POST http://localhost:8321/api/observations \
124
117
  -H 'Content-Type: application/json' \
125
118
  -d '{
126
- "source": "gmail",
127
- "type": "mail:lifecycle",
119
+ "source": "gmail:<accountId>",
128
120
  "ref": "<threadId>",
129
- "actor": "user",
130
- "receivedAt": "<ISO-8601 UTC>",
131
- "summary_text": "<one-line subject + sender + snippet>",
132
- "refs": {
133
- "threadId": "<id>",
134
- "subject": "<subject>",
135
- "from": "<from-address>"
136
- },
137
- "payload": <verbatim MCP response object>
121
+ "changeType": "created",
122
+ "actor": "agent",
123
+ "payload": <verbatim connector response object>
138
124
  }'
139
125
  ```
140
126
 
127
+ `actor` MUST be `"agent"` or `"system"` — the server rejects `"user"`
128
+ (user-authored observations arrive through the vault / mail watchers,
129
+ never this route). The `source` value follows the `"<integrationKey>:<scope>"`
130
+ convention so the hourly_check consumer's
131
+ `source_prefix=gmail:` filter matches.
132
+
141
133
  `/api/observations` is **never** native-gated — it is the chokepoint the
142
134
  native flow relies on for cross-mode dedup, so it stays reachable in
143
135
  every mode. The route also rejects late writes from a mode-flip race
@@ -151,10 +143,10 @@ window (§11.3.1) with HTTP 409; on 409 stop and re-read
151
143
  `routine.hourly_check.native.<backend>.md`. No drafts, labels,
152
144
  archives during the hourly pass — the morning / evening / DM
153
145
  flows are the write paths.
154
- - **Prefer drafts over send.** Claude's connector has no send surface,
155
- so drafts are the default channel here. If the user explicitly wants
156
- a message sent, point them at the Gmail web UI — explain that this
157
- configuration is draft-only by design.
146
+ - **Prefer drafts over send.** Hosted Gmail connectors typically expose
147
+ no send surface, so drafts are the default channel here. If the user
148
+ explicitly wants a message sent, point them at the Gmail web UI —
149
+ explain that this configuration is draft-only by design.
158
150
  - **Replies preserve the RFC-2822 chain.** Fetch the thread, copy
159
151
  `Message-Id` to `inReplyTo`, append it to `references`. The connector
160
152
  signs from the user's authenticated Google account; do not pass an
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: mail
3
- description: Load when the task touches Gmail and Gmail is in native mode bound to Codex (`nativeBackend === "codex"`). Use Codex's hosted Gmail MCP directly; the daemon does not proxy Gmail. Non-Gmail accounts (IMAP/Outlook/iCloud/Yahoo) keep the direct `/api/mail/*` surface.
3
+ description: Load when the task touches Gmail and Gmail is in native mode bound to Codex (`nativeBackend === "codex"`). Use the in-session Gmail connector your Codex harness exposes directly; the daemon does not proxy Gmail. Non-Gmail accounts (IMAP/Outlook/iCloud/Yahoo) keep the direct `/api/mail/*` surface.
4
4
  allowed-tools:
5
5
  - Bash(curl *)
6
6
  - Read
7
7
  ---
8
8
 
9
- # Mail (native — Codex Gmail MCP)
9
+ # Mail (native — in-session Gmail connector)
10
10
 
11
11
  > **Refusal directive — read first.** Gmail is in `native` mode bound to
12
12
  > Codex. Do **NOT** call any of:
@@ -16,72 +16,69 @@ allowed-tools:
16
16
  > - `POST /api/integrations/gmail/reconcile` (410)
17
17
  > - `/api/mail/<gmail-account-id>/*` (per-account 410)
18
18
  >
19
- > Reach Gmail through the `mcp__codex_apps__gmail._*` MCP tools this
20
- > Codex session already holds.
19
+ > Reach Gmail through the in-session Gmail connector your harness
20
+ > exposes. Your tool menu lists every available tool at session start
21
+ > pick the Gmail one. The 410 is a contract, not an outage — the route
22
+ > gate enforces native-mode exclusivity per
23
+ > `INTEGRATION_NATIVE_MODE_DESIGN.md` §9.
21
24
 
22
25
  To confirm the binding, read `<integration_modes>` (carries
23
26
  `gmail="native"`) and the `<integration-routing-table>` block in the
24
27
  session preamble. `~/.personal-agent/integrations.md` mirrors the same
25
28
  information.
26
29
 
27
- ## Gmail — Codex's hosted Gmail MCP (native)
30
+ ## Gmail — in-session connector
28
31
 
29
- Tool namespace: `mcp__codex_apps__gmail._`
32
+ The exact tool names depend on which Gmail connector your harness has
33
+ loaded. Inspect your tool menu at session start and pick the matching
34
+ capability. Codex-side hosted connectors typically expose a richer
35
+ surface than Claude's (search-emails / read-thread / draft + dedicated
36
+ send / forward / delete / archive / label tools), but the surface
37
+ varies by harness; rely on the capability classes below rather than
38
+ specific names.
30
39
 
31
- The Codex namespace terminates with `._`, so the bare suffix below is
32
- what you write after the namespace (e.g. `_search_emails` =
33
- `mcp__codex_apps__gmail._search_emails`).
40
+ ### Read-class capabilities (`requiredCapabilities` floor)
34
41
 
35
- ### Read-class tools (`requiredCapabilities` floor)
42
+ | Capability | What to do |
43
+ |---|---|
44
+ | `search` | Search Gmail with a query string. Most connectors expose a results-with-payload primitive plus an ids-only paging variant — use the ids-only flavor when the result count would overflow a single page. |
45
+ | `read` | Single-message read or full-thread read by id. If the connector exposes both, prefer the thread-walk primitive when you need the conversation context. |
46
+ | `label` | Enumerate available labels (read-only). |
36
47
 
37
- | Capability | Tool(s) | Use |
38
- |---|---|---|
39
- | `search` | `_search_emails`, `_search_email_ids` | Search; `_search_email_ids` returns ids only when you need to page. |
40
- | `read` | `_read_email`, `_read_email_thread` | Single message read; full-thread read. |
41
- | `label` | `_list_labels` | Enumerate available labels. |
48
+ Canonical search flow: invoke your connector's search function with
49
+ `query="newer_than:1d in:inbox -label:Promotions"` and `max_results=50`.
50
+ The exact argument names match the connector's schema (often `query` +
51
+ `max_results`); inspect the tool definition to confirm.
42
52
 
43
- Canonical search call:
53
+ Canonical thread read: invoke your connector's read-thread function
54
+ (or single-message-read + iterate) with the `thread_id` / `message_id`
55
+ returned by search.
44
56
 
45
- ```
46
- mcp__codex_apps__gmail._search_emails(
47
- query="newer_than:1d in:inbox -label:Promotions",
48
- max_results=50
49
- )
50
- ```
57
+ ### Draft-class capabilities (reversible — write-class, not destructive)
51
58
 
52
- Canonical thread read (after search returns thread/message ids):
59
+ | Capability | What to do | Confirmation |
60
+ |---|---|---|
61
+ | `draft` | Create a draft. Autonomous — drafts are inert until the user sends. Prefer drafts. |
62
+ | `draft` | List drafts (read). |
63
+ | `update_draft` | Mutate a not-yet-sent draft. Reversible — the user can still review before sending. Write-class but not destructive. |
53
64
 
54
- ```
55
- mcp__codex_apps__gmail._read_email_thread(thread_id="<id>")
56
- ```
65
+ Reply-thread chaining: most connectors expose RFC-2822 `in_reply_to` /
66
+ `references` fields on their create-draft function. Fetch the thread
67
+ first, copy the last message's `Message-Id` to `in_reply_to`, append it
68
+ to `references`.
57
69
 
58
- ### Draft-class tools (reversible write-class, not destructive)
70
+ ### Destructive capabilities (require explicit user confirmation)
59
71
 
60
- | Capability | Tool | Confirmation |
61
- |---|---|---|
62
- | `draft` | `_create_draft` | Autonomous — drafts are inert until the user sends. Prefer drafts. |
63
- | `draft` | `_list_drafts` | Read. |
64
- | `update_draft` | `_update_draft` | Reversible — `update_draft` mutates a not-yet-sent draft; the user can still review before sending. Write-class but not destructive. |
65
-
66
- Reply-thread chaining: the connector accepts RFC-2822 `in_reply_to` /
67
- `references` fields on `_create_draft`. Fetch the thread first, copy
68
- the last message's `Message-Id` to `in_reply_to`, append it to
69
- `references`.
70
-
71
- ### Destructive tools (require explicit user confirmation)
72
-
73
- Per the registry's `gmail.backendConnectors.codex.destructiveTools`:
74
-
75
- - `_send_email` — irreversible dispatch.
76
- - `_send_draft` — irreversible dispatch of a previously composed draft.
77
- - `_forward_emails` — irreversible dispatch.
78
- - `_delete_emails` — irreversible.
79
- - `_archive_emails` — reversible (archive can be unarchived) but
80
- user-visible and treated as destructive in the registry.
81
- - `_apply_labels_to_emails` — label mutation.
82
- - `_bulk_label_matching_emails` — mass label mutation.
83
- - `_create_label` — taxonomy edit.
84
- - `_batch_modify_email` — mass mutation.
72
+ Per the registry's `gmail.backendConnectors.codex.destructiveTools`,
73
+ the following capability classes are destructive in native:codex mode:
74
+
75
+ - **Send / forward** irreversible dispatch (compose-and-send, send a
76
+ previously composed draft, forward a thread).
77
+ - **Delete** — irreversible removal.
78
+ - **Archive** reversible but user-visible; treated as destructive.
79
+ - **Apply / bulk-apply labels** label mutation, single or mass.
80
+ - **Create label** taxonomy edit.
81
+ - **Batch modify** — mass mutation across many messages.
85
82
 
86
83
  Apply the destructive-confirm contract:
87
84
 
@@ -92,10 +89,10 @@ Apply the destructive-confirm contract:
92
89
  the absolute-block layer or the `deniedTools` deny list rejected it
93
90
  for a reason.
94
91
 
95
- The starter `deniedTools` set (e.g. `_send_email`) is pre-populated by
96
- the setup wizard for safety; the dashboard's Tool Permissions card is
97
- the surface for widening it. Calls into a denied tool fail before they
98
- land at the connector.
92
+ The starter `deniedTools` list (typically denies the send capability)
93
+ is pre-populated by the setup wizard for safety; the dashboard's Tool
94
+ Permissions card is the surface for widening it. Calls into a denied
95
+ tool fail before they reach the connector.
99
96
 
100
97
  ## Non-Gmail accounts (IMAP / Outlook / iCloud / Yahoo)
101
98
 
@@ -105,7 +102,7 @@ alongside this skill) is the authoritative list. Routing:
105
102
 
106
103
  | Selected account `kind` | Path |
107
104
  |---|---|
108
- | `gmail` | native MCP tools above |
105
+ | `gmail` | in-session Gmail connector (as above) |
109
106
  | `outlook` / `icloud` / `yahoo` / `imap` | direct: `/api/mail/<acct>/*` (see base body) |
110
107
 
111
108
  The base body's account-resolution rules (§1), send-vs-draft contract,
@@ -115,27 +112,28 @@ and RFC-2822 reply chain shape are unchanged for non-Gmail accounts.
115
112
 
116
113
  POST each materialised Gmail thread fetched in a routine to
117
114
  `/api/observations`. The daemon computes `contentHash` server-side via
118
- `@personal-agent/shared/observations-hash.ts`; pass `payload` verbatim:
115
+ `@personal-agent/shared/observations-hash.ts`; pass `payload` verbatim.
116
+
117
+ **Batch when you have more than one thread.** Use
118
+ `POST /api/observations/batch` with up to 200 items in a single
119
+ `observations[]` array (see the `observations` skill for the envelope).
120
+ The single-item form below is for the rare "one new thread surfaced"
121
+ case.
119
122
 
120
123
  ```bash
121
124
  curl -s -X POST http://localhost:8321/api/observations \
122
125
  -H 'Content-Type: application/json' \
123
126
  -d '{
124
- "source": "gmail",
125
- "type": "mail:lifecycle",
127
+ "source": "gmail:<accountId>",
126
128
  "ref": "<threadId>",
127
- "actor": "user",
128
- "receivedAt": "<ISO-8601 UTC>",
129
- "summary_text": "<one-line subject + sender + snippet>",
130
- "refs": {
131
- "threadId": "<id>",
132
- "subject": "<subject>",
133
- "from": "<from-address>"
134
- },
135
- "payload": <verbatim MCP response object>
129
+ "changeType": "created",
130
+ "actor": "agent",
131
+ "payload": <verbatim connector response object>
136
132
  }'
137
133
  ```
138
134
 
135
+ `actor` MUST be `"agent"` or `"system"` — the server rejects `"user"`.
136
+
139
137
  `/api/observations` is never gated. On HTTP 409 (lock-window race
140
138
  during a mode flip per §11.3.1), stop and re-read `<integration_modes>`
141
139
  — the integration has flipped under you.
@@ -145,14 +143,14 @@ during a mode flip per §11.3.1), stop and re-read `<integration_modes>`
145
143
  - **Hourly check is read-only** — inherits the constraint from
146
144
  `routine.hourly_check.native.codex.md`. No sends, archives, label
147
145
  writes during hourly.
148
- - **Prefer drafts over send.** `_create_draft` is autonomous;
149
- `_send_email` / `_send_draft` require explicit user OK.
146
+ - **Prefer drafts over send.** The create-draft capability is
147
+ autonomous; the send / send-draft capabilities require explicit user
148
+ OK.
150
149
  - **Replies preserve the RFC-2822 chain.** Pin `Message-Id` /
151
150
  `References` headers on the draft.
152
- - **Bulk operations: ask first.** A `_bulk_label_matching_emails` or
153
- `_batch_modify_email` call that would touch more than ~3 messages
154
- needs an explicit confirmation message summarising the criteria and
155
- the count.
151
+ - **Bulk operations: ask first.** A bulk-label or batch-modify call
152
+ that would touch more than ~3 messages needs an explicit confirmation
153
+ message summarising the criteria and the count.
156
154
  - **The reply account is implicit.** The connector signs from the
157
155
  authenticated Google account; do not pass an `accountId`.
158
156
  - **No `bcc` unless the user explicitly asks for it.**
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: mail
3
- description: Load when the task touches Gmail and Gmail is in native mode bound to Gemini (`nativeBackend === "gemini"`). Use Gemini CLI's google-workspace extension directly; the daemon does not proxy Gmail. Non-Gmail accounts (IMAP/Outlook/iCloud/Yahoo) keep the direct `/api/mail/*` surface.
3
+ description: Load when the task touches Gmail and Gmail is in native mode bound to Gemini (`nativeBackend === "gemini"`). Use the in-session Gmail connector your Gemini harness exposes directly; the daemon does not proxy Gmail. Non-Gmail accounts (IMAP/Outlook/iCloud/Yahoo) keep the direct `/api/mail/*` surface.
4
4
  allowed-tools:
5
5
  - Bash(curl *)
6
6
  - Read
7
7
  ---
8
8
 
9
- # Mail (native — Gemini google-workspace extension)
9
+ # Mail (native — in-session Gmail connector)
10
10
 
11
11
  > **Refusal directive — read first.** Gmail is in `native` mode bound to
12
12
  > Gemini. Do **NOT** call any of:
@@ -16,83 +16,86 @@ allowed-tools:
16
16
  > - `POST /api/integrations/gmail/reconcile` (410)
17
17
  > - `/api/mail/<gmail-account-id>/*` (per-account 410)
18
18
  >
19
- > Reach Gmail through the `mcp_google-workspace_gmail.*` MCP tools your
20
- > Gemini session already holds via the `google-workspace` extension.
19
+ > Reach Gmail through the in-session Gmail connector your harness
20
+ > exposes (typically Gemini CLI's `google-workspace` extension or a
21
+ > user-installed equivalent). Your tool menu lists every available tool
22
+ > at session start — pick the Gmail one.
21
23
 
22
24
  Confirm the binding by reading `<integration_modes>` (carries
23
25
  `gmail="native"`) and the `<integration-routing-table>` block in the
24
26
  session preamble. `~/.personal-agent/integrations.md` mirrors the same.
25
27
 
26
- ## Gmail — google-workspace extension (native MCP)
28
+ ## Gmail — in-session connector
27
29
 
28
- Tool namespace: `mcp_google-workspace_gmail.`
30
+ The exact tool names depend on which Gmail connector your harness has
31
+ loaded. Inspect your tool menu at session start and pick the matching
32
+ capability. Gemini CLI's `google-workspace` extension is the typical
33
+ provider here; its surface is leaner than Codex's (no dedicated
34
+ delete / forward — those compose from primitives, see below). Other
35
+ user-installed Gmail MCP servers may differ; rely on the capability
36
+ classes rather than specific tool names.
29
37
 
30
- Gemini CLI registers extension tools with single underscores and a
31
- `.` separator between server and tool, so the bare suffix below is what
32
- you write after the namespace (`search` =
33
- `mcp_google-workspace_gmail.search`).
38
+ ### Read-class capabilities (`requiredCapabilities` floor)
34
39
 
35
- ### Read-class tools (`requiredCapabilities` floor)
36
-
37
- | Capability | Tool | Use |
38
- |---|---|---|
39
- | `search` | `search` | Gmail search (`q` accepts the same query grammar as the web UI). |
40
- | `read` | `get` | Fetch a single message by `id` (the extension does not expose a thread-walk primitive; compose search + per-message `get`). |
41
- | `label` | `listLabels` | Enumerate available labels. |
42
-
43
- Canonical search call:
40
+ | Capability | What to do |
41
+ |---|---|
42
+ | `search` | Gmail search pass a query string in the same grammar as the web UI. |
43
+ | `read` | Fetch a single message by id. Some connectors expose no thread-walk primitive; compose search + per-message read in that case (see pattern below). |
44
+ | `label` | Enumerate available labels (read-only). |
44
45
 
45
- ```
46
- mcp_google-workspace_gmail.search(
47
- q="newer_than:1d in:inbox -label:Promotions",
48
- maxResults=50
49
- )
50
- ```
46
+ Canonical search flow: invoke your connector's search function with
47
+ `q="newer_than:1d in:inbox -label:Promotions"` and (if supported)
48
+ `maxResults=50`. See the Gemini-specific quirk below: some connectors
49
+ silently ignore `maxResults`.
51
50
 
52
- Read pattern (the extension lacks `getThread`, so compose):
51
+ Read pattern when the connector lacks a thread-walk primitive (compose
52
+ search + per-message read):
53
53
 
54
54
  ```
55
- hits = mcp_google-workspace_gmail.search(q="threadId:<id>", maxResults=100)
55
+ hits = <connector search>(q="threadId:<id>", maxResults=100)
56
56
  for msg_id in hits:
57
- mcp_google-workspace_gmail.get(id=msg_id)
57
+ <connector get message>(id=msg_id)
58
58
  ```
59
59
 
60
- ### Draft-class tools (reversible — write-class, not destructive)
60
+ ### Draft-class capabilities (reversible — write-class, not destructive)
61
61
 
62
- | Capability | Tool | Confirmation |
62
+ | Capability | What to do | Confirmation |
63
63
  |---|---|---|
64
- | `draft` | `createDraft` | Autonomous — drafts are inert until the user sends. Prefer drafts over `send`. |
65
- | `read_attachment` | `downloadAttachment` | Read. |
64
+ | `draft` | Create a draft. Autonomous — drafts are inert until the user sends. Prefer drafts over send. |
65
+ | `read_attachment` | Download an attachment (read). |
66
66
 
67
- `createDraft` accepts `inReplyTo` and `references` fields for
68
- RFC-2822 thread chaining — fetch the thread first, pin the headers.
67
+ The create-draft capability typically accepts `inReplyTo` and
68
+ `references` fields for RFC-2822 thread chaining — fetch the thread
69
+ first, pin the headers.
69
70
 
70
- ### Destructive tools (require explicit user confirmation)
71
+ ### Destructive capabilities (require explicit user confirmation)
71
72
 
72
- Per the registry's `gmail.backendConnectors.gemini.destructiveTools`:
73
+ Per the registry's `gmail.backendConnectors.gemini.destructiveTools`,
74
+ the following capability classes are destructive in native:gemini mode:
73
75
 
74
- - `send` — compose-and-send in one call (irreversible).
75
- - `sendDraft` — dispatch a previously composed draft (irreversible).
76
- - `modify` — apply / remove labels including the system `TRASH` label
76
+ - **Send** — compose-and-send in one call (irreversible).
77
+ - **Send draft** — dispatch a previously composed draft (irreversible).
78
+ - **Modify** — apply / remove labels including the system `TRASH` label
77
79
  (covers delete-by-trash; archive likewise via `INBOX` label removal).
78
- - `modifyThread` — same as `modify`, thread-scope.
79
- - `createLabel` — taxonomy edit.
80
- - `batchModify` — mass label mutation.
81
-
82
- The google-workspace extension exposes **no** dedicated `delete` or
83
- `forward` tool — those compose from primitives (`delete` = `modify` +
84
- add `TRASH`; `forward` = `send` with re-quoted body). The registry's
85
- `gemini.optionalCapabilities` reflect this honestly; do not infer parity
86
- the connector does not have. If the user asks to forward a message,
87
- fetch it, compose the body, and call `send` after the destructive
88
- confirmation.
80
+ - **Modify thread** — same as modify, thread-scope.
81
+ - **Create label** — taxonomy edit.
82
+ - **Batch modify** — mass label mutation.
83
+
84
+ Some Gemini-side connectors (notably the `google-workspace` extension)
85
+ expose **no** dedicated delete or forward tool — those compose from
86
+ primitives (delete = modify + add `TRASH`; forward = send with re-quoted
87
+ body). The registry's `gemini.optionalCapabilities` reflects this
88
+ honestly; do not infer parity the connector does not have. If the user
89
+ asks to forward a message, fetch it, compose the body, and call send
90
+ after the destructive confirmation.
89
91
 
90
92
  Apply the destructive-confirm contract:
91
93
 
92
94
  1. Summarise the plan in one line.
93
95
  2. Surface verbatim and wait for explicit user OK.
94
- 3. On OK, issue the call once. The starter `deniedTools` list (typically
95
- includes `send`) is enforced before the call lands; honour it.
96
+ 3. On OK, issue the call once. The starter `deniedTools` list
97
+ (typically includes the send capability) is enforced before the
98
+ call lands; honour it.
96
99
 
97
100
  The absolute-block layer (`docs/design/09-safety-cost.md` §6) continues
98
101
  to fire regardless of mode — recursive deletes, secret-file reads, and
@@ -105,7 +108,7 @@ resolves to a Gmail account. Routing:
105
108
 
106
109
  | Selected account `kind` | Path |
107
110
  |---|---|
108
- | `gmail` | native MCP tools above |
111
+ | `gmail` | in-session Gmail connector (as above) |
109
112
  | `outlook` / `icloud` / `yahoo` / `imap` | direct: `/api/mail/<acct>/*` (see base body) |
110
113
 
111
114
  The base body's account-resolution rules (§1), send-vs-draft contract,
@@ -117,27 +120,28 @@ for non-Gmail accounts.
117
120
  POST each materialised Gmail message fetched in a routine to
118
121
  `/api/observations`. The daemon computes `contentHash` server-side via
119
122
  the shared util in `@personal-agent/shared/observations-hash.ts`; pass
120
- `payload` verbatim:
123
+ `payload` verbatim.
124
+
125
+ **Batch when you have more than one message.** Use
126
+ `POST /api/observations/batch` with up to 200 items in one
127
+ `observations[]` array (see the `observations` skill for the envelope).
128
+ The single-item form below is for the rare "one new message surfaced"
129
+ case.
121
130
 
122
131
  ```bash
123
132
  curl -s -X POST http://localhost:8321/api/observations \
124
133
  -H 'Content-Type: application/json' \
125
134
  -d '{
126
- "source": "gmail",
127
- "type": "mail:lifecycle",
135
+ "source": "gmail:<accountId>",
128
136
  "ref": "<threadId-or-messageId>",
129
- "actor": "user",
130
- "receivedAt": "<ISO-8601 UTC>",
131
- "summary_text": "<one-line subject + sender + snippet>",
132
- "refs": {
133
- "threadId": "<id>",
134
- "subject": "<subject>",
135
- "from": "<from-address>"
136
- },
137
- "payload": <verbatim MCP response object>
137
+ "changeType": "created",
138
+ "actor": "agent",
139
+ "payload": <verbatim connector response object>
138
140
  }'
139
141
  ```
140
142
 
143
+ `actor` MUST be `"agent"` or `"system"` — the server rejects `"user"`.
144
+
141
145
  `/api/observations` is never gated. On HTTP 409 the integration has
142
146
  flipped during the lock window (§11.3.1) — stop and re-read
143
147
  `<integration_modes>`.
@@ -146,20 +150,21 @@ flipped during the lock window (§11.3.1) — stop and re-read
146
150
 
147
151
  - **Hourly check is read-only** — inherits the constraint from
148
152
  `routine.hourly_check.native.gemini.md`.
149
- - **Prefer drafts over send.** `createDraft` is autonomous; `send` /
150
- `sendDraft` need explicit user OK.
153
+ - **Prefer drafts over send.** The create-draft capability is
154
+ autonomous; send / send-draft need explicit user OK.
151
155
  - **Replies preserve the RFC-2822 chain.** Pin `inReplyTo` /
152
156
  `references` on the draft.
153
- - **Bulk operations: ask first.** `batchModify` and `modifyThread`
154
- calls touching more than ~3 messages need an explicit confirmation.
155
- - **The reply account is implicit** — the extension signs from the
157
+ - **Bulk operations: ask first.** Batch-modify and modify-thread calls
158
+ touching more than ~3 messages need an explicit confirmation.
159
+ - **The reply account is implicit** — the connector signs from the
156
160
  user's authenticated Google account.
157
161
  - **No `bcc` unless the user explicitly asks for it.**
158
- - **Gemini-specific quirk** (`maxResults` ignored on `search`): the
159
- google-workspace extension silently ignores `maxResults`; the result
160
- set is bounded only by the query window and Google's default. When
161
- the call returns more than expected, paginate via narrower `q=`
162
- windows rather than retrying with a smaller `maxResults`.
162
+ - **Gemini-specific quirk** (`maxResults` ignored on search): some
163
+ Gemini-side Gmail connectors silently ignore `maxResults`; the
164
+ result set is bounded only by the query window and the connector's
165
+ default. When the call returns more than expected, paginate via
166
+ narrower `q=` windows rather than retrying with a smaller
167
+ `maxResults`.
163
168
 
164
169
  ## Cost / audit
165
170