@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
@@ -41,41 +41,44 @@ Global rules (apply at every step):
41
41
  > routine prepares the agent-day in progress — never tomorrow.
42
42
 
43
43
  ### Step 2 — Sync external sources (apply the day-type filter at read time)
44
- 3. Mail: for each active account in the `mail` skill's `accounts.md`, fetch
45
- the 10 most recent messages (the wire surface depends on Gmail's mode in
46
- `<integration_modes>` see the four-branch block below). Then classify
47
- each actionable email into a category tag and drop any whose focus is
48
- off. Skip the step entirely when no accounts are active.
49
-
50
- <!-- mode:direct:gmail -->
51
- Use the `mail` skill — `GET /api/mail/:accountId/messages?limit=10` for
52
- every account (Gmail, Outlook, iCloud, Yahoo, IMAP same wire surface).
53
- <!-- /mode:direct:gmail -->
54
- <!-- mode:delegated-same:gmail -->
55
- Non-Gmail accounts (iCloud / Outlook / Yahoo / IMAP): use the `mail`
56
- skill as in direct mode. Gmail accounts: the `/api/mail/*` per-account
57
- gate returns 410 use your session backend's native Gmail MCP tool
58
- with a "10 most recent inbox" query (`q=in:inbox`, limit/maxResults
59
- `10`). The `mail` skill body lists the per-backend tool names; this
60
- session is same-backend so no daemon proxy is involved.
61
- <!-- /mode:delegated-same:gmail -->
62
- <!-- mode:delegated-cross:gmail -->
63
- Non-Gmail accounts: use the `mail` skill as in direct mode. Gmail
64
- accounts: call `POST http://localhost:8321/api/integrations/gmail/exec`
65
- with a natural-language `task` (e.g. "Search Gmail for the 10 most
66
- recent inbox messages, return from / subject / snippet / ts") and a
67
- small `outputSchema`. The cross-backend `mail` skill variant
68
- (`SKILL.delegated.<session-backend>.md`, materialized for this
69
- session) carries the worked schema templates. Do NOT call
70
- `/api/mail/:gmail-account/*` (returns 410), and do NOT fall back to
71
- your own backend's native Gmail MCP tools — that connector reads a
72
- different account than the user's delegated one.
73
- <!-- /mode:delegated-cross:gmail -->
74
- <!-- mode:disabled:gmail -->
75
- Gmail is disabled — skip Gmail accounts entirely. Continue with the
76
- remaining accounts (iCloud / Outlook / Yahoo / IMAP) via the `mail`
77
- skill so non-Gmail actionables still flow into today's draft.
78
- <!-- /mode:disabled:gmail -->
44
+ 3. Mail and Notion acquisition. The pre-pass fetcher session
45
+ (`routine.fetch_window`) ran ahead of you and posted a `<fetch>` row's
46
+ worth of observations for every active mail / notion integration. The
47
+ `<fetch_report>` block injected ahead of this body tells you the
48
+ pre-pass status:
49
+
50
+ - `status="success"` or `"partial"` → freshly-fetched rows are
51
+ visible in `/api/observations?pending=true`. Trust the table.
52
+ - `status="failed"` the pre-pass either crashed or its output was
53
+ unparseable. Pending observations from prior ticks may still be
54
+ present; treat the table as best-effort and skip integration
55
+ sections whose source_prefix returns nothing.
56
+ - `status="skipped"` no integration was active for this routine
57
+ this tick; mail / notion sections are no-ops for this run.
58
+
59
+ Then drain pending observations and apply category / focus filtering:
60
+
61
+ a. **Mail observations**:
62
+ `GET /api/observations?pending=true&source_prefix=gmail:,outlook_mail:&limit=30`.
63
+ Classify each per the `mail` skill's category taxonomy. Drop any
64
+ whose day-type focus is `off`. When `summary_text` is NULL (the
65
+ async summarizer has not drained yet) fall back to a one-line
66
+ snippet from `payload.raw` (subject + from). Mail data arrives
67
+ here regardless of integration mode the pre-pass partial
68
+ handled the direct / delegated-same / delegated-cross / native
69
+ wire surface for you.
70
+
71
+ b. **Notion observations**:
72
+ `GET /api/observations?pending=true&source_prefix=notion:&limit=20`.
73
+ Use for project / decision context only. Do NOT graduate Notion
74
+ edits into User Tasks unless the user explicitly tagged the entry.
75
+
76
+ c. **Calendar context** is already injected as `<calendar_events_7d>`
77
+ (multi-provider) ahead of this prompt reference the block
78
+ directly in Step 6 (today.md generation).
79
+
80
+ Skip the entire step when no integrations are active and no mail /
81
+ notion observations are pending.
79
82
  4. Source-of-Truth tasks: read `<management_rules>` ## Source of Truth →
80
83
  Tasks, call the matching endpoint, drop filtered-off items before merge.
81
84
  Skip if no external source is configured.
@@ -99,10 +102,15 @@ Global rules (apply at every step):
99
102
  flavor 1: Look-ahead checklist" format (`- [ ] (HIGH/MID/LOW) ...`).
100
103
  Skip this step entirely if no today-items and no look-ahead items exist.
101
104
 
102
- ### Step 3 — Review overnight observations
105
+ ### Step 3 — Review overnight user-originated observations
103
106
  6. Call `GET /api/observations?pending=true&actor=user` (observations
104
- skill). Fold only meaningful user-originated changes into the `today.md`
105
- draft you're building, respecting the day-type filter.
107
+ skill). This is the **user-actor** complement to Step 2 — mail / notion
108
+ rows posted by the pre-pass / partials carry `actor=agent` and have
109
+ already been folded in. Step 3 picks up anything the user themselves
110
+ changed overnight (Obsidian edits, manual file drops, git commits)
111
+ that the daemon recorded under `actor=user`. Fold only meaningful
112
+ changes into the `today.md` draft you're building, respecting the
113
+ day-type filter.
106
114
 
107
115
  ### Step 4 — Inbox triage (B-007 §5.9 Q5 case A)
108
116
  7. `GET /api/context/list/inbox` to enumerate pasted memos. For each file:
@@ -153,8 +161,10 @@ Global rules (apply at every step):
153
161
  `yesterday.md` for curated phrasing already shown to the user.
154
162
  Compose `daily/YYYY-MM-DD.md` (YYYY-MM-DD = yesterday's agent-day
155
163
  date) following the **`Daily journal format spec`** policy block above.
156
- - Write in `<settings primary_language>` (fall back to English on
157
- unknown values). Keep technical terms in their original form.
164
+ - Output language: follow `<output_language_policy>` (Policy B
165
+ skeleton H2 headers stay English; body prose in
166
+ `<settings primary_language>`). Keep technical terms in their
167
+ original form.
158
168
  - When `<settings vault_mode>` is `obsidian`, render project / people
159
169
  references as `[[wikilink]]`s resolving to `projects/<slug>.md` or
160
170
  `user/people.md#...`. When `plain`, write plain text only.
@@ -187,7 +197,10 @@ Global rules (apply at every step):
187
197
  on Sonnet.
188
198
  Source → section mapping:
189
199
  - ## User Schedule ← `<calendar_events_7d>` (filtered). Write
190
- `- (calendar unavailable)` if `<calendar_status>` reports failure.
200
+ `- (calendar unavailable)` when the block has been replaced by
201
+ `<calendar_status>Calendar service not available...</calendar_status>`
202
+ (no active provider) or when every `<provider>` sub-block's
203
+ directive fetch failed for this run.
191
204
  - ## User Tasks ← Step 1 handoff Tomorrow + Step 2 email actionables
192
205
  + SoT tasks + roadmap `[today]`. Use `<active_projects>` for context.
193
206
  - ## Agent Plan ← Step 2 `[notify]`/`[check]` rows plus any
@@ -297,4 +310,4 @@ the evening sweep (Operation 5B), not the morning routine.
297
310
  - Checks from routines/morning.md: <list any user-added ones executed>
298
311
  - Anomalies / skipped steps: <short notes or "none">
299
312
  ```
300
- Always English (B-007 §3 P6) regardless of `<settings primary_language>`.
313
+ <output_language>english_only Policy A surface (agent journal, parsed log); `<output_language_policy>` carves this out explicitly.</output_language>
@@ -36,41 +36,33 @@ Global rules:
36
36
  > routine prepares the agent-day in progress — never tomorrow.
37
37
 
38
38
  ### Step 2 — Sync external sources
39
- 2. Mail: for each active account in the `mail` skill's `accounts.md`, fetch
40
- the 10 most recent messages (the wire surface depends on Gmail's mode in
41
- `<integration_modes>` see the four-branch block below). Then classify
42
- each actionable email into a category tag and drop filtered-off items.
43
- Skip the step entirely when no accounts are active.
44
-
45
- <!-- mode:direct:gmail -->
46
- Use the `mail` skill `GET /api/mail/:accountId/messages?limit=10` for
47
- every account (Gmail, Outlook, iCloud, Yahoo, IMAP — same wire surface).
48
- <!-- /mode:direct:gmail -->
49
- <!-- mode:delegated-same:gmail -->
50
- Non-Gmail accounts (iCloud / Outlook / Yahoo / IMAP): use the `mail`
51
- skill as in direct mode. Gmail accounts: the `/api/mail/*` per-account
52
- gate returns 410 use your session backend's native Gmail MCP tool
53
- with a "10 most recent inbox" query (`q=in:inbox`, limit/maxResults
54
- `10`). The `mail` skill body lists the per-backend tool names; this
55
- session is same-backend so no daemon proxy is involved.
56
- <!-- /mode:delegated-same:gmail -->
57
- <!-- mode:delegated-cross:gmail -->
58
- Non-Gmail accounts: use the `mail` skill as in direct mode. Gmail
59
- accounts: call `POST http://localhost:8321/api/integrations/gmail/exec`
60
- with a natural-language `task` (e.g. "Search Gmail for the 10 most
61
- recent inbox messages, return from / subject / snippet / ts") and a
62
- small `outputSchema`. The cross-backend `mail` skill variant
63
- (`SKILL.delegated.<session-backend>.md`, materialized for this
64
- session) carries the worked schema templates. Do NOT call
65
- `/api/mail/:gmail-account/*` (returns 410), and do NOT fall back to
66
- your own backend's native Gmail MCP tools — that connector reads a
67
- different account than the user's delegated one.
68
- <!-- /mode:delegated-cross:gmail -->
69
- <!-- mode:disabled:gmail -->
70
- Gmail is disabled — skip Gmail accounts entirely. Continue with the
71
- remaining accounts (iCloud / Outlook / Yahoo / IMAP) via the `mail`
72
- skill so non-Gmail actionables still flow into today's draft.
73
- <!-- /mode:disabled:gmail -->
39
+ 2. Mail and Notion acquisition. The pre-pass fetcher session
40
+ (`routine.fetch_window`) ran ahead of you and posted observations
41
+ for every active mail / notion integration. The `<fetch_report>`
42
+ block in your prompt tells you the pre-pass status `success` /
43
+ `partial` means the table is fresh, `failed` / `skipped` means
44
+ trust nothing newer than the prior tick.
45
+
46
+ Drain pending observations and apply category / focus filtering:
47
+
48
+ a. **Mail observations**:
49
+ `GET /api/observations?pending=true&source_prefix=gmail:,outlook_mail:&limit=30`.
50
+ Classify each actionable item into a category tag and drop any
51
+ whose day-type focus is `off`. When `summary_text` is NULL fall
52
+ back to a one-line snippet from `payload.raw`. Mail data arrives
53
+ here regardless of integration mode the pre-pass partial
54
+ handled the wire surface.
55
+
56
+ b. **Notion observations**:
57
+ `GET /api/observations?pending=true&source_prefix=notion:&limit=20`.
58
+ Use for project / decision context only.
59
+
60
+ c. **Calendar context** is already injected as `<calendar_events_7d>`
61
+ (multi-provider) ahead of this prompt reference the block
62
+ directly in Step 6.
63
+
64
+ Skip the entire step when no integrations are active and no mail /
65
+ notion observations are pending.
74
66
  3. Source-of-Truth tasks: read `<management_rules>` ## Source of Truth →
75
67
  Tasks, call the matching endpoint, drop filtered-off items.
76
68
  4. Roadmap ## Agent Action Plan — process items dated today or overdue:
@@ -83,9 +75,13 @@ Global rules:
83
75
  `<calendar_events_7d>`) into ## Agent Notes using the skill's "Agent
84
76
  Notes flavor 1: Look-ahead checklist" format.
85
77
 
86
- ### Step 3 — Review overnight observations
78
+ ### Step 3 — Review overnight user-originated observations
87
79
  5. `GET /api/observations?pending=true&actor=user` (observations skill).
88
- Fold only meaningful user-originated changes into the draft.
80
+ This is the user-actor complement to Step 2 — mail / notion rows
81
+ posted by the partials carry `actor=agent` and have already been
82
+ folded in. Step 3 picks up user-originated changes (manual file drops,
83
+ Obsidian edits, git commits) recorded under `actor=user`. Fold only
84
+ meaningful changes into the draft.
89
85
 
90
86
  ### Step 4 — Inbox triage
91
87
  6. `GET /api/context/list/inbox` to enumerate any pasted memos the user
@@ -106,7 +102,10 @@ Journal synthesis is deferred to the next morning run. The first
106
102
  `- [ ] HH:MM <action> [work|study|personal|home] →<DM|notify|check-in|wake>`.
107
103
  Source → section mapping:
108
104
  - ## User Schedule ← `<calendar_events_7d>` (filtered). Write
109
- `- (calendar unavailable)` if `<calendar_status>` reports failure.
105
+ `- (calendar unavailable)` when the block has been replaced by
106
+ `<calendar_status>Calendar service not available...</calendar_status>`
107
+ (no active provider) or when every `<provider>` sub-block's
108
+ directive fetch failed for this run.
110
109
  - ## User Tasks ← Step 2 email actionables + SoT tasks + roadmap
111
110
  `[today]`. Use `<active_projects>` for context. Drop meta-maintenance.
112
111
  - ## Agent Plan ← Step 2 `[notify]`/`[check]` rows plus any
@@ -24,52 +24,44 @@ consult it for the rules your output must satisfy. This task flow only
24
24
  coordinates the high-level gather → analyze → write loop.
25
25
 
26
26
  ### Phase 1: Gather Data
27
- 1. If `<calendar_status>` indicates the calendar is available, fetch a
28
- 90-day window. Pick the call by current Calendar mode (read
29
- `<integration_modes>` injected above):
30
- <!-- mode:direct:google_calendar -->
31
- Direct mode:
32
- ```
33
- curl -s 'http://localhost:8321/api/calendar/events?date=today&days=90'
34
- ```
35
- <!-- /mode:direct:google_calendar -->
36
- <!-- mode:delegated-same:google_calendar -->
37
- Same-backend delegated the connector is signed in on this session's
38
- backend; use its native list-events tool with `timeMin = today 00:00`
39
- and `timeMax = today + 90d`:
40
- - claude session: `mcp__claude_ai_Google_Calendar__list_events`
41
- - codex session: `mcp__codex_apps__google_calendar._search_events`
42
- - gemini session: `mcp_google-workspace_calendar.listEvents`
43
-
44
- `/api/calendar/events` returns 410 in delegated mode; do not call it.
45
- <!-- /mode:delegated-same:google_calendar -->
46
- <!-- mode:delegated-cross:google_calendar -->
47
- Cross-backend delegated call the daemon's `/exec` task endpoint
48
- with a natural-language intent; the delegate picks the right
49
- connector tool whichever backend currently owns Calendar.
50
- ```
51
- curl -s -X POST http://localhost:8321/api/integrations/google_calendar/exec \
52
- -H 'Content-Type: application/json' \
53
- -d '{
54
- "task": "List every event on my primary calendar between <today 00:00 ISO> and <today+90d ISO>. Return id, title, start, end, attendees.",
55
- "outputSchema": { "type": "object", "required": ["events"], "properties": { "events": { "type": "array", "items": { "type": "object", "required": ["id","title","start","end"] } } } },
56
- "maxToolCalls": 4,
57
- "cacheable": true
58
- }'
59
- ```
60
-
61
- Do NOT call `/api/calendar/events` (410) and do NOT fall back to
62
- your backend's native Calendar MCP tools (different account).
63
- <!-- /mode:delegated-cross:google_calendar -->
64
- <!-- mode:disabled:google_calendar -->
65
- Calendar is disabled — skip the calendar fetch entirely; proceed to
66
- the schedule fetch below and work with existing roadmap content only.
67
- <!-- /mode:disabled:google_calendar -->
68
-
69
- If the response contains "error" or a non-200 status, treat as unavailable.
70
- If the calendar is unavailable (status says so OR the call fails), proceed
71
- to the schedule fetch below and work with existing roadmap content only —
72
- do not retry.
27
+ 1. **Calendar (next 90 days).** The `<calendar_events_90d>` block in your
28
+ prompt is the canonical surface for every active calendar provider
29
+ (`google_calendar`, `outlook_calendar`) across all four integration
30
+ modes. The daemon emits one `<provider key="..." mode="...">` sub-block
31
+ per active provider; consume each per its mode:
32
+
33
+ - **`mode="direct"`** — the sub-block contains the pre-fetched events
34
+ for the next 90 days, already grouped by date. Read inline; no
35
+ additional fetch is needed. (If the sub-block instead carries the
36
+ "direct mode, daemon service not initialized" hint, fall back to
37
+ `GET /api/calendar/events?date=today&days=90` for Google or
38
+ `GET /api/calendar/outlook?date=today&days=90` for Outlook as the
39
+ hint instructs.)
40
+ - **`mode="delegated"`** follow the directive verbatim. It tells you
41
+ whether this is same-backend (use your session's Calendar MCP tool)
42
+ or cross-backend (POST `/api/integrations/<key>/exec`), substituting
43
+ the `timeMin` / `timeMax` carried on the `<calendar_events_90d>`
44
+ wrapper.
45
+ - **`mode="native"`** — follow the directive verbatim. Native bindings
46
+ never go through the daemon; call your session backend's Calendar
47
+ MCP tool directly with the `timeMin` / `timeMax` from the wrapper.
48
+ If `<integration_modes>` shows the provider's `_native_to` is a
49
+ different backend than yours, treat the provider as unavailable for
50
+ this turn (per the directive).
51
+ - **No sub-block for a provider** — that provider is disabled; skip
52
+ it without retry.
53
+
54
+ If `<calendar_events_90d>` is replaced by
55
+ `<calendar_status>Calendar service not available...</calendar_status>`
56
+ (no provider is active in any mode), skip calendar-derived steps in
57
+ Phase 2 (event entries, prep timelines, travel cross-check) and
58
+ proceed with the rest of Phase 1 — the refresh still bumps `Last
59
+ synced` and updates `## Annual Goals` / `## Quarterly Focus`
60
+ placeholders so the file does not drift.
61
+
62
+ If a directive fetch errors out (non-2xx / connector unavailable),
63
+ log one line to `## Agent Log`, drop that provider's events for this
64
+ run, and proceed — do not retry inline.
73
65
 
74
66
  2. Fetch pending and running scheduled tasks:
75
67
  ```
@@ -24,117 +24,74 @@ day rotation and **not** a morning routine.
24
24
  also blocked by the same lock. The next morning/hourly run will
25
25
  reconcile.
26
26
 
27
- ### Step 1 — Fetch today's calendar events
27
+ ### Step 1 — Read today's calendar from observations
28
28
 
29
- The fetch path depends on the current Google Calendar mode (read
30
- `<integration_modes>` injected above).
29
+ The pre-pass fetcher session (`routine.fetch_window`) ran ahead of you
30
+ and posted a full next-24h calendar slice for every active calendar
31
+ provider (`google_calendar`, `outlook_calendar`). The `<fetch_report>`
32
+ block in your prompt tells you the pre-pass status. The `<calendar_status>`
33
+ block restates the contract for the routine's prose.
31
34
 
32
- <!-- mode:direct:google_calendar -->
33
- **Direct mode** — daemon polls Google Calendar; call its proxy:
35
+ **If `<fetch_report status="skipped">`** — every calendar integration
36
+ is disabled. Append
37
+ `- HH:MM Manual refresh: calendar disabled, schedule unchanged`
38
+ to `## Agent Log` and **skip Steps 2 and 3**.
34
39
 
35
- ```
36
- curl -s 'http://localhost:8321/api/calendar/events?date=today&days=1'
37
- ```
40
+ **If `<fetch_report status="failed">`** — the pre-pass crashed or the
41
+ output was unparseable; trust no row newer than the prior tick. Append
42
+ `- HH:MM Manual refresh: pre-pass failed, schedule unchanged`
43
+ to `## Agent Log` and **skip Steps 2 and 3**.
38
44
 
39
- - On `200`: continue to processing rules below.
40
- - On `410`: the integration flipped to delegated between selection and
41
- call (mode drift). Append
42
- `- HH:MM Manual refresh: calendar route 410 (delegation drift), schedule unchanged`
43
- to `## Agent Log` and return without touching `## User Schedule`.
44
- - On `503` or `502`: calendar service not configured or upstream error.
45
- Append
46
- `- HH:MM Manual refresh: calendar unavailable, schedule unchanged`
47
- to `## Agent Log` and return without touching `## User Schedule`.
48
- <!-- /mode:direct:google_calendar -->
49
-
50
- <!-- mode:delegated-same:google_calendar -->
51
- **Same-backend delegated** — your session has native MCP access to the
52
- Google Calendar connector signed in on this backend. No daemon proxy
53
- is needed. Call the backend-specific list-events tool with
54
- `timeMin = today 00:00 (local TZ)` and `timeMax = tomorrow 00:00`:
55
-
56
- | Session backend | Tool |
57
- |-----------------|-----------------------------------------------------------|
58
- | claude | `mcp__claude_ai_Google_Calendar__list_events` |
59
- | codex | `mcp__codex_apps__google_calendar._search_events` |
60
- | gemini | `mcp_google-workspace_calendar.listEvents` |
61
-
62
- The result is the connector's native shape; treat each entry as one
63
- event with `summary`, `start`, `end`, `location` and continue with the
64
- processing rules below.
65
-
66
- `/api/calendar/events` returns 410 in delegated mode; do not call it.
67
- On a connector error (auth lapsed, network failure), append
68
- `- HH:MM Manual refresh: calendar connector error, schedule unchanged`
69
- to `## Agent Log` and return without touching `## User Schedule`.
70
- <!-- /mode:delegated-same:google_calendar -->
71
-
72
- <!-- mode:delegated-cross:google_calendar -->
73
- **Cross-backend delegated** — the Calendar connector lives on a
74
- different backend than this session. Call the daemon's `/exec` task
75
- endpoint with a natural-language intent; the daemon spawns the
76
- delegated backend and lets it pick the right tool whichever connector
77
- currently owns Calendar.
45
+ **If `<fetch_report>` carries `errors:[{"type":"no-surface", ...}]` for
46
+ every active calendar provider** (e.g. user picked native for Outlook
47
+ without binding a surface), append
48
+ `- HH:MM Manual refresh: calendar connector unavailable, schedule unchanged`
49
+ to `## Agent Log` and **skip Steps 2 and 3**.
50
+
51
+ Otherwise (success / partial), read the merged set of pending calendar
52
+ observations:
78
53
 
79
54
  ```
80
- curl -s -X POST http://localhost:8321/api/integrations/google_calendar/exec \
81
- -H 'Content-Type: application/json' \
82
- -d '{
83
- "task": "List every event on my primary calendar between <today 00:00 ISO> and <tomorrow 00:00 ISO>. Return up to 250 with id, title, start, end, attendees.",
84
- "outputSchema": { "type": "object", "required": ["events"], "properties": { "events": { "type": "array", "items": { "type": "object", "required": ["id","title","start","end"] } } } },
85
- "cacheable": true
86
- }'
55
+ GET /api/observations?pending=true&source_prefix=google_calendar:,outlook_calendar:&limit=200
87
56
  ```
88
57
 
89
- - On `200`: the response payload exposes the schema-validated event
90
- list under `.result.events` continue with the processing rules
91
- below.
92
- - On `410` from `/api/calendar/events` (do NOT call it): would mean a
93
- hallucinated direct call; never reach this branch.
94
- - On `409 mode_mismatch` / `precondition`: state drifted during the
95
- call. Append
96
- `- HH:MM Manual refresh: calendar mode flipped mid-call, schedule unchanged`
97
- and stop.
98
- - On `503 delegated_proxy_busy`: queue full. Append
99
- `- HH:MM Manual refresh: calendar proxy busy, schedule unchanged`
100
- and stop (no retry — the dashboard user can re-click Regenerate).
101
- - On `502 auth_error`: the delegated backend's connector is signed
102
- out. Append
103
- `- HH:MM Manual refresh: <backend> calendar connector signed out, schedule unchanged`
104
- and stop.
105
-
106
- Do NOT fall back to your own backend's native Calendar MCP tools —
107
- they read a different Google account than the user's delegated one.
108
- <!-- /mode:delegated-cross:google_calendar -->
109
-
110
- <!-- mode:disabled:google_calendar -->
111
- **Calendar disabled** — there is no live source to refresh from. Append
112
- `- HH:MM Manual refresh: calendar disabled, schedule unchanged`
113
- to `## Agent Log` and return without touching `## User Schedule`.
114
- **Skip Steps 2 and 3.**
115
- <!-- /mode:disabled:google_calendar -->
58
+ Because every mode fetches the full 24h window (unchanged events return
59
+ 409 server-side, changed ones write a fresh row), the pending set
60
+ carries the complete day picture for both providers — no need for a
61
+ "drift" carve-out in this routine's prose. When `summary_text` is NULL
62
+ (the summarizer has not drained yet), fall back to a one-line snippet
63
+ from `payload.raw` (`title` + `start`). The unified observations table
64
+ covers both Google and Outlook providers, so no provider-specific
65
+ branch is needed below.
116
66
 
117
- ### Processing rules (apply after a successful fetch above)
67
+ ### Processing rules (apply after Step 1 above produced observations)
118
68
 
119
69
  - Today's local date comes from `<current_time>` (`local` attribute,
120
70
  YYYY-MM-DD prefix). The configured timezone is `<current_time>`'s
121
71
  `timezone` attribute — use it for every `HH:MM` you emit.
122
- - Parse the event list, then:
72
+ - Walk each observation row from Step 1's GET. The provider-side fields
73
+ live under `payload.raw` (`title` / `start` / `end` /
74
+ `attendees` / `status`); `start` and `end` are ISO 8601 strings. Then:
123
75
  1. **Filter to events that START today-local.** For timed events,
124
- convert `start.dateTime` to the configured timezone and keep
125
- only rows whose local date matches today. For all-day events,
126
- keep only rows whose `start.date` equals today's YYYY-MM-DD.
127
- (The query spans `[today 00:00, tomorrow 00:00)` in UTC, so
128
- multi-day events that started earlier will appear — drop those.)
129
- 2. **Sort ascending by start time** (all-day events first, then
76
+ convert `start` to the configured timezone and keep only rows
77
+ whose local date matches today. For all-day events (where `start`
78
+ is a date-only `YYYY-MM-DD` with no time component), keep only
79
+ rows whose `start` equals today's YYYY-MM-DD. (The drift window
80
+ spans `[now, now+24h)`, so events that started earlier in the
81
+ same day will appear keep those whose local date matches today,
82
+ drop multi-day events that started yesterday.)
83
+ 2. **Drop `changeType: "deleted"` rows.** Cancelled events should not
84
+ appear in the new schedule. The cancellation is reflected by
85
+ omission.
86
+ 3. **Sort ascending by start time** (all-day events first, then
130
87
  timed events in chronological order).
131
- 3. Render each row using these forms:
132
- - Timed event: `- HH:MM–HH:MM <summary>` (append
133
- ` @ <location>` only when `location` is non-empty).
134
- - All-day event: `- All day <summary>` (append ` @ <location>`
135
- only when present). An event is all-day when `start.date` is
136
- set and `start.dateTime` is absent.
137
- 4. If after filtering the list is empty, the body is the single line
88
+ 4. Render each row using these forms:
89
+ - Timed event: `- HH:MM–HH:MM <title>` (append
90
+ ` @ <location>` only when `payload.raw.location` is non-empty).
91
+ - All-day event: `- All day <title>` (append ` @ <location>`
92
+ only when present). An event is all-day when `start` is a
93
+ date-only string.
94
+ 5. If after filtering the list is empty, the body is the single line
138
95
  `- No scheduled events today`.
139
96
 
140
97
  ### Step 2 — Replace the User Schedule section