@aitne-sh/aitne 0.1.3 → 0.1.4

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 (87) hide show
  1. package/README.md +151 -147
  2. package/agent-assets/agent-profiles/conversational.md +23 -1
  3. package/agent-assets/agent-profiles/observer.md +15 -0
  4. package/agent-assets/agent-profiles/routine-fetch-window.md +128 -0
  5. package/agent-assets/agent-profiles/routine.md +16 -0
  6. package/agent-assets/agent-profiles/task.md +15 -0
  7. package/agent-assets/docs/concepts/auth-health.md +25 -9
  8. package/agent-assets/docs/concepts/backends-and-tiers.md +40 -4
  9. package/agent-assets/docs/concepts/costs-and-quotas.md +87 -25
  10. package/agent-assets/docs/concepts/delegated-mode.md +7 -13
  11. package/agent-assets/docs/concepts/memory-model.md +14 -1
  12. package/agent-assets/docs/concepts/observations.md +19 -1
  13. package/agent-assets/docs/concepts/process-keys.md +5 -0
  14. package/agent-assets/docs/concepts/routines.md +22 -10
  15. package/agent-assets/docs/concepts/safety-model.md +3 -8
  16. package/agent-assets/docs/concepts/skills.md +36 -1
  17. package/agent-assets/docs/features/integrations/calendar.md +74 -3
  18. package/agent-assets/docs/features/integrations/git.md +4 -4
  19. package/agent-assets/docs/features/integrations/github.md +75 -107
  20. package/agent-assets/docs/features/lifestyle/git.md +169 -22
  21. package/agent-assets/docs/features/messaging/overview.md +10 -1
  22. package/agent-assets/docs/features/routines/morning-routine.md +1 -1
  23. package/agent-assets/docs/getting-started/01-what-is-this.md +30 -12
  24. package/agent-assets/docs/getting-started/02-first-steps.md +15 -4
  25. package/agent-assets/docs/getting-started/03-what-can-this-do.md +17 -2
  26. package/agent-assets/docs/guides/install-and-run.md +10 -1
  27. package/agent-assets/docs/guides/setup-wizard.md +43 -6
  28. package/agent-assets/docs/guides/switch-default-backend.md +7 -3
  29. package/agent-assets/docs/reference/skills.md +10 -1
  30. package/agent-assets/docs/troubleshooting/auth-failed.md +27 -8
  31. package/agent-assets/docs/troubleshooting/quota-exhausted.md +35 -12
  32. package/agent-assets/skills/context/SKILL.md +6 -0
  33. package/agent-assets/skills/external-services/SKILL.md +4 -0
  34. package/agent-assets/skills/external-services/SKILL.native.claude.md +320 -0
  35. package/agent-assets/skills/external-services/SKILL.native.codex.md +243 -0
  36. package/agent-assets/skills/external-services/SKILL.native.gemini.md +237 -0
  37. package/agent-assets/skills/mail/SKILL.md +42 -14
  38. package/agent-assets/skills/mail/SKILL.native.claude.md +175 -0
  39. package/agent-assets/skills/mail/SKILL.native.codex.md +165 -0
  40. package/agent-assets/skills/mail/SKILL.native.gemini.md +169 -0
  41. package/agent-assets/skills/management-task-modify/SKILL.md +2 -1
  42. package/agent-assets/skills/management-task-stop/SKILL.md +2 -2
  43. package/agent-assets/skills/notify/SKILL.md +4 -4
  44. package/agent-assets/skills/notion/SKILL.md +6 -0
  45. package/agent-assets/skills/notion/SKILL.native.claude.md +202 -0
  46. package/agent-assets/skills/notion/SKILL.native.codex.md +166 -0
  47. package/agent-assets/skills/notion/SKILL.native.gemini.md +167 -0
  48. package/agent-assets/skills/observations/SKILL.md +7 -0
  49. package/agent-assets/skills/project-doc/SKILL.md +6 -0
  50. package/agent-assets/skills/reading/SKILL.md +2 -0
  51. package/agent-assets/skills/roadmap/SKILL.md +7 -0
  52. package/agent-assets/skills/today/SKILL.md +7 -0
  53. package/agent-assets/skills/user-interview/SKILL.md +1 -1
  54. package/agent-assets/skills/user-profile/SKILL.md +7 -0
  55. package/agent-assets/task-flows/_partials/calendar-acquire.google_calendar.md +119 -0
  56. package/agent-assets/task-flows/_partials/calendar-acquire.outlook_calendar.md +101 -0
  57. package/agent-assets/task-flows/_partials/mail-acquire.gmail.md +113 -0
  58. package/agent-assets/task-flows/_partials/mail-acquire.outlook_mail.md +97 -0
  59. package/agent-assets/task-flows/_partials/notion-acquire.notion.md +104 -0
  60. package/agent-assets/task-flows/git.project.refresh_architecture.md +24 -1
  61. package/agent-assets/task-flows/message.received.dm.md +3 -0
  62. package/agent-assets/task-flows/message.received.dm.native.claude.md +76 -0
  63. package/agent-assets/task-flows/message.received.dm.native.codex.md +57 -0
  64. package/agent-assets/task-flows/message.received.dm.native.gemini.md +70 -0
  65. package/agent-assets/task-flows/message.received.dm_first.md +3 -0
  66. package/agent-assets/task-flows/message.received.dm_first.native.claude.md +56 -0
  67. package/agent-assets/task-flows/message.received.dm_first.native.codex.md +48 -0
  68. package/agent-assets/task-flows/message.received.dm_first.native.gemini.md +54 -0
  69. package/agent-assets/task-flows/routine.evening_review.md +28 -1
  70. package/agent-assets/task-flows/routine.fetch_window.md +93 -0
  71. package/agent-assets/task-flows/routine.hourly_check.md +44 -5
  72. package/agent-assets/task-flows/routine.monthly_review.md +13 -2
  73. package/agent-assets/task-flows/routine.morning_routine.md +55 -42
  74. package/agent-assets/task-flows/routine.morning_routine_initial.md +37 -38
  75. package/agent-assets/task-flows/routine.roadmap_refresh.md +38 -46
  76. package/agent-assets/task-flows/routine.today_refresh.md +53 -96
  77. package/agent-assets/task-flows/routine.weekly_review.md +40 -17
  78. package/agent-assets/task-flows/scheduled.dm.md +13 -11
  79. package/agent-assets/task-flows/scheduled.task.md +2 -2
  80. package/agent-assets/task-flows/setup.initial.md +5 -4
  81. package/agent-assets/task-flows/setup.update.md +1 -1
  82. package/agent-assets/templates/README.md +13 -6
  83. package/package.json +4 -4
  84. package/scripts/regen-skill-fixtures.mjs +39 -0
  85. package/agent-assets/task-flows/routine.hourly_check.delegated.claude.md +0 -405
  86. package/agent-assets/task-flows/routine.hourly_check.delegated.codex.md +0 -400
  87. package/agent-assets/task-flows/routine.hourly_check.delegated.gemini.md +0 -404
@@ -0,0 +1,175 @@
1
+ ---
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.
4
+ allowed-tools:
5
+ - Bash(curl *)
6
+ - Read
7
+ ---
8
+
9
+ # Mail (native — Claude Gmail connector)
10
+
11
+ > **Refusal directive — read first.** Gmail is in `native` mode bound to
12
+ > Claude. Do **NOT** call any of:
13
+ >
14
+ > - `POST /api/integrations/gmail/exec` (returns `410` with
15
+ > `X-Integration-Mode: native`)
16
+ > - `POST /api/integrations/gmail/reconcile` (410)
17
+ > - `/api/mail/<gmail-account-id>/*` (per-account 410 inside the mail
18
+ > handler; the daemon returns `{"error":"integration_native"}`)
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.
24
+
25
+ To confirm Gmail's current binding, read the `<integration_modes>`
26
+ block in the system prompt (it carries `gmail="native"` and the
27
+ `<integration-routing-table>` block names the bound backend). The
28
+ fallback file `~/.personal-agent/integrations.md` shows the same
29
+ information.
30
+
31
+ ## Gmail — Claude's hosted Gmail connector (native MCP)
32
+
33
+ Tool namespace: `mcp__claude_ai_Gmail__`
34
+
35
+ ### Read-class tools (`requiredCapabilities` floor)
36
+
37
+ | Capability | Tool | Use |
38
+ |---|---|---|
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
+
43
+ Canonical search call:
44
+
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
+ ```
57
+
58
+ ### Draft-class tools (reversible — write-class, not destructive)
59
+
60
+ | Capability | Tool | Confirmation |
61
+ |---|---|---|
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. |
64
+
65
+ 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
68
+ the last message's `Message-Id` into `inReplyTo`, append it to `references`.
69
+
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
87
+ mode — secret-file reads, recursive deletes, and privilege escalation are
88
+ denied in every posture.
89
+
90
+ The `deniedTools` list (from `<integration_modes>` / dashboard Tool
91
+ Permissions card) still applies. A tool name on the deny list returns
92
+ an error before the call lands.
93
+
94
+ ## Non-Gmail accounts (IMAP / Outlook / iCloud / Yahoo)
95
+
96
+ Per-account gating: the `/api/mail/*` 410 only fires when the resolved
97
+ `accountId` is `kind=gmail`. IMAP / Outlook / iCloud / Yahoo accounts
98
+ remain fully reachable through the direct-mode endpoints — `accounts.md`
99
+ (materialised alongside this skill) lists every active account, and the
100
+ routing decision is per account `kind`:
101
+
102
+ | Selected account `kind` | Path |
103
+ |---|---|
104
+ | `gmail` | native MCP tools above |
105
+ | `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
+
107
+ Only the Gmail branch leaves the direct-mode surface. Account
108
+ resolution, send-vs-draft preferences, and per-account quotas are
109
+ unchanged for non-Gmail accounts.
110
+
111
+ ## Persisting observations from native fetches
112
+
113
+ When you fetch Gmail data during a routine (e.g. `routine.hourly_check`'s
114
+ Step 0a), POST each materialised thread to the daemon's
115
+ `/api/observations` endpoint so subsequent runs can dedup. The daemon
116
+ computes `contentHash` server-side via
117
+ `@personal-agent/shared/observations-hash.ts` — pass the raw `payload`
118
+ verbatim; do **not** compute the hash yourself (LLM-side hashes drift
119
+ between runs and from the delegated-sync-worker's hash, breaking
120
+ `delegated → native` flip dedup).
121
+
122
+ ```bash
123
+ curl -s -X POST http://localhost:8321/api/observations \
124
+ -H 'Content-Type: application/json' \
125
+ -d '{
126
+ "source": "gmail",
127
+ "type": "mail:lifecycle",
128
+ "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>
138
+ }'
139
+ ```
140
+
141
+ `/api/observations` is **never** native-gated — it is the chokepoint the
142
+ native flow relies on for cross-mode dedup, so it stays reachable in
143
+ every mode. The route also rejects late writes from a mode-flip race
144
+ window (§11.3.1) with HTTP 409; on 409 stop and re-read
145
+ `<integration_modes>` — the integration has flipped under you.
146
+
147
+ ## Decision rules
148
+
149
+ - **Hourly check is read-only.** Native variants inherit the
150
+ "External services are read-only this hour" constraint from
151
+ `routine.hourly_check.native.<backend>.md`. No drafts, labels,
152
+ archives during the hourly pass — the morning / evening / DM
153
+ 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.
158
+ - **Replies preserve the RFC-2822 chain.** Fetch the thread, copy
159
+ `Message-Id` to `inReplyTo`, append it to `references`. The connector
160
+ signs from the user's authenticated Google account; do not pass an
161
+ `accountId` (the connector picks).
162
+ - **Bulk operations: ask first.** Label mutations that touch more than
163
+ ~3 threads in one call should be summarised and confirmed before
164
+ issuing — even when the destructive-confirm dance covers the tool
165
+ itself.
166
+ - **No `bcc` unless the user explicitly asks for it.**
167
+
168
+ ## Cost / audit
169
+
170
+ Every native MCP call lands one `agent_actions` row of type `mcp_call`
171
+ with `provider="claude"`, the tool name, `inputTokens` /
172
+ `outputTokens`, and the parent `event_id` / `processKey` attached. The
173
+ cost dashboard's `nativeAttribution` column (§14.4) joins those rows
174
+ to the integration registry by `toolNamespace` prefix so the operator
175
+ can see the spend shift after a flip.
@@ -0,0 +1,165 @@
1
+ ---
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.
4
+ allowed-tools:
5
+ - Bash(curl *)
6
+ - Read
7
+ ---
8
+
9
+ # Mail (native — Codex Gmail MCP)
10
+
11
+ > **Refusal directive — read first.** Gmail is in `native` mode bound to
12
+ > Codex. Do **NOT** call any of:
13
+ >
14
+ > - `POST /api/integrations/gmail/exec` (returns `410` with
15
+ > `X-Integration-Mode: native`)
16
+ > - `POST /api/integrations/gmail/reconcile` (410)
17
+ > - `/api/mail/<gmail-account-id>/*` (per-account 410)
18
+ >
19
+ > Reach Gmail through the `mcp__codex_apps__gmail._*` MCP tools this
20
+ > Codex session already holds.
21
+
22
+ To confirm the binding, read `<integration_modes>` (carries
23
+ `gmail="native"`) and the `<integration-routing-table>` block in the
24
+ session preamble. `~/.personal-agent/integrations.md` mirrors the same
25
+ information.
26
+
27
+ ## Gmail — Codex's hosted Gmail MCP (native)
28
+
29
+ Tool namespace: `mcp__codex_apps__gmail._`
30
+
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`).
34
+
35
+ ### Read-class tools (`requiredCapabilities` floor)
36
+
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. |
42
+
43
+ Canonical search call:
44
+
45
+ ```
46
+ mcp__codex_apps__gmail._search_emails(
47
+ query="newer_than:1d in:inbox -label:Promotions",
48
+ max_results=50
49
+ )
50
+ ```
51
+
52
+ Canonical thread read (after search returns thread/message ids):
53
+
54
+ ```
55
+ mcp__codex_apps__gmail._read_email_thread(thread_id="<id>")
56
+ ```
57
+
58
+ ### Draft-class tools (reversible — write-class, not destructive)
59
+
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.
85
+
86
+ Apply the destructive-confirm contract:
87
+
88
+ 1. Compose a one-line plan ("send reply to alice@example.com Re:
89
+ Proposal"; "archive 4 newsletter threads matching `from:digest@...`").
90
+ 2. Surface the plan to the user verbatim and wait for an explicit OK.
91
+ 3. On OK, issue the call once. Do not retry on `policy_violation` —
92
+ the absolute-block layer or the `deniedTools` deny list rejected it
93
+ for a reason.
94
+
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.
99
+
100
+ ## Non-Gmail accounts (IMAP / Outlook / iCloud / Yahoo)
101
+
102
+ Per-account gating: `/api/mail/*` 410 only fires when
103
+ `accountId` resolves to a Gmail account. `accounts.md` (materialised
104
+ alongside this skill) is the authoritative list. Routing:
105
+
106
+ | Selected account `kind` | Path |
107
+ |---|---|
108
+ | `gmail` | native MCP tools above |
109
+ | `outlook` / `icloud` / `yahoo` / `imap` | direct: `/api/mail/<acct>/*` (see base body) |
110
+
111
+ The base body's account-resolution rules (§1), send-vs-draft contract,
112
+ and RFC-2822 reply chain shape are unchanged for non-Gmail accounts.
113
+
114
+ ## Persisting observations from native fetches
115
+
116
+ POST each materialised Gmail thread fetched in a routine to
117
+ `/api/observations`. The daemon computes `contentHash` server-side via
118
+ `@personal-agent/shared/observations-hash.ts`; pass `payload` verbatim:
119
+
120
+ ```bash
121
+ curl -s -X POST http://localhost:8321/api/observations \
122
+ -H 'Content-Type: application/json' \
123
+ -d '{
124
+ "source": "gmail",
125
+ "type": "mail:lifecycle",
126
+ "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>
136
+ }'
137
+ ```
138
+
139
+ `/api/observations` is never gated. On HTTP 409 (lock-window race
140
+ during a mode flip per §11.3.1), stop and re-read `<integration_modes>`
141
+ — the integration has flipped under you.
142
+
143
+ ## Decision rules
144
+
145
+ - **Hourly check is read-only** — inherits the constraint from
146
+ `routine.hourly_check.native.codex.md`. No sends, archives, label
147
+ writes during hourly.
148
+ - **Prefer drafts over send.** `_create_draft` is autonomous;
149
+ `_send_email` / `_send_draft` require explicit user OK.
150
+ - **Replies preserve the RFC-2822 chain.** Pin `Message-Id` /
151
+ `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.
156
+ - **The reply account is implicit.** The connector signs from the
157
+ authenticated Google account; do not pass an `accountId`.
158
+ - **No `bcc` unless the user explicitly asks for it.**
159
+
160
+ ## Cost / audit
161
+
162
+ Native MCP calls land `agent_actions` rows of type `mcp_call` with
163
+ `provider="codex"`, the tool name, and the parent `event_id` /
164
+ `processKey`. The cost dashboard joins these to the registry by
165
+ `toolNamespace` prefix for the `nativeAttribution` rollup (§14.4).
@@ -0,0 +1,169 @@
1
+ ---
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.
4
+ allowed-tools:
5
+ - Bash(curl *)
6
+ - Read
7
+ ---
8
+
9
+ # Mail (native — Gemini google-workspace extension)
10
+
11
+ > **Refusal directive — read first.** Gmail is in `native` mode bound to
12
+ > Gemini. Do **NOT** call any of:
13
+ >
14
+ > - `POST /api/integrations/gmail/exec` (returns `410` with
15
+ > `X-Integration-Mode: native`)
16
+ > - `POST /api/integrations/gmail/reconcile` (410)
17
+ > - `/api/mail/<gmail-account-id>/*` (per-account 410)
18
+ >
19
+ > Reach Gmail through the `mcp_google-workspace_gmail.*` MCP tools your
20
+ > Gemini session already holds via the `google-workspace` extension.
21
+
22
+ Confirm the binding by reading `<integration_modes>` (carries
23
+ `gmail="native"`) and the `<integration-routing-table>` block in the
24
+ session preamble. `~/.personal-agent/integrations.md` mirrors the same.
25
+
26
+ ## Gmail — google-workspace extension (native MCP)
27
+
28
+ Tool namespace: `mcp_google-workspace_gmail.`
29
+
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`).
34
+
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:
44
+
45
+ ```
46
+ mcp_google-workspace_gmail.search(
47
+ q="newer_than:1d in:inbox -label:Promotions",
48
+ maxResults=50
49
+ )
50
+ ```
51
+
52
+ Read pattern (the extension lacks `getThread`, so compose):
53
+
54
+ ```
55
+ hits = mcp_google-workspace_gmail.search(q="threadId:<id>", maxResults=100)
56
+ for msg_id in hits:
57
+ mcp_google-workspace_gmail.get(id=msg_id)
58
+ ```
59
+
60
+ ### Draft-class tools (reversible — write-class, not destructive)
61
+
62
+ | Capability | Tool | Confirmation |
63
+ |---|---|---|
64
+ | `draft` | `createDraft` | Autonomous — drafts are inert until the user sends. Prefer drafts over `send`. |
65
+ | `read_attachment` | `downloadAttachment` | Read. |
66
+
67
+ `createDraft` accepts `inReplyTo` and `references` fields for
68
+ RFC-2822 thread chaining — fetch the thread first, pin the headers.
69
+
70
+ ### Destructive tools (require explicit user confirmation)
71
+
72
+ Per the registry's `gmail.backendConnectors.gemini.destructiveTools`:
73
+
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
77
+ (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.
89
+
90
+ Apply the destructive-confirm contract:
91
+
92
+ 1. Summarise the plan in one line.
93
+ 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
+
97
+ The absolute-block layer (`docs/design/09-safety-cost.md` §6) continues
98
+ to fire regardless of mode — recursive deletes, secret-file reads, and
99
+ privilege escalation are denied in every posture.
100
+
101
+ ## Non-Gmail accounts (IMAP / Outlook / iCloud / Yahoo)
102
+
103
+ Per-account gating: `/api/mail/*` 410 only fires when `accountId`
104
+ resolves to a Gmail account. Routing:
105
+
106
+ | Selected account `kind` | Path |
107
+ |---|---|
108
+ | `gmail` | native MCP tools above |
109
+ | `outlook` / `icloud` / `yahoo` / `imap` | direct: `/api/mail/<acct>/*` (see base body) |
110
+
111
+ The base body's account-resolution rules (§1), send-vs-draft contract,
112
+ RFC-2822 reply chain shape, and bulk-operation discipline are unchanged
113
+ for non-Gmail accounts.
114
+
115
+ ## Persisting observations from native fetches
116
+
117
+ POST each materialised Gmail message fetched in a routine to
118
+ `/api/observations`. The daemon computes `contentHash` server-side via
119
+ the shared util in `@personal-agent/shared/observations-hash.ts`; pass
120
+ `payload` verbatim:
121
+
122
+ ```bash
123
+ curl -s -X POST http://localhost:8321/api/observations \
124
+ -H 'Content-Type: application/json' \
125
+ -d '{
126
+ "source": "gmail",
127
+ "type": "mail:lifecycle",
128
+ "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>
138
+ }'
139
+ ```
140
+
141
+ `/api/observations` is never gated. On HTTP 409 the integration has
142
+ flipped during the lock window (§11.3.1) — stop and re-read
143
+ `<integration_modes>`.
144
+
145
+ ## Decision rules
146
+
147
+ - **Hourly check is read-only** — inherits the constraint from
148
+ `routine.hourly_check.native.gemini.md`.
149
+ - **Prefer drafts over send.** `createDraft` is autonomous; `send` /
150
+ `sendDraft` need explicit user OK.
151
+ - **Replies preserve the RFC-2822 chain.** Pin `inReplyTo` /
152
+ `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
156
+ user's authenticated Google account.
157
+ - **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`.
163
+
164
+ ## Cost / audit
165
+
166
+ Native MCP calls land `agent_actions` rows of type `mcp_call` with
167
+ `provider="gemini"`, the tool name, and the parent `event_id` /
168
+ `processKey`. The cost dashboard joins them to the registry by
169
+ `toolNamespace` prefix for the `nativeAttribution` rollup (§14.4).
@@ -187,7 +187,8 @@ adds them, surface them verbatim.
187
187
  - Does NOT migrate entity files when `output_path` changes; only
188
188
  future runs honor the new path.
189
189
  - Does NOT auto-confirm "this looks right" — Notify-tier means a real
190
- user-facing confirmation in the user's preferred language.
190
+ user-facing confirmation. Output language: follow
191
+ `<output_language_policy>`.
191
192
 
192
193
  ## API summary
193
194
 
@@ -66,8 +66,8 @@ If no row matches, DM:
66
66
  DELETE on a managed task is **Notify tier** (§13.1) AND removes a
67
67
  recurring commitment that the user themselves set up. Both safety
68
68
  invariants ("destructive ops require user confirmation" from
69
- CLAUDE.md, plus the Notify-tier policy) demand a real DM confirmation
70
- in the user's preferred language. Never auto-stop.
69
+ CLAUDE.md, plus the Notify-tier policy) demand a real DM confirmation.
70
+ Output language: follow `<output_language_policy>`. Never auto-stop.
71
71
 
72
72
  > Stop `mt_42` Zoom check (daily 10:00 JST · last run ok 3 new)? It
73
73
  > won't auto-resume.
@@ -71,9 +71,9 @@ rule above bars *introducing* such enumeration in any other surface.)
71
71
 
72
72
  ### Language and style
73
73
 
74
- Respond in the user's preferred language. Follow `user/profile.md`
75
- Communication Style and the Character block in your system prompt.
76
- Keep technical terms in original form.
74
+ Output language: follow `<output_language_policy>`. Tone: follow
75
+ `user/profile.md` Communication Style and the Character block in your
76
+ system prompt. Keep technical terms in original form.
77
77
 
78
78
  ### Compactness
79
79
 
@@ -128,7 +128,7 @@ the default; see Step 4a's awareness gate). This section owns format
128
128
  rules for the rare evening where the gate plus a positive trigger
129
129
  clears the bar.
130
130
 
131
- ### Content (in user's preferred language)
131
+ ### Content (follows `<output_language_policy>`)
132
132
 
133
133
  1. **The agent-discovered thing the user needs to know** — the
134
134
  specific item that cleared the awareness gate. Lead with substance.
@@ -9,6 +9,12 @@ allowed-tools:
9
9
 
10
10
  # Notion API Reference
11
11
 
12
+ Output language: follow `<output_language_policy>`. **Property names**
13
+ defined in the user's Notion database are Policy A (the API contract —
14
+ never translate them; pass them through verbatim). **Property values**
15
+ and page body content the agent fills are Policy C (write in
16
+ `<settings primary_language>`).
17
+
12
18
  Base URL: `http://localhost:8321`. All calls via `curl -s` with
13
19
  `Content-Type: application/json` on POST/PATCH/PUT. URL-encode spaces in paths.
14
20