@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
@@ -44,6 +44,15 @@ events** when they detect changes. They write observation rows to
44
44
  SQLite. A single `routine.hourly_check` consumes the queue and decides
45
45
  what is worth surfacing.
46
46
 
47
+ Since 2026-05, observations have a **second writer**: every main
48
+ routine (morning, today_refresh, hourly_check, evening, weekly) is
49
+ preceded by a lite-tier `routine.fetch_window` pre-pass that fetches
50
+ mail / calendar / Notion windows and POSTs them to
51
+ `/api/observations`. The main routine then reads them via the same
52
+ `pending=true` queue that the polling path feeds. Observation rows
53
+ look identical regardless of which writer produced them — the
54
+ distinction is invisible to downstream consumers.
55
+
47
56
  ## Why This Concept Exists
48
57
 
49
58
  Per-change notifications turned every routine commit, every saved
@@ -57,10 +66,19 @@ up to something the operator should hear about.
57
66
  - **Observation**: one row in the `observations` table.
58
67
  - **Actor**: who caused the change. `actor='agent'` rows are filtered
59
68
  out by the consumer (anti-loop).
60
- - **Hourly check**: the consumer routine. Light tier by default.
69
+ - **Hourly check**: the consumer routine. Medium tier by default
70
+ (Sonnet); fed by both the background polling path and the pre-pass
71
+ fetcher.
61
72
  - **`AgentWriteTracker`**: the daemon component that tags
62
73
  agent-originated writes so observers don't observe the agent's own
63
74
  output.
75
+ - **Pre-pass writer (2026-05+)**: the lite-tier `routine.fetch_window`
76
+ session spawned by each main routine's dispatcher. Fetches a
77
+ per-routine window (`ROUTINE_WINDOWS` in
78
+ `packages/daemon/src/core/routine-windows.ts`) for each enabled
79
+ mail / calendar / Notion integration and POSTs observations. The
80
+ server computes `contentHash` from `(source, payload)`, so an
81
+ unchanged item written twice in the same cadence dedupes to a 409.
64
82
 
65
83
  ## Concrete Examples
66
84
 
@@ -68,6 +68,11 @@ those subsystems.
68
68
  `routine.monthly_review`, `routine.hourly_check`,
69
69
  `routine.roadmap_refresh`, `routine.today_refresh`,
70
70
  `routine.user_profile_sweep`
71
+ - Routine sub-jobs (lite tier, dispatcher-spawned, not user-facing):
72
+ `routine.fetch_window` (pre-pass mail/calendar/Notion fetcher that
73
+ runs before each main routine and POSTs observations) and
74
+ `routine.hourly_check.triage` (Stage 2 escalate-vs-log-only gate
75
+ inside the hourly check).
71
76
  - Custom routines: `routine.custom.<slug>` (kebab-case slug)
72
77
  - Messaging: `message.dm`, `message.mention`
73
78
  - Dashboard: `dashboard.chat`, `dashboard.docs_qa`
@@ -73,22 +73,34 @@ DM is who fired the event.
73
73
  - **Catch-up**: if the daemon was offline at the trigger time, the
74
74
  scheduler re-fires the routine on next launch when it is still in
75
75
  the same agent day.
76
- - **Heavy / light tier**: only `routine.morning_routine` (and the
77
- one-shot `routine.morning_routine_initial`) run heavy by default
78
- (Opus on Claude, GPT-5.5 on Codex, Gemini 3 Pro on Gemini). Evening,
79
- weekly, and monthly reviews plus the hourly check default to light
80
- see [Backends and Tiers](backends-and-tiers.md).
76
+ - **Tier policy**: only the one-shot `routine.morning_routine_initial`
77
+ runs heavy by default (Opus on Claude, GPT-5.5 on Codex, Gemini 3
78
+ Pro on Gemini). Every other recurring routine morning, evening,
79
+ weekly, monthly, hourly check defaults to **medium** (Sonnet on
80
+ Claude). The lite (Haiku) tier is reserved for mechanical
81
+ sub-jobs: the hourly-check triage gate and the new pre-pass
82
+ fetcher. See [Backends and Tiers](backends-and-tiers.md).
83
+ - **Pre-pass fetcher**: each main routine that needs fresh mail /
84
+ calendar / Notion data is preceded by a lite-tier
85
+ `routine.fetch_window` session that fetches the relevant window and
86
+ POSTs observations. The main routine consumes the resulting
87
+ `<fetch_report>` block plus pending observations instead of
88
+ fetching upstream APIs itself. This is the cost-savings split
89
+ introduced in 2026-05.
81
90
 
82
91
  ## Concrete Examples
83
92
 
84
93
  | ProcessKey | When | Tier |
85
94
  |---|---|---|
86
95
  | `routine.morning_routine_initial` | First setup day, one-shot | heavy |
87
- | `routine.morning_routine` | `dayBoundaryHour` daily | heavy |
88
- | `routine.evening_review` | 18:00 daily (fixed) | light |
89
- | `routine.hourly_check` | Every `hourlyCheckIntervalMinutes` (default 60) inside the active window | light |
90
- | `routine.weekly_review` | Friday 18:00 (fixed) | light |
91
- | `routine.monthly_review` | Last day of month, 18:00 (fixed) | light |
96
+ | `routine.morning_routine` | `dayBoundaryHour` daily | medium |
97
+ | `routine.today_refresh` | Every 4h inside the active window | medium |
98
+ | `routine.evening_review` | 18:00 daily (fixed) | medium |
99
+ | `routine.hourly_check` | Every `hourlyCheckIntervalMinutes` (default 60) inside the active window | medium |
100
+ | `routine.weekly_review` | Friday 18:00 (fixed) | medium |
101
+ | `routine.monthly_review` | Last day of month, 18:00 (fixed) | medium |
102
+ | `routine.fetch_window` | Spawned before each routine above (except monthly) | lite |
103
+ | `routine.hourly_check.triage` | Stage 2 gate of every hourly check | lite |
92
104
  | `routine.custom.<slug>` | Operator-defined recurrence | configurable |
93
105
 
94
106
  ## Where You See It in the Dashboard
@@ -121,13 +121,8 @@ of "report to me" events. Information about what the agent did is
121
121
  - **`matchToolPattern`** — pattern matcher used everywhere `deniedTools`
122
122
  is enforced. Exact match (`send_email`), prefix glob (`send_*`), or
123
123
  bare `*`.
124
- - **`/api/integrations/:key/exec`** — the cross-backend chokepoint
125
- (task mode). Enforces `deniedTools` and the per-task allowed-tools
126
- envelope server-side before spawning a subprocess. The legacy RPC
127
- `/api/integrations/:key/invoke` route is retired (preserved as
128
- commented code for future reactivation; the internal
129
- `DelegatedBackendInvoker.invoke()` API remains wired for
130
- daemon-internal pollers).
124
+ - **`/api/integrations/:key/invoke`** — the cross-backend chokepoint.
125
+ Enforces `deniedTools` server-side before spawning a subprocess.
131
126
  - **`agent_actions`** — SQLite table of every agent action. Direct +
132
127
  cross-backend rows are full-fidelity. Same-backend native MCP rolls
133
128
  up to `mcp_tool_calls` + the parent session row.
@@ -137,7 +132,7 @@ of "report to me" events. Information about what the agent did is
137
132
  | Path | Enforcement |
138
133
  |---|---|
139
134
  | Direct mode (`/api/mail/*`, `/api/calendar/*`) | Route handler middleware checks `deniedTools` against the materialized skill body's `allowed-tools` list (frontmatter). |
140
- | Cross-backend (`/api/integrations/:key/exec`) | The task-mode subprocess is launched with the integration's allowed tools minus the user's `deniedTools`; daemon-side stream pre-emption aborts on out-of-allowlist `tool_use` events as `policy_violation`. |
135
+ | Cross-backend (`/api/integrations/:key/invoke`) | Endpoint handler runs `matchToolPattern(deniedPattern, tool)` before spawning. Returns `403 denied_tool` on hit. |
141
136
  | Same-backend native MCP — Claude | `collectSessionDeniedTools` merges the deny patterns into the SDK's `disallowedTools` array at `query()` time. |
142
137
  | Same-backend native MCP — Gemini | Patterns are folded into `generateAdminPolicy`'s TOML deny rules (priority 1000). |
143
138
  | Same-backend native MCP — Codex | **Prose-only.** Codex bundles its connector apps into the binary; there is no per-tool deny config and the workspace-write sandbox does not match MCP tool calls. Skill prose lists the denied tools explicitly. Operators who require strict deny on Gmail / Calendar should pick a non-Codex DM backend or run those integrations through the proxy. |
@@ -24,19 +24,24 @@ ask_examples:
24
24
  - Why does the agent refuse to run a tool?
25
25
  locale: en-US
26
26
  created: 2026-04-25
27
- updated: 2026-04-25
27
+ updated: 2026-05-04
28
28
  keywords:
29
29
  - SKILL.md
30
30
  - allowed-tools
31
31
  - skills-compiler
32
32
  - manifest
33
+ - self-optimization
34
+ - skill curation
35
+ - overlays
33
36
  related:
34
37
  - concepts/safety-and-execution
35
38
  - concepts/process-keys
36
39
  - reference/skills
40
+ - features/operations/skill-self-optimization
37
41
  ui_anchors:
38
42
  - /knowledge
39
43
  - /connections/mcp
44
+ - /settings/self-learning
40
45
  ---
41
46
 
42
47
  # Skills
@@ -84,12 +89,40 @@ visible to the model.
84
89
  `dashboard.docs_qa`.
85
90
  - `notify` — emit notifications through the configured messaging app.
86
91
 
92
+ ## Self-Optimization (Overlays)
93
+
94
+ Skills aren't frozen. A background process — **skill curation** —
95
+ watches how your knowledge layout drifts (file moves, new
96
+ sub-folders, schema tweaks in `user/`, `projects/`, etc.) and
97
+ proposes JSON **overlays** that update specific sections of the
98
+ relevant skill: knowledge layout, routing tables, frontmatter
99
+ schema, search recipes, convention notes, cross-references.
100
+
101
+ Overlays live at `<dataDir>/overlays/<skill>/<section-id>.json` and
102
+ are merged in by the SkillsCompiler at session-init. The original
103
+ `SKILL.md` files in `agent-assets/skills/` are never rewritten;
104
+ disabling the overlay (or deleting the JSON file) reverts to the
105
+ seed payload immediately.
106
+
107
+ The optimizer agent runs in an isolated workdir with a tightly
108
+ scoped toolset (`Bash(curl http://localhost:8321/api/skill-curation/*)`,
109
+ `Read`) and an auto-revert safety net — if the next run sees more
110
+ drift signals than the previous overlay generated, the section is
111
+ reverted and frozen for two cycles.
112
+
113
+ See [Skill Self-Optimization](../features/operations/skill-self-optimization.md)
114
+ for cadence, manual run, and the dashboard surface.
115
+
87
116
  ## Where You See It in the Dashboard
88
117
 
89
118
  - **Knowledge → Skills** lists every skill, its description, and the
90
119
  events it loads for.
91
120
  - **Connections → MCP** is where MCP servers (which surface as tools
92
121
  inside skills) attach.
122
+ - **Settings → Self-learning (`/settings/self-learning`)** is where
123
+ the curation cadence, model, and per-skill exclusions live, plus
124
+ a "Run optimization now" button and a rolled-up summary of the
125
+ most recent runs.
93
126
 
94
127
  ## Related
95
128
 
@@ -98,3 +131,5 @@ visible to the model.
98
131
  `allowed-tools` is too permissive.
99
132
  - [Process Keys](process-keys.md) — the dispatch identity that picks
100
133
  which skill manifest to load.
134
+ - [Skill Self-Optimization](../features/operations/skill-self-optimization.md) —
135
+ how overlays are generated and applied.
@@ -11,7 +11,10 @@ category: features
11
11
  summary: |
12
12
  The calendar integration pulls your events into Aitne so the
13
13
  morning routine, schedule files, and travel-time skill can reason
14
- about your day.
14
+ about your day. The Connections → Calendar page also picks the
15
+ backend that handles approaching-event notifications and observed
16
+ calendar changes (Calendar Event Model) — that picker only applies
17
+ when the integration runs in direct mode.
15
18
  section: integrations
16
19
  tags:
17
20
  - integration
@@ -22,22 +25,39 @@ ask_examples:
22
25
  - How do I connect my Google Calendar?
23
26
  - Why doesn't my calendar event show up in today's schedule?
24
27
  - Can the agent create calendar events?
28
+ - What is the Calendar Event Model setting on the Connections page?
29
+ - Why is the Calendar Event Model card missing when my calendar is delegated?
30
+ - Will Aitne notice calendar changes while my calendar is delegated?
31
+ - Which model handles approaching-event reminders?
25
32
  locale: en-US
26
33
  created: 2026-04-25
27
- updated: 2026-04-25
34
+ updated: 2026-04-28
28
35
  keywords:
29
36
  - calendar
30
37
  - google calendar
31
38
  - events
39
+ - calendar event model
40
+ - calendar.change
41
+ - approaching event
42
+ - reminder
43
+ - change observation
44
+ - calendar poller
45
+ - delegated mode
46
+ - direct mode
32
47
  related:
33
48
  - features/routines/morning-routine
34
49
  - features/memory-files/schedule
50
+ - concepts/delegated-mode
51
+ - concepts/process-keys
52
+ - concepts/observations
35
53
  ui_anchors:
36
54
  - /connections/calendar
37
55
  api_endpoints:
38
56
  - /api/calendar
39
57
  config_keys:
40
58
  - calendarPollIntervalSeconds
59
+ process_keys:
60
+ - calendar.change
41
61
  ---
42
62
 
43
63
  # Calendar
@@ -73,20 +93,71 @@ action). It does not auto-schedule on its own.
73
93
  ## Where in the Dashboard
74
94
 
75
95
  - **Connections → Calendar** holds OAuth, scope, and polling.
96
+ - The same page hosts the **Calendar Event Model** card (see below)
97
+ when Google Calendar is in direct mode.
98
+
99
+ ## Calendar Event Model
100
+
101
+ The Calendar Event Model picker chooses the backend and model that
102
+ runs when the agent reacts to a calendar event. It binds the
103
+ `calendar.change` ProcessKey, which fires from the calendar poller in
104
+ three situations:
105
+
106
+ - An event is about to start (the operator gets an approaching-event
107
+ reminder).
108
+ - An event was added, moved, or deleted between polls (recorded as a
109
+ change observation; the hourly check picks it up).
110
+ - An event was created far in advance (long-horizon events nudge the
111
+ roadmap-refresh routine so `roadmap.md` can build a preparation
112
+ timeline).
113
+
114
+ Light tier is the default and almost always sufficient — these flows
115
+ are classification and scheduling, not generation. The default backend
116
+ is whichever you picked as your main backend during setup; you can
117
+ override per-process here if you want a different mix.
118
+
119
+ The picker is **only meaningful when Google Calendar runs in direct
120
+ mode.** In delegated mode the daemon hands off all Google Calendar
121
+ work to the connector inside your agent's backend, so:
122
+
123
+ - No approaching-event reminders fire from the daemon.
124
+ - No change observations are recorded between polls.
125
+ - The hourly check has no calendar-side observations to react to.
126
+ - Long-horizon roadmap-refresh nudges from calendar do not fire.
127
+
128
+ The agent only learns about calendar state in delegated mode when it
129
+ asks the connector itself inside a session (for example, while
130
+ running the morning routine). It is a pull-only model — the daemon
131
+ does not push.
132
+
133
+ To avoid presenting a setting that does nothing, the dashboard hides
134
+ the Calendar Event Model card whenever Google Calendar is delegated.
135
+ If you want approaching-event reminders and change observations back,
136
+ switch the integration mode to direct on the same page.
76
137
 
77
138
  ## Configuration
78
139
 
79
140
  | Setting | Default | Notes |
80
141
  |---|---|---|
81
- | `calendarPollIntervalSeconds` | 300 | How often to poll for changes. |
142
+ | `calendarPollIntervalSeconds` | 300 | How often to poll for changes (direct mode only). |
143
+
144
+ The Calendar Event Model is configured through its dashboard card
145
+ rather than an env-style setting; the underlying state lives in the
146
+ `process_backend_config` table for the `calendar.change` row.
82
147
 
83
148
  ## When Something Goes Wrong
84
149
 
85
150
  - A **stale calendar** in `/schedule` after a real-world add usually
86
151
  means the poll has not yet run. Check the next-fire timestamp.
87
152
  - An **OAuth-expired** state reports on the auth-health card.
153
+ - **No reminders or change observations** while in delegated mode is
154
+ expected behavior, not a bug — switch to direct mode to restore the
155
+ daemon-side flows. See "Calendar Event Model" above.
88
156
 
89
157
  ## Related
90
158
 
91
159
  - [Morning Routine](../routines/morning-routine.md)
92
160
  - [daily/ files](../memory-files/schedule.md)
161
+ - [Delegated Mode](../../concepts/delegated-mode.md)
162
+ - [ProcessKeys](../../concepts/process-keys.md)
163
+ - [Observations](../../concepts/observations.md)
@@ -52,8 +52,8 @@ flagging.
52
52
 
53
53
  - **Polls** each watched repo every `gitPollIntervalSeconds`.
54
54
  - **Records observations** when new commits land between polls. The
55
- commit range, changed files, and summary stats are included so the
56
- hourly check can decide whether the activity matters.
55
+ commit author is included so agent-originated commits do not
56
+ re-surface to the agent (defended via `AgentWriteTracker`).
57
57
  - **Surfaces patterns**, not individual commits — three small commits
58
58
  in an hour will not page you.
59
59
 
@@ -83,8 +83,8 @@ by design.
83
83
  ## When Something Goes Wrong
84
84
 
85
85
  - A **missing observation** for a commit you just made: check that the
86
- repo path is actually watched on `/connections/repositories` and that
87
- the poll has fired since.
86
+ repo path is actually watched on `/connections/git` and that the
87
+ poll has fired since.
88
88
  - A repo that **never appears** in observations: the agent's own
89
89
  writes are filtered out (see `AgentWriteTracker`); make sure the
90
90
  commit was authored by you, not by an agent session.
@@ -10,161 +10,129 @@ aliases:
10
10
  category: features
11
11
  summary: |
12
12
  GitHub is the remote-side counterpart to the Git integration. The
13
- daemon polls the user's notifications feed and watched-repo CI failures
14
- via the local `gh` CLI, recording observations and DM-ing the user
15
- about high-priority signals (review requests, default-branch CI failures,
16
- Dependabot alerts, assignments). The agent never auto-comments,
17
- auto-merges, or pushes.
13
+ daemon polls notifications and CI failures via the local `gh` CLI;
14
+ high-priority signals (review requests, default-branch CI failures,
15
+ security alerts, assignments) become direct DMs.
18
16
  section: integrations
19
17
  tags:
20
18
  - integration
21
19
  - github
22
20
  - observation
23
- - polling
24
21
  status: stable
25
22
  ask_examples:
26
23
  - How do I connect GitHub?
27
24
  - Will the agent message me on every CI failure?
28
25
  - Can the agent reply to GitHub issues?
29
- - Why isn't the GitHub poller firing?
30
26
  locale: en-US
31
27
  created: 2026-04-25
32
28
  updated: 2026-04-28
33
- keywords:
34
- - github
35
- - notifications
36
- - workflow_run
37
- - review_requested
38
- - gh cli
39
29
  related:
40
30
  - features/integrations/git
41
- - features/routines/hourly-check
42
31
  - concepts/observations
43
32
  ui_anchors:
44
33
  - /connections/repositories
45
- config_keys:
46
- - githubPollIntervalSeconds
47
- - gitRepos
48
- - githubRepos
49
34
  ---
50
35
 
51
36
  # GitHub
52
37
 
53
38
  ## In One Sentence
54
39
 
55
- The daemon polls GitHub Notifications + watched-repo CI failures via
56
- the local `gh` CLI, surfacing high-priority signals as DMs and feeding
57
- everything else into the hourly check.
40
+ The daemon polls GitHub via the local `gh` CLI: review requests, CI
41
+ failures on the default branch, security alerts, and assignments
42
+ become DMs; everything else is recorded for the hourly check.
58
43
 
59
- ## How It Works
44
+ ## What It Does
60
45
 
61
- GitHub access is **delegated to the local `gh` CLI** rather than carried
62
- by a daemon-side personal access token. Authentication happens once via
63
- `gh auth login`; the daemon shells out to `gh api …` per poll. This
64
- keeps secrets in the OS keychain that `gh` already manages, and lines
65
- up with the future delegated-mode story (Claude / Codex / Gemini will
66
- share the same auth path).
46
+ - **Polls Notifications** every `githubPollIntervalSeconds` (default
47
+ 600s) using ETag caching 304s cost no rate-limit quota.
48
+ - **Polls workflow_runs** per watched GitHub repository on the same
49
+ cadence, filtered by `status=failure`. Watched repos can come from a
50
+ local clone's GitHub `origin` or from an explicit `owner/repo` entry.
51
+ - **DMs the user** on the four high-priority triggers below; quieter
52
+ signals are coalesced into the hourly check summary.
67
53
 
68
- Two cadences run on a single timer:
54
+ The agent never auto-comments, auto-merges, or pushes.
69
55
 
70
- 1. **Notifications** — `gh api notifications` with ETag caching.
71
- 304 Not Modified responses cost zero rate quota.
72
- 2. **Workflow runs** — per watched GitHub repo (any explicit
73
- `owner/repo` entry in the GitHub card, plus any entry in the
74
- Git Repositories card whose `origin` resolves to GitHub),
75
- `gh api repos/<owner>/<name>/actions/runs?status=failure`.
56
+ ## High-priority events
76
57
 
77
- When `githubRepos` is non-empty, notification processing is scoped to
78
- those `owner/repo` entries. When it is empty, the poller preserves the
79
- older behavior and processes the authenticated user's unread
80
- notifications globally.
58
+ The agent will DM the user (priority `high`, can break quiet hours
59
+ depending on your notify-skill settings) on:
81
60
 
82
- The classifier maps each event to either a `recordObservation` call
83
- (for the hourly check to coalesce) or both an observation **and** an
84
- EventBus emit (for high-priority signals that warrant a direct DM).
61
+ - A teammate or bot **requested your review** on a PR.
62
+ - You were **assigned** to an issue or PR.
63
+ - A **Dependabot or code-scanning security alert** fired on a watched
64
+ repository.
65
+ - A **default-branch CI failure** (feature-branch failures stay
66
+ observation-only — they're the normal developer feedback loop).
85
67
 
86
- ## High-priority events
87
-
88
- | Trigger | Event type | Task-flow |
89
- |---|---|---|
90
- | `notifications.reason === "review_requested"` | `github.pull_request.review_requested` | `github.pull_request.review_requested.md` |
91
- | `notifications.reason === "assign"` | `github.assigned` | `github.assigned.md` |
92
- | `notifications.reason === "security_alert"` | `github.security_alert` | `github.security_alert.md` |
93
- | Workflow run failure on default branch | `github.workflow_run.failed` | `github.workflow_run.failed.md` |
68
+ Each DM follows the notify skill's awareness-gate: if the agent already
69
+ sees you triaging it in `today.md`, it stays silent and just logs.
94
70
 
95
- Feature-branch CI failures stay observation-only (LOW priority) — they
96
- are the developer's normal feedback loop, not interruption-worthy.
71
+ ## Setup
97
72
 
98
- ## Cold-start safety
73
+ 1. Install `gh`: `brew install gh` on macOS; see
74
+ [cli.github.com](https://cli.github.com/) for other platforms.
75
+ 2. Authenticate: `gh auth login` (browser flow).
76
+ 3. Add `owner/repo` entries to **Connections → GitHub**, or add local
77
+ repository paths to **Connections → Git Repositories**. For local
78
+ paths, the poller derives `owner/name` from each repo's `origin`
79
+ remote — non-GitHub remotes are silently skipped.
80
+ 4. Restart the daemon (the poll interval is captured at start time).
99
81
 
100
- On first start with a fresh database, the workflow-runs path records
101
- the latest failures without emitting direct events. This prevents the
102
- user from waking up to 30 stale CI-failure DMs after enabling the
103
- integration while still warming the idempotency table. Notifications are
104
- inherently cold-start-safe because GitHub returns only currently-unread
105
- notifications.
82
+ The daemon does NOT need a personal access token in its keychain — it
83
+ re-uses whatever `gh` already has.
106
84
 
107
- ## Idempotency
85
+ ## Cold-start behavior
108
86
 
109
- Every emission goes through a pre-check: `SELECT 1 FROM observations
110
- WHERE source = ? AND ref = ?` covers both consumed and pending rows.
111
- If a `review_requested` notification stays unread for an hour and you
112
- poll every 10 minutes, the user is DM'd **once**, not six times.
87
+ The first time the daemon polls a watched repo, it records the latest
88
+ failed workflow runs **without emitting any events**. This prevents a
89
+ flood of DMs about historical CI failures the user has already triaged.
90
+ New failures landing after that warm-up are surfaced normally.
113
91
 
114
92
  ## Where in the Dashboard
115
93
 
116
- - **Connections → GitHub** shows the integration status, the
117
- `gh auth login` reminder, explicit `owner/repo` watched repos, and
118
- event model routing cards.
119
- - **Git Repositories** on the same page lists local clone paths whose
120
- GitHub remotes are also watched for workflow failures.
94
+ - **Connections → GitHub** shows status and the `gh auth login`
95
+ hint.
96
+ - **Connections GitHub** controls explicit `owner/repo` watched repos.
97
+ When this list is non-empty, notification processing is scoped to it.
98
+ - **Connections Git Repositories** controls local clone paths whose
99
+ GitHub remotes are watched for workflow_run failures.
121
100
 
122
101
  ## Configuration
123
102
 
124
103
  | Setting | Default | Notes |
125
104
  |---|---|---|
126
- | `githubPollIntervalSeconds` | 600 | Both notifications and workflow_runs poll on this cadence. Restart-required (the timer is captured at construction time). |
127
- | `gitRepos` | `[]` | Local repo paths. The poller derives `owner/name` via `git remote get-url origin` for each entry whose remote is on GitHub. |
128
- | `githubRepos` | `[]` | Direct remote repos in `owner/repo` form. Enables workflow polling without a local clone and scopes GitHub notification processing when non-empty. |
105
+ | `githubPollIntervalSeconds` | 600 (10 min) | Both poll cadences. Lower for faster review-request alerts at the cost of slightly more rate-limit budget. **Restart-required.** |
106
+ | `gitRepos` | `[]` | Local repo paths to watch. |
107
+ | `githubRepos` | `[]` | Direct remote repos in `owner/repo` form. Also scopes notification processing when non-empty. |
129
108
 
130
109
  ## When Something Goes Wrong
131
110
 
132
- - **`gh` CLI not found.** The daemon log shows `\`gh\` CLI is not on
133
- PATH install via \`brew install gh\` (or platform equivalent),
134
- then \`gh auth login\``. Polls stay quiet (exponential backoff up
135
- to 16 ticks ≈ 2.6 hours at default cadence) until `gh` is
136
- reachable.
137
- - **Authentication expired.** `gh auth status` non-zero produces
138
- a `GitHub poll failed (auth)` warning per backoff cycle. Log in
139
- again with `gh auth login`.
140
- - **No DMs for a known PR review request.** Confirm the notification
141
- is actually surfaced via `gh api notifications` from your shell —
142
- if it's missing there too, GitHub's own notification routing has
143
- filtered it (watch / mention settings on the source repo).
144
- - **Wrong default branch detection.** The poller queries
145
- `gh api repos/<o>/<r> --jq .default_branch` once at startup. If
146
- this lookup fails (rate limit, transient network), the cached
147
- default is `main`. Restart the daemon after the issue clears to
148
- re-resolve.
149
-
150
- ## Backend routing
151
-
152
- High-priority GitHub events are first-class process keys:
153
-
154
- - `github.pull_request.review_requested`
155
- - `github.assigned`
156
- - `github.security_alert`
157
- - `github.workflow_run.failed`
158
-
159
- Configure them under **Connections → Git & Code** or **Settings →
160
- Models → Process Routing**. Each row can route to Claude Code, Codex,
161
- or Gemini CLI, with the same fallback, auth-health, turn-limit, and
162
- cost-audit behavior as other autonomous processes.
111
+ - **No DMs after enabling.** Run `gh auth status` from your shell. If
112
+ it reports anything other than logged-in, the daemon log will show
113
+ a backoff message — re-run `gh auth login` and the next poll tick
114
+ picks up.
115
+ - **`gh` not installed.** Daemon logs warn with the install command;
116
+ the observer keeps retrying with exponential backoff (capped at
117
+ ~16 ticks).
118
+ - **Default branch detected as `main` but mine is `master`.** The
119
+ one-time `gh api repos/<o>/<r> --jq .default_branch` lookup at
120
+ startup failed (rate limit or transient). Restart after the
121
+ condition clears.
122
+ - **Repeated DMs for the same notification.** Should not happen — the
123
+ poller pre-checks `observations(source, ref)` before every emit. If
124
+ it does, file a bug with the notification id.
125
+
126
+ ## Delegated mode (coming soon)
127
+
128
+ A future release will let Claude Code, Codex, or Gemini CLI handle
129
+ GitHub directly via their native MCP / `gh` integrations, optionally
130
+ replacing the daemon-side poller. Most users won't need this — the
131
+ built-in poller already covers the common surface — but it'll be
132
+ useful if you'd rather skip the daemon-side polling entirely.
163
133
 
164
134
  ## Related
165
135
 
166
136
  - [Git](git.md) — local repo file watcher (separate observer).
167
- - [Hourly Check](../routines/hourly-check.md) — consumer of
168
- observation-only signals.
169
- - [Observations](../../concepts/observations.md) — the storage
170
- contract this poller writes against.
137
+ - [Hourly Check](../routines/hourly-check.md) — the consumer of
138
+ non-DM-priority observations.