@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
@@ -21,9 +21,10 @@ ask_examples:
21
21
  - How do I re-login to Claude?
22
22
  locale: en-US
23
23
  created: 2026-04-25
24
- updated: 2026-04-25
24
+ updated: 2026-05-04
25
25
  related:
26
26
  - concepts/auth-health
27
+ - concepts/costs-and-quotas
27
28
  - features/operations/backend-routing
28
29
  ---
29
30
 
@@ -36,17 +37,35 @@ related:
36
37
 
37
38
  ## Most Likely Causes
38
39
 
39
- 1. **Token expired** (Codex, Gemini API).
40
- 2. **Claude credentials rotated** out of the keychain.
41
- 3. **Scope changed** (e.g. Claude Max plan was downgraded).
40
+ 1. **Provider API key revoked or rotated** the most common cause
41
+ on a healthy install. Re-paste the key on `/settings/models`.
42
+ 2. **Subscription-fallback login expired** when no API key was
43
+ registered (the daemon was running on the CLI's local login —
44
+ `claude`, `codex login`, `gemini auth` — and that session timed
45
+ out). The recommended fix is to register an API key.
46
+ 3. **Account-level scope change** at the provider (key disabled,
47
+ project deleted, billing suspended). For cloud providers
48
+ (Bedrock / Vertex / Foundry / Azure OpenAI / Gemini-Vertex),
49
+ IAM-role / service-account changes show up the same way.
42
50
 
43
51
  ## Diagnostic Steps
44
52
 
45
53
  1. Click the pill to see the recovery hint.
46
- 2. For Claude: `claude` CLI login, the daemon picks up the new
47
- credentials on probe refresh.
48
- 3. For Codex / Gemini: paste a fresh token / API key on
49
- `/settings/models`.
54
+ 2. Check `/settings/models` the backend card shows whether it is
55
+ running on a registered API key (the supported path) or on the
56
+ subscription fallback. The `SubscriptionAuthWarning` banner
57
+ appears whenever any backend is on the fallback.
58
+ 3. If on the API key, paste a fresh key on `/settings/models` — the
59
+ daemon mirrors it into `process.env` and re-probes immediately.
60
+ 4. If on the subscription fallback, the recommended fix is to
61
+ register an API key on `/settings/models` (or one of the cloud-
62
+ provider options — see
63
+ [Use a Cloud Provider for Models](../guides/use-cloud-providers.md)).
64
+ If you cannot or do not want to, run the corresponding CLI login
65
+ (`claude`, `codex login`, `gemini auth`) and the daemon picks up
66
+ the new credentials on the next probe. Note that this fallback
67
+ is not provider-supported for automated agent use — see
68
+ [Costs and Quotas](../concepts/costs-and-quotas.md).
50
69
 
51
70
  ## Confirming the Fix
52
71
 
@@ -4,13 +4,14 @@ slug: troubleshooting/quota-exhausted
4
4
  title: Quota Exhausted
5
5
  id: quota-exhausted
6
6
  aliases:
7
- - max5 limit hit
7
+ - api quota exceeded
8
+ - rate limit
8
9
  - opus window
9
- - subscription limit
10
10
  category: troubleshooting
11
11
  summary: |
12
12
  A backend reported a quota error and the router fell over to the
13
- fallback. Either wait for the window to refresh or upgrade the plan.
13
+ fallback. Wait for the provider window to refresh, raise your API
14
+ spending limit, or pin a different model.
14
15
  section: quota-exhausted
15
16
  tags:
16
17
  - troubleshooting
@@ -18,13 +19,15 @@ tags:
18
19
  - backends
19
20
  status: stable
20
21
  ask_examples:
21
- - Why am I seeing "subscription limit reached"?
22
- - When does the Opus window reset?
22
+ - Why did Aitne fall over to the fallback backend?
23
+ - Why is my Anthropic API call returning a quota error?
23
24
  locale: en-US
24
25
  created: 2026-04-25
25
- updated: 2026-04-25
26
+ updated: 2026-05-04
26
27
  related:
27
28
  - concepts/costs-and-quotas
29
+ - concepts/auth-health
30
+ - guides/use-cloud-providers
28
31
  ---
29
32
 
30
33
  # Quota Exhausted
@@ -37,16 +40,36 @@ related:
37
40
 
38
41
  ## Most Likely Causes
39
42
 
40
- 1. **5-hour Opus window** burned by a heavy routine cluster.
41
- 2. **Daily Sonnet bucket** hit on a long-running session.
42
- 3. **Gemini per-day cap** for `gemini-2.5-flash` reached on the free
43
- tier.
43
+ 1. **Provider rate limit** on your API key (Anthropic / OpenAI /
44
+ Google) the supported path. Check the provider console for the
45
+ per-minute / per-day caps tied to your billing.
46
+ 2. **Gemini per-day cap** for `gemini-2.5-flash` reached on the free
47
+ tier (`GEMINI_API_KEY` without billing).
48
+ 3. **Cloud-provider quota** — Bedrock / Vertex / Foundry / Azure
49
+ OpenAI / Gemini-Vertex enforce their own per-region / per-model
50
+ quotas. The error surfaces the same way as a direct-API quota.
51
+ 4. **Subscription fallback exhausted** — no API key registered, so
52
+ the backend is running on the CLI's local subscription login.
53
+ The underlying provider's subscription limits then apply (e.g.
54
+ Claude's rolling 5-hour Opus window on a Max plan login). The
55
+ recommended fix is to register an API key on `/settings/models`;
56
+ the fallback is not provider-supported for automated agent use.
57
+ See [Costs and Quotas](../concepts/costs-and-quotas.md).
44
58
 
45
59
  ## Diagnostic Steps
46
60
 
47
61
  1. Open `/analytics` and look at the by-backend rollup.
48
- 2. The "next reset" timestamp on Claude's card tells you when the
49
- rolling window refreshes.
62
+ 2. Check `/settings/models` to confirm whether the affected backend
63
+ is on a registered API key (the `SubscriptionAuthWarning` banner
64
+ is *absent*) or on the subscription fallback (banner *present*).
65
+ 3. If on an API key, open the provider console and verify your
66
+ account's spending / rate-limit settings. For cloud providers,
67
+ open the matching console (AWS / GCP / Azure) and check the
68
+ per-region / per-model quota.
69
+ 4. If on the subscription fallback, the backend card shows the
70
+ "next reset" timestamp for the rolling window. Consider
71
+ registering an API key — see
72
+ [Costs and Quotas](../concepts/costs-and-quotas.md).
50
73
 
51
74
  ## Confirming the Fix
52
75
 
@@ -8,6 +8,12 @@ allowed-tools:
8
8
 
9
9
  # Context File Update Guide
10
10
 
11
+ Output language: follow `<output_language_policy>`. Context files are
12
+ Policy B — H2/H3 headers from `agent-assets/templates/` are skeleton
13
+ (English); body prose, bullets, and summaries are written in
14
+ `<settings primary_language>`. Preserve user-customized headers
15
+ verbatim (whichever language the user rewrote them in).
16
+
11
17
  Context files are the agent's working memory, stored in the **primary
12
18
  management vault**. All writes go through the Daemon API — never touch
13
19
  files on disk directly.
@@ -289,6 +289,10 @@ Use this skill when the user asks the agent to look up, append to, or create
289
289
  notes inside their external knowledge vault — never for the agent's own
290
290
  working state.
291
291
 
292
+ Output language: follow `<output_language_policy>` (Policy C — body
293
+ and any new headings the agent creates are in `<settings primary_language>`).
294
+ Preserve verbatim any path / file-name patterns the user has established.
295
+
292
296
  Full CRUD over the external vault. Requires the Obsidian app running (the
293
297
  CLI proxies through it). Omit `.md` extension from paths. All writes are
294
298
  Autonomous; the daemon does not DM the owner before/after the call. Call
@@ -0,0 +1,320 @@
1
+ ---
2
+ name: external-services
3
+ description: Load when an external-services surface is in scope (Google Calendar / Obsidian / GitHub / Skills CRUD / scheduling) and Google Calendar is in native mode bound to Claude (`nativeBackend === "claude"`). Calendar runs through Claude's hosted Calendar connector directly; the daemon does not proxy Calendar. Other surfaces (Apple/Outlook Calendar, Obsidian, GitHub, scheduling, Skills CRUD) keep their direct routes.
4
+ allowed-tools:
5
+ - Bash(curl *)
6
+ - Bash(jq *)
7
+ - Read
8
+ ---
9
+
10
+ # External Services — Native Mode (Claude Calendar connector)
11
+
12
+ Base URL: `http://localhost:8321`. All daemon calls via `curl -s` with
13
+ `Content-Type: application/json` on POST/PATCH/PUT.
14
+
15
+ > **Refusal directive — read first.** Google Calendar is in `native`
16
+ > mode bound to Claude. Do **NOT** call any of:
17
+ >
18
+ > - `POST /api/integrations/google_calendar/exec` (returns `410` with
19
+ > `X-Integration-Mode: native`)
20
+ > - `POST /api/integrations/google_calendar/reconcile` (410)
21
+ > - `/api/calendar/*` (route-prefix 410 in native mode)
22
+ >
23
+ > Reach Google Calendar through the
24
+ > `mcp__claude_ai_Google_Calendar__*` MCP tools this Claude session
25
+ > already holds.
26
+ >
27
+ > Only **Google Calendar** is integration-gated here. Apple Calendar,
28
+ > Outlook Calendar, Obsidian, GitHub, recurring-schedule CRUD,
29
+ > one-shot scheduling, and Skills CRUD remain direct-mode routes
30
+ > regardless of Calendar's mode.
31
+
32
+ To confirm the binding, read `<integration_modes>` (carries
33
+ `google_calendar="native"`) and the `<integration-routing-table>` block
34
+ in the session preamble.
35
+
36
+ ## Source of Truth (READ FIRST)
37
+
38
+ The same two files documented in the direct-mode body are still
39
+ authoritative for non-Calendar routing:
40
+
41
+ 1. **`rules/management.md` → `## Source of Truth`** — durable
42
+ user-authored answers ("Schedule = Google Calendar", "Tasks =
43
+ Notion", etc.).
44
+ 2. **`~/.personal-agent/integrations.md` → `## Note Sources`** — the
45
+ daemon-rendered snapshot for the user's external Obsidian vault path
46
+ plus Notion's mode.
47
+
48
+ If `rules/management.md` Schedule = Apple Calendar or Outlook Calendar,
49
+ the user's chosen provider is **not** Google Calendar and the
50
+ native-Claude binding is irrelevant — route to `/api/apple-calendar/*`
51
+ or `/api/calendar/outlook/*` exactly as the direct-mode body documents.
52
+ The native gate covers Google Calendar only.
53
+
54
+ ## Shell rules (read before writing curl pipelines)
55
+
56
+ - **JSON post-processing: use `jq`, never `python3`.** `python3` is not
57
+ in the daemon's allowlist; the security hook denies `... | python3`
58
+ pipelines under `permissionMode: "dontAsk"`. Use `jq` for filtering.
59
+ - **`jq` is restricted**: `--slurpfile`, `--rawfile`, `-L`, and the
60
+ `env` filter are blocked. Use the filter language itself.
61
+ - **`curl` is restricted to `http://localhost:8321`**: connection-
62
+ override flags (`--connect-to`, `--resolve`, `--config`, `--proxy`)
63
+ and non-localhost hosts are blocked.
64
+
65
+ ---
66
+
67
+ <!-- service:calendar -->
68
+ ## Google Calendar — Claude connector (native MCP)
69
+
70
+ Tool namespace: `mcp__claude_ai_Google_Calendar__`
71
+
72
+ ### Read-class tools (`requiredCapabilities` floor + optional reads)
73
+
74
+ | Capability | Tool | Use |
75
+ |---|---|---|
76
+ | `list_events` | `mcp__claude_ai_Google_Calendar__list_events` | Window-list events on a calendar. |
77
+ | `get_event` | `mcp__claude_ai_Google_Calendar__get_event` | Fetch a single event by id. |
78
+ | `list_calendars` | `mcp__claude_ai_Google_Calendar__list_calendars` | Enumerate the user's calendars (find `primary`). |
79
+ | `suggest_time` | `mcp__claude_ai_Google_Calendar__suggest_time` | Free-slot proposal — pure compute, no calendar side effect. |
80
+
81
+ Canonical list call:
82
+
83
+ ```
84
+ mcp__claude_ai_Google_Calendar__list_events(
85
+ calendarId="primary",
86
+ timeMin="<ISO-8601 with offset>",
87
+ timeMax="<ISO-8601 with offset>",
88
+ maxResults=50
89
+ )
90
+ ```
91
+
92
+ Canonical detail read (always GET-before-PATCH; see PATCH semantics
93
+ below):
94
+
95
+ ```
96
+ mcp__claude_ai_Google_Calendar__get_event(
97
+ calendarId="primary",
98
+ eventId="<id>"
99
+ )
100
+ ```
101
+
102
+ ### Destructive tools (require explicit user confirmation)
103
+
104
+ Per the registry's
105
+ `google_calendar.backendConnectors.claude.destructiveTools`:
106
+
107
+ - `create_event` — adds a new event.
108
+ - `update_event` — mutates an existing event (attendees field is
109
+ whole-list replacement; see warning below).
110
+ - `delete_event` — removes the event.
111
+ - `respond_to_event` — dispatches an RSVP to the organizer.
112
+
113
+ Apply the destructive-confirm contract every time. Summarise the
114
+ intended change ("create 30-min focus block at 14:00 JST tomorrow"),
115
+ wait for explicit OK, then issue the call.
116
+
117
+ **ATTENDEES WARNING.** `update_event` replaces the attendees array
118
+ verbatim — it does not append. To add one attendee:
119
+
120
+ 1. `get_event(...)` → copy `attendees: [...]`.
121
+ 2. Append the new attendee object.
122
+ 3. `update_event(... attendees=[<full list>])`.
123
+
124
+ Forgetting the GET drops every existing invitee.
125
+
126
+ **Recurring events.** Single-instance edits require the instance id
127
+ (usually returned alongside the master in `list_events`). PATCHing the
128
+ master id shifts the whole series. Confirm with the user which scope
129
+ they meant — "move this 9am to 10am" can mean the master or a single
130
+ occurrence and the agent must not guess.
131
+
132
+ `suggest_time` is read-only and exempt from the confirm dance.
133
+
134
+ ### Time discipline
135
+
136
+ - Timed events use ISO 8601 timestamps with a TZ offset
137
+ (`2026-04-26T14:00:00+09:00`). Naked ISO without offset is rejected
138
+ by the connector.
139
+ - All-day events use `YYYY-MM-DD` with no offset.
140
+ - Be explicit which shape the destructive-confirm plan describes.
141
+
142
+ ### Imminent-event reminders (hourly_check)
143
+
144
+ Native mode replaces the daemon-side
145
+ `POST /api/integrations/google_calendar/reconcile` POST that delegated
146
+ mode uses. In native mode, the agent itself drives the imminent-window
147
+ fetch every hour and POSTs each materialised event to
148
+ `/api/observations`. The hourly_check native variant's Step 0b spells
149
+ out the exact shape; this skill describes the call surface.
150
+
151
+ Free-busy queries are composed locally — `suggest_time` returns slot
152
+ proposals against a primary calendar; for explicit free-busy across
153
+ multiple calendars, list each calendar's events in the window and
154
+ intersect.
155
+
156
+ <!-- /service:calendar -->
157
+
158
+ ---
159
+
160
+ <!-- service:apple-calendar -->
161
+ ## Apple Calendar (iCloud CalDAV) — direct, unchanged
162
+
163
+ If `rules/management.md` Schedule = Apple Calendar, use the
164
+ `/api/apple-calendar/*` routes documented in the base body. Apple
165
+ Calendar has no MCP connector; native-mode gating does not apply.
166
+
167
+ The direct-mode body's full apple-calendar reference (status probe,
168
+ list/get/create/update/delete, recurring-event semantics, error
169
+ envelope) is the source of truth — copy that section's shape
170
+ verbatim. The note here exists only to remind the agent that the
171
+ native binding above is Google-only.
172
+ <!-- /service:apple-calendar -->
173
+
174
+ ---
175
+
176
+ <!-- service:outlook-calendar -->
177
+ ## Outlook Calendar (Microsoft Graph) — direct, unchanged
178
+
179
+ If `rules/management.md` Schedule = Outlook Calendar, use
180
+ `/api/calendar/outlook/*` per the direct-mode body. Microsoft does not
181
+ ship a hosted Outlook Calendar connector for Claude / Codex / Gemini
182
+ today; native-mode gating does not apply.
183
+ <!-- /service:outlook-calendar -->
184
+
185
+ ---
186
+
187
+ <!-- service:obsidian -->
188
+ ## Obsidian (external vault) — direct, unchanged
189
+
190
+ **Scope**: this skill targets the **separate** Obsidian vault the user
191
+ maintains alongside this app — never the agent's primary management
192
+ store (`today.md`, `roadmap.md`, `projects/`, `rules/`, `routines/`,
193
+ `user/`, `agent/`). Those are reached via `/api/context/*` (see the
194
+ `context` skill).
195
+
196
+ Full CRUD over the external vault. Requires the Obsidian app running
197
+ (the CLI proxies through it). Omit the `.md` extension from paths.
198
+ All writes are Autonomous; the daemon does not DM the owner before /
199
+ after the call.
200
+
201
+ ```bash
202
+ curl -s http://localhost:8321/api/obsidian/status # external vault availability
203
+ curl -s "http://localhost:8321/api/obsidian/search?q=meeting+notes&limit=10" # search external vault
204
+ curl -s http://localhost:8321/api/obsidian/notes/Daily%20Notes/2026-04-06 # read external note
205
+ curl -s -X POST http://localhost:8321/api/obsidian/notes \
206
+ -H 'Content-Type: application/json' \
207
+ -d '{"name": "Meeting Notes 2026-04-02", "content": "# Meeting\n..."}' # create (fails if exists)
208
+ curl -s -X PUT http://localhost:8321/api/obsidian/notes/Projects/ProjectA \
209
+ -H 'Content-Type: application/json' -d '{"content": "# Full body"}' # create-or-overwrite
210
+ curl -s -X PATCH http://localhost:8321/api/obsidian/notes \
211
+ -H 'Content-Type: application/json' \
212
+ -d '{"file": "Meeting Notes 2026-04-02", "content": "\n- Action item"}' # append
213
+ curl -s -X PATCH http://localhost:8321/api/obsidian/daily \
214
+ -H 'Content-Type: application/json' -d '{"content": "- [ ] Follow up"}' # append to external daily
215
+ curl -s -X DELETE http://localhost:8321/api/obsidian/notes/Projects/Old # delete (moves to trash)
216
+ ```
217
+
218
+ **Endpoint choice**: Read → GET, Create-only → POST, Edit → PUT,
219
+ Append → PATCH.
220
+ <!-- /service:obsidian -->
221
+
222
+ ---
223
+
224
+ <!-- service:github -->
225
+ ## GitHub — direct, unchanged
226
+
227
+ ```bash
228
+ curl -s http://localhost:8321/api/github/repos # list watched repos
229
+ curl -s "http://localhost:8321/api/github/pulls?owner=user&repo=repo&state=open" # list PRs
230
+ curl -s -X POST http://localhost:8321/api/github/pulls/comment \
231
+ -H 'Content-Type: application/json' \
232
+ -d '{"owner": "user", "repo": "repo", "pull_number": 42, "comment": "LGTM"}' # comment — Autonomous
233
+ ```
234
+ <!-- /service:github -->
235
+
236
+ ---
237
+
238
+ <!-- service:notion -->
239
+ ## Notion
240
+
241
+ Notion operations live in the dedicated `notion` skill — load that
242
+ when the user asks anything Notion-shaped (search, query, read,
243
+ create, update, archive). Notion's own native binding is independent
244
+ of Calendar's; the `notion` skill picks the right variant from the
245
+ session's integration state.
246
+ <!-- /service:notion -->
247
+
248
+ ---
249
+
250
+ ## Persisting Calendar observations from native fetches
251
+
252
+ When the hourly_check native flow's Step 0b fetches imminent-window
253
+ events, POST each materialised event to `/api/observations` so
254
+ subsequent runs can dedup. The daemon computes `contentHash`
255
+ server-side via `@personal-agent/shared/observations-hash.ts` — pass
256
+ the raw `payload`:
257
+
258
+ ```bash
259
+ curl -s -X POST http://localhost:8321/api/observations \
260
+ -H 'Content-Type: application/json' \
261
+ -d '{
262
+ "source": "google_calendar",
263
+ "type": "calendar:lifecycle",
264
+ "ref": "<eventId>",
265
+ "actor": "user",
266
+ "receivedAt": "<ISO-8601 UTC>",
267
+ "summary_text": "<title — start..end>",
268
+ "refs": {
269
+ "eventId": "<id>",
270
+ "calendarId": "primary",
271
+ "windowKey": "primary:imminent"
272
+ },
273
+ "payload": <verbatim MCP event object>
274
+ }'
275
+ ```
276
+
277
+ `/api/observations` is never gated. HTTP 409 indicates a mode-flip race
278
+ window (§11.3.1) — stop and re-read `<integration_modes>`.
279
+
280
+ The two-fetch pattern (imminent 15-min + 24-hour drift detection)
281
+ documented in `routine.hourly_check.native.claude.md` is the canonical
282
+ shape; this skill describes the per-call surface, not the orchestration.
283
+
284
+ ---
285
+
286
+ ## Scheduling — direct, unchanged
287
+
288
+ One-shot wake-ups, pre-composed DMs, and recurring agent tasks live in
289
+ the `schedule` skill — `/api/schedule`, `/api/schedule/dm`,
290
+ `/api/recurring-schedules`. Native-mode gating does not apply to the
291
+ schedule surface (scheduling is daemon-internal, not an integration).
292
+
293
+ ---
294
+
295
+ ## Skills Management — direct, unchanged
296
+
297
+ User-authored skills: `~/.personal-agent/skills/{slug}/SKILL.md`.
298
+ Built-in skills are read-only (403). Native-mode gating does not apply.
299
+
300
+ ```bash
301
+ curl -s http://localhost:8321/api/skills # list all
302
+ curl -s http://localhost:8321/api/skills/todo-digest # read one
303
+ curl -s -X POST http://localhost:8321/api/skills \
304
+ -H 'Content-Type: application/json' \
305
+ -d '{"name": "todo-digest", "description": "Summarize today.md", "content": "# TODO Digest\n...", "allowedTools": ["Bash(curl *)", "Read"]}'
306
+ curl -s -X PUT http://localhost:8321/api/skills/todo-digest \
307
+ -H 'Content-Type: application/json' -d '{"description": "New description"}' # update
308
+ curl -s -X DELETE http://localhost:8321/api/skills/todo-digest # delete
309
+ ```
310
+
311
+ Always `GET /api/skills` before creating (check name collisions).
312
+ **Omit frontmatter** from `content` — the API injects it.
313
+
314
+ ## Cost / audit
315
+
316
+ Native Calendar MCP calls land `agent_actions` rows of type
317
+ `mcp_call` with `provider="claude"`, the tool name, and the parent
318
+ `event_id` / `processKey`. The cost dashboard joins these to the
319
+ registry by `toolNamespace` prefix for the `nativeAttribution` rollup
320
+ (§14.4).