@aitne-sh/aitne 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +295 -479
- package/agent-assets/agent-profiles/_safety.md +17 -2
- package/agent-assets/agent-profiles/routine-fetch-window.md +75 -40
- package/agent-assets/agent-profiles/wiki-agent.md +19 -0
- package/agent-assets/docs/features/messaging/bang-commands.md +161 -0
- package/agent-assets/docs/features/messaging/overview.md +3 -0
- package/agent-assets/docs/features/wiki/commands.md +222 -0
- package/agent-assets/docs/features/wiki/overview.md +145 -0
- package/agent-assets/docs/getting-started/03-what-can-this-do.md +18 -0
- package/agent-assets/docs/glossary.md +34 -0
- package/agent-assets/docs/guides/budget-and-cost-for-wiki.md +123 -0
- package/agent-assets/docs/guides/build-your-wiki.md +99 -0
- package/agent-assets/docs/guides/explore-with-trace-and-connect.md +169 -0
- package/agent-assets/docs/guides/maintain-wiki-health.md +168 -0
- package/agent-assets/docs/guides/multiple-wikis-for-multiple-domains.md +192 -0
- package/agent-assets/docs/guides/pause-the-agent.md +10 -3
- package/agent-assets/docs/guides/use-an-existing-obsidian-vault.md +156 -0
- package/agent-assets/docs/reference/cli-commands.md +24 -1
- package/agent-assets/docs/troubleshooting/wiki-ingest-full-blocked.md +96 -0
- package/agent-assets/docs/troubleshooting/wiki-write-failed.md +82 -0
- package/agent-assets/skills/context/SKILL.md +288 -17
- package/agent-assets/skills/external-services/SKILL.delegated.claude.md +2 -2
- package/agent-assets/skills/external-services/SKILL.delegated.codex.md +3 -3
- package/agent-assets/skills/external-services/SKILL.delegated.gemini.md +6 -6
- package/agent-assets/skills/external-services/SKILL.md +5 -3
- package/agent-assets/skills/external-services/SKILL.native.claude.md +49 -58
- package/agent-assets/skills/external-services/SKILL.native.codex.md +50 -58
- package/agent-assets/skills/external-services/SKILL.native.gemini.md +53 -56
- package/agent-assets/skills/mail/SKILL.md +5 -5
- package/agent-assets/skills/mail/SKILL.native.claude.md +57 -65
- package/agent-assets/skills/mail/SKILL.native.codex.md +73 -75
- package/agent-assets/skills/mail/SKILL.native.gemini.md +80 -75
- package/agent-assets/skills/management-task-register/SKILL.md +3 -3
- package/agent-assets/skills/notion/SKILL.native.claude.md +78 -82
- package/agent-assets/skills/notion/SKILL.native.codex.md +78 -80
- package/agent-assets/skills/notion/SKILL.native.gemini.md +91 -90
- package/agent-assets/skills/observations/SKILL.md +104 -14
- package/agent-assets/skills/roadmap/SKILL.md +19 -0
- package/agent-assets/skills/schedule/SKILL.md +44 -3
- package/agent-assets/skills/today/SKILL.md +25 -5
- package/agent-assets/skills/travel-time/SKILL.md +9 -0
- package/agent-assets/skills/wiki/wiki-ask/SKILL.md +32 -0
- package/agent-assets/skills/wiki/wiki-compile/SKILL.md +126 -0
- package/agent-assets/skills/wiki/wiki-connect/SKILL.md +75 -0
- package/agent-assets/skills/wiki/wiki-graduate/SKILL.md +45 -0
- package/agent-assets/skills/wiki/wiki-ingest/SKILL.md +182 -0
- package/agent-assets/skills/wiki/wiki-lint/SKILL.md +90 -0
- package/agent-assets/skills/wiki/wiki-trace/SKILL.md +72 -0
- package/agent-assets/skills/wiki/wiki-vault-rules/SKILL.md +145 -0
- package/agent-assets/task-flows/_partials/calendar-acquire.google_calendar.md +28 -9
- package/agent-assets/task-flows/_partials/calendar-acquire.outlook_calendar.md +26 -9
- package/agent-assets/task-flows/_partials/mail-acquire.gmail.md +51 -24
- package/agent-assets/task-flows/_partials/mail-acquire.outlook_mail.md +46 -16
- package/agent-assets/task-flows/_partials/notion-acquire.notion.md +29 -9
- package/agent-assets/task-flows/message.received.dm.md +35 -2
- package/agent-assets/task-flows/message.received.dm.native.claude.md +25 -26
- package/agent-assets/task-flows/message.received.dm.native.codex.md +30 -24
- package/agent-assets/task-flows/message.received.dm.native.gemini.md +36 -36
- package/agent-assets/task-flows/message.received.dm_first.md +43 -4
- package/agent-assets/task-flows/message.received.dm_first.native.claude.md +20 -20
- package/agent-assets/task-flows/message.received.dm_first.native.codex.md +22 -19
- package/agent-assets/task-flows/message.received.dm_first.native.gemini.md +28 -24
- package/agent-assets/task-flows/routine.fetch_window.md +51 -36
- package/agent-assets/task-flows/routine.morning_routine.md +12 -3
- package/agent-assets/task-flows/routine.morning_routine_initial.md +22 -1
- package/agent-assets/task-flows/scheduled.dm.md +477 -0
- package/agent-assets/task-flows/wiki.ask.md +11 -0
- package/agent-assets/task-flows/wiki.compile.md +28 -0
- package/agent-assets/task-flows/wiki.connect.md +12 -0
- package/agent-assets/task-flows/wiki.ingest_url.md +35 -0
- package/agent-assets/task-flows/wiki.lint.md +13 -0
- package/agent-assets/task-flows/wiki.trace.md +13 -0
- package/agent-assets/wiki-seeds/schemas/output.md +12 -0
- package/agent-assets/wiki-seeds/schemas/raw.md +13 -0
- package/agent-assets/wiki-seeds/schemas/wiki.md +12 -0
- package/agent-assets/wiki-seeds/taxonomy.md +13 -0
- package/package.json +21 -41
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: notion
|
|
3
|
-
description: Load when the task touches Notion and Notion is in native mode bound to Gemini (`nativeBackend === "gemini"`). Use the
|
|
3
|
+
description: Load when the task touches Notion and Notion is in native mode bound to Gemini (`nativeBackend === "gemini"`). Use the in-session Notion connector your Gemini harness exposes directly; the daemon does not proxy Notion. `/api/notion/databases` (label → UUID config dump) is the only daemon route still reachable.
|
|
4
4
|
allowed-tools:
|
|
5
5
|
- Bash(curl *)
|
|
6
6
|
- Bash(jq *)
|
|
7
7
|
- Read
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
# Notion (native —
|
|
10
|
+
# Notion (native — in-session Notion connector)
|
|
11
11
|
|
|
12
12
|
> **Refusal directive — read first.** Notion is in `native` mode bound
|
|
13
13
|
> to Gemini. Do **NOT** call any of:
|
|
@@ -18,22 +18,22 @@ allowed-tools:
|
|
|
18
18
|
> - `/api/notion/query`, `/api/notion/search`, `/api/notion/pages`,
|
|
19
19
|
> `/api/notion/pages/<id>/content` (each route-prefix 410)
|
|
20
20
|
>
|
|
21
|
-
> Reach Notion through the
|
|
22
|
-
>
|
|
21
|
+
> Reach Notion through the in-session Notion connector your harness
|
|
22
|
+
> exposes (typically a user-installed Notion MCP server registered
|
|
23
|
+
> against the Gemini CLI). Your tool menu lists every available tool at
|
|
24
|
+
> session start — pick the Notion one.
|
|
23
25
|
>
|
|
24
26
|
> Exception: **`GET /api/notion/databases`** remains reachable in every
|
|
25
27
|
> mode (config dump, no Notion API side-effect).
|
|
26
28
|
|
|
27
|
-
##
|
|
29
|
+
## Connector presence assumption
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
the
|
|
34
|
-
|
|
35
|
-
missing and the dashboard surfaces an actionable "wrong server name"
|
|
36
|
-
hint. This skill body assumes the probe passed.
|
|
31
|
+
Native:gemini mode assumes a Notion MCP server is registered against
|
|
32
|
+
the user's Gemini CLI. The §9.3 probe at flip time verifies every
|
|
33
|
+
required capability is reachable from the in-session tool menu; if the
|
|
34
|
+
probe fails (wrong server name, server not registered, or capabilities
|
|
35
|
+
missing), the dashboard surfaces an actionable hint and the mode does
|
|
36
|
+
not flip. This skill body assumes the probe passed.
|
|
37
37
|
|
|
38
38
|
Confirm the binding via `<integration_modes>` (`notion="native"`) and
|
|
39
39
|
the `<integration-routing-table>` block in the session preamble.
|
|
@@ -47,106 +47,107 @@ curl -s http://localhost:8321/api/notion/databases
|
|
|
47
47
|
|
|
48
48
|
Resolve label → UUID before any Notion call.
|
|
49
49
|
|
|
50
|
-
## 2. Notion —
|
|
50
|
+
## 2. Notion — in-session connector
|
|
51
|
+
|
|
52
|
+
The exact tool names depend on which Notion MCP server the user has
|
|
53
|
+
registered against their Gemini CLI. Inspect your tool menu at session
|
|
54
|
+
start and pick the matching capability. Notion's official MCP server
|
|
55
|
+
exposes hyphenated identifiers (search / fetch / get-comments / …);
|
|
56
|
+
under Gemini's namespace convention they surface with a server prefix.
|
|
57
|
+
The capability classes below are stable across connectors; the exact
|
|
58
|
+
tool names depend on the server you have loaded.
|
|
59
|
+
|
|
60
|
+
### Read-class capabilities
|
|
61
|
+
|
|
62
|
+
| Capability | What to do |
|
|
63
|
+
|---|---|
|
|
64
|
+
| `search` | Workspace search (text + Notion query parameters), optionally filtered to a specific data source. |
|
|
65
|
+
| `read` | Retrieve a single page / database / block by URL or UUID; returns block tree. |
|
|
66
|
+
| `comments` | Read page comments. |
|
|
67
|
+
| `users` | Enumerate workspace users. |
|
|
68
|
+
| `teams` | Enumerate teams / teamspaces. |
|
|
69
|
+
|
|
70
|
+
Canonical search flow: invoke your connector's search function with
|
|
71
|
+
the user's text query and the data-source URL constructed from the
|
|
72
|
+
resolved UUID (e.g.
|
|
73
|
+
`https://www.notion.so/<workspace>/<database-uuid>`).
|
|
74
|
+
|
|
75
|
+
Canonical page read: invoke your connector's fetch / read-page
|
|
76
|
+
function with the page's URL or UUID.
|
|
77
|
+
|
|
78
|
+
### Destructive capabilities (require explicit user confirmation)
|
|
79
|
+
|
|
80
|
+
Per the registry's `notion.backendConnectors.gemini.destructiveTools`,
|
|
81
|
+
the following capability classes are destructive in native:gemini mode:
|
|
82
|
+
|
|
83
|
+
- **Page creation** — adds new pages (batch-aware on most connectors).
|
|
84
|
+
- **Page update** — mutates properties / content; **also** the archive
|
|
85
|
+
workaround (Status="Archived") — §3 below.
|
|
86
|
+
- **Page duplicate** — clones a page.
|
|
87
|
+
- **Page move** — relocates pages between databases / parents.
|
|
88
|
+
- **Comment create** — posts a comment (user-visible).
|
|
89
|
+
- **Database create** — schema admin (creates new DB).
|
|
90
|
+
- **Data-source update** — schema admin (mutates DB columns).
|
|
91
|
+
- **View create / update** — schema admin (new view / mutates view
|
|
92
|
+
config).
|
|
93
|
+
|
|
94
|
+
Apply the destructive-confirm contract every time. Schema-admin
|
|
95
|
+
capability classes warrant an explicit "schema admin" label on the
|
|
96
|
+
surfaced plan. The starter `deniedTools` list is enforced before the
|
|
97
|
+
call lands.
|
|
51
98
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
The Notion MCP server exposes the same tool names as Anthropic's hosted
|
|
55
|
-
Notion connector (hyphenated identifiers, e.g. `notion-search`); under
|
|
56
|
-
Gemini's namespace convention they surface as `mcp_notion_<tool>`.
|
|
57
|
-
|
|
58
|
-
### Read-class tools
|
|
59
|
-
|
|
60
|
-
| Capability | Tool | Use |
|
|
61
|
-
|---|---|---|
|
|
62
|
-
| `search` | `mcp_notion_notion-search` | Workspace search. |
|
|
63
|
-
| `read` | `mcp_notion_notion-fetch` | Single page / database / block by URL or UUID. |
|
|
64
|
-
| `comments` | `mcp_notion_notion-get-comments` | Read page comments. |
|
|
65
|
-
| `users` | `mcp_notion_notion-get-users` | Enumerate workspace users. |
|
|
66
|
-
| `teams` | `mcp_notion_notion-get-teams` | Enumerate teams. |
|
|
67
|
-
|
|
68
|
-
Canonical search call:
|
|
69
|
-
|
|
70
|
-
```
|
|
71
|
-
mcp_notion_notion-search(
|
|
72
|
-
query="acme proposal",
|
|
73
|
-
data_source_url="https://www.notion.so/<workspace>/<database-uuid>"
|
|
74
|
-
)
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Canonical page read:
|
|
78
|
-
|
|
79
|
-
```
|
|
80
|
-
mcp_notion_notion-fetch(id="<page-url-or-uuid>")
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### Destructive tools (require explicit user confirmation)
|
|
84
|
-
|
|
85
|
-
Per the registry's `notion.backendConnectors.gemini.destructiveTools`:
|
|
86
|
-
|
|
87
|
-
- `mcp_notion_notion-create-pages`
|
|
88
|
-
- `mcp_notion_notion-update-page` — properties / content / archive
|
|
89
|
-
workaround.
|
|
90
|
-
- `mcp_notion_notion-duplicate-page`
|
|
91
|
-
- `mcp_notion_notion-move-pages`
|
|
92
|
-
- `mcp_notion_notion-create-comment`
|
|
93
|
-
- `mcp_notion_notion-create-database` — schema admin.
|
|
94
|
-
- `mcp_notion_notion-update-data-source` — schema admin.
|
|
95
|
-
- `mcp_notion_notion-create-view` — schema admin.
|
|
96
|
-
- `mcp_notion_notion-update-view` — schema admin.
|
|
99
|
+
## 3. Page archive — workaround only
|
|
97
100
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
starter `deniedTools` list is enforced before the call lands.
|
|
101
|
+
Same gap as Claude / Codex hosted connectors — typically no dedicated
|
|
102
|
+
archive tool. To "archive":
|
|
101
103
|
|
|
102
|
-
|
|
104
|
+
1. **Property workaround** (preferred): update the page's Status
|
|
105
|
+
property to "Archived" via the page-update capability.
|
|
106
|
+
2. **Move to a "Trash" page**: relocate the page under a top-level
|
|
107
|
+
"Trash" page via the page-move capability.
|
|
103
108
|
|
|
104
|
-
|
|
105
|
-
tool. Use the property-update workaround (Status="Archived") via
|
|
106
|
-
`mcp_notion_notion-update-page`, or move the page under a top-level
|
|
107
|
-
Trash page via `mcp_notion_notion-move-pages`. Surface the choice.
|
|
109
|
+
Surface the choice to the user.
|
|
108
110
|
|
|
109
111
|
## 4. Decision rules
|
|
110
112
|
|
|
111
113
|
- **Hourly check is read-only** — inherits the constraint from
|
|
112
114
|
`routine.hourly_check.native.gemini.md`.
|
|
113
|
-
- **Mass-update — ask first.**
|
|
114
|
-
|
|
115
|
-
confirmation.
|
|
115
|
+
- **Mass-update — ask first.** Batch page-creation can take up to 100
|
|
116
|
+
pages; batches >~10 pages warrant explicit confirmation.
|
|
116
117
|
- **Schema admin — Approve-tier.** Database / view / data-source
|
|
117
118
|
mutations alter workspace structure.
|
|
118
|
-
- **Comments are user-visible.**
|
|
119
|
-
|
|
120
|
-
- **No
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
119
|
+
- **Comments are user-visible.** Posting a page comment is treated
|
|
120
|
+
like a send: confirm before issuing.
|
|
121
|
+
- **No SQL-style structured query on this surface.** Notion's official
|
|
122
|
+
MCP server (the typical native:gemini connector) does not expose a
|
|
123
|
+
structured-filter primitive equivalent to Codex's
|
|
124
|
+
`query_data_sources`. For "what tasks are in status X" intents, use
|
|
125
|
+
the workspace search capability with a data-source filter scoping
|
|
126
|
+
the request and process the result client-side.
|
|
125
127
|
|
|
126
128
|
## 5. Persisting observations from native fetches
|
|
127
129
|
|
|
130
|
+
**Batch when you have more than one page.** Use
|
|
131
|
+
`POST /api/observations/batch` with up to 200 items in one
|
|
132
|
+
`observations[]` array (see the `observations` skill for the envelope).
|
|
133
|
+
The single-item form below is for the rare "one page changed" case.
|
|
134
|
+
|
|
128
135
|
```bash
|
|
129
136
|
curl -s -X POST http://localhost:8321/api/observations \
|
|
130
137
|
-H 'Content-Type: application/json' \
|
|
131
138
|
-d '{
|
|
132
|
-
"source": "notion",
|
|
133
|
-
"type": "notion:lifecycle",
|
|
139
|
+
"source": "notion:<workspaceId>",
|
|
134
140
|
"ref": "<pageId>",
|
|
135
|
-
"
|
|
136
|
-
"
|
|
137
|
-
"
|
|
138
|
-
"refs": {
|
|
139
|
-
"pageId": "<id>",
|
|
140
|
-
"parentDatabase": "<db-uuid-or-null>",
|
|
141
|
-
"title": "<title>"
|
|
142
|
-
},
|
|
143
|
-
"payload": <verbatim MCP page object>
|
|
141
|
+
"changeType": "created",
|
|
142
|
+
"actor": "agent",
|
|
143
|
+
"payload": <verbatim connector page object>
|
|
144
144
|
}'
|
|
145
145
|
```
|
|
146
146
|
|
|
147
147
|
The daemon computes `contentHash` server-side. Pass `payload`
|
|
148
|
-
verbatim.
|
|
149
|
-
|
|
148
|
+
verbatim. `actor` MUST be `"agent"` or `"system"` — the server
|
|
149
|
+
rejects `"user"`. HTTP 409 → mode-flip race window (§11.3.1); stop
|
|
150
|
+
and re-read `<integration_modes>`.
|
|
150
151
|
|
|
151
152
|
## 6. Owner notification (opt-in)
|
|
152
153
|
|
|
@@ -133,6 +133,65 @@ creating a duplicate. Subkind suffixes after the colon are by
|
|
|
133
133
|
convention (`roadmap_candidate:calendar`, `roadmap_candidate:vault`,
|
|
134
134
|
etc.) and are picked up by the prefix match on the GET route.
|
|
135
135
|
|
|
136
|
+
### POST /api/observations/batch
|
|
137
|
+
|
|
138
|
+
Bulk-insert up to 200 observations in a single transaction. Use this
|
|
139
|
+
whenever a single fetch surface (a mail window, a calendar query, a
|
|
140
|
+
Notion page list) yields more than one observation — calling
|
|
141
|
+
`POST /api/observations` once per item collides with the Bash hook
|
|
142
|
+
that caps each curl invocation at one HTTP request and strips heredoc
|
|
143
|
+
bodies before URL validation. The batch endpoint resolves the
|
|
144
|
+
cardinality mismatch without weakening either hook.
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
curl -s -X POST http://localhost:8321/api/observations/batch \
|
|
148
|
+
-H 'Content-Type: application/json' \
|
|
149
|
+
-d @- <<'JSON'
|
|
150
|
+
{
|
|
151
|
+
"observations": [
|
|
152
|
+
{"source":"gmail:acct-1","ref":"msg-123","changeType":"created","actor":"agent",
|
|
153
|
+
"payload":{"kind":"mail","providerId":"acct-1","raw":{"subject":"…","from":"…","snippet":"…","date":"…"}}},
|
|
154
|
+
{"source":"gmail:acct-1","ref":"msg-124","changeType":"created","actor":"agent",
|
|
155
|
+
"payload":{"kind":"mail","providerId":"acct-1","raw":{"subject":"…","from":"…","snippet":"…","date":"…"}}}
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
JSON
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Per-element shape mirrors `POST /api/observations` exactly. Same
|
|
162
|
+
forgery guard (`actor` must be `"agent"` or `"system"`), same
|
|
163
|
+
server-side `(source, payload)` content-hash dedup.
|
|
164
|
+
|
|
165
|
+
Response is always `200` with envelope:
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"results": [
|
|
170
|
+
{"index":0,"status":"created","source":"gmail:acct-1","ref":"msg-123","contentHash":"…","id":42},
|
|
171
|
+
{"index":1,"status":"duplicate","source":"gmail:acct-1","ref":"msg-124","contentHash":"…","id":17}
|
|
172
|
+
],
|
|
173
|
+
"fetched": 2,
|
|
174
|
+
"posted": 1,
|
|
175
|
+
"duplicates": 1,
|
|
176
|
+
"errors": 0
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
`results[*].status` is one of `"created"`, `"modified"`, `"duplicate"`,
|
|
181
|
+
`"flip_locked"` (integration mode-flip in progress — retry on the next
|
|
182
|
+
tick), `"validation_error"` (malformed item; `error` field names the
|
|
183
|
+
issue). The envelope's `posted` / `duplicates` / `errors` counters are
|
|
184
|
+
pre-aggregated; the per-item array is for correlating a failure back
|
|
185
|
+
to a specific input.
|
|
186
|
+
|
|
187
|
+
Hard limits:
|
|
188
|
+
|
|
189
|
+
- Max 200 items per call. Larger batches return 400 `batch_too_large` —
|
|
190
|
+
split into chunks.
|
|
191
|
+
- 1 MiB body cap (shared with the single-item route).
|
|
192
|
+
- Envelope JSON must have an `observations` array; missing or
|
|
193
|
+
non-array returns 400 `validation_error` with a hint.
|
|
194
|
+
|
|
136
195
|
### POST /api/observations/consume
|
|
137
196
|
|
|
138
197
|
Marks one or more observations consumed. **Bulk-only** — there is no
|
|
@@ -154,10 +213,25 @@ curl -s -X POST http://localhost:8321/api/observations/consume \
|
|
|
154
213
|
| Field | Type | Required | Notes |
|
|
155
214
|
|---|---|---|---|
|
|
156
215
|
| `ids` | `number[]` | yes | Integers, not strings. `["14"]` is rejected. |
|
|
157
|
-
| `correlationId` | `string` | yes |
|
|
216
|
+
| `correlationId` | `string` | yes | camelCase, verbatim from the `<event_correlation_id>` context tag. Non-string, missing, snake_case `correlation_id`, or the literal placeholder `<...>` → 400. |
|
|
158
217
|
|
|
159
|
-
Response: `{ "consumed": <count
|
|
160
|
-
`{"error":"validation_error"}`.
|
|
218
|
+
Response: `{ "consumed": <count>, "notFound": [<id>...] }`. Validation
|
|
219
|
+
failures return 400 with `{ "error": "validation_error", "issues": [...], "expectedShape": "...", "example": "..." }`. **Read the
|
|
220
|
+
`issues` array — each entry names the offending field and a one-line
|
|
221
|
+
fix. Do NOT retry with a different shape unless the issue list tells
|
|
222
|
+
you to.**
|
|
223
|
+
|
|
224
|
+
#### Common mistakes — do not retry these, they will keep failing
|
|
225
|
+
|
|
226
|
+
| Wrong call | Why it fails | Correct shape |
|
|
227
|
+
|---|---|---|
|
|
228
|
+
| `POST /api/observations -d 'limit=30'` | Body is a query string. POST records, GET fetches. | `GET /api/observations?limit=30&pending=true` |
|
|
229
|
+
| `POST /api/observations/14/consume` | Per-id path returns 405 `use_bulk_endpoint`. | `POST /api/observations/consume -d '{"ids":[14],"correlationId":"..."}'` |
|
|
230
|
+
| `GET /api/observations/consume` | Consume is POST-only; GET returns 405. | `POST /api/observations/consume -d '{"ids":[...],"correlationId":"..."}'` |
|
|
231
|
+
| `PATCH /api/observations` | No PATCH route — auth middleware returns 401. | `POST /api/observations/consume` (or `POST /api/observations` for new rows). |
|
|
232
|
+
| `-d '{"ids":[14],"correlation_id":"..."}'` | snake_case. Field must be camelCase. | `-d '{"ids":[14],"correlationId":"..."}'` |
|
|
233
|
+
| `-d '{"ids":["14"],"correlationId":"..."}'` | Stringified ids. Use integers. | `-d '{"ids":[14],"correlationId":"..."}'` |
|
|
234
|
+
| `-d '{"ids":[14],"correlationId":"<event_correlation_id>"}'` | Pasted the angle-bracket placeholder. | Paste the actual id, e.g. `"hourly-2026-04-23T15:00:00Z-7af3"`. |
|
|
161
235
|
|
|
162
236
|
### GET /api/observations/stats
|
|
163
237
|
|
|
@@ -210,17 +284,20 @@ involved. Resolve `<databaseId>` first by reading the un-gated
|
|
|
210
284
|
(`curl -s http://localhost:8321/api/notion/databases`) and then pass
|
|
211
285
|
the UUID to the connector's data-source / search tool:
|
|
212
286
|
|
|
213
|
-
| session backend | structured filter (data-source query)
|
|
214
|
-
|
|
215
|
-
| claude | n/a — connector has no filtered query
|
|
216
|
-
| codex |
|
|
217
|
-
| gemini | n/a — connector has no filtered query
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
287
|
+
| session backend | structured filter (data-source query) | listing fallback (no filter support) | workspace search |
|
|
288
|
+
|-----------------|---------------------------------------|--------------------------------------|------------------|
|
|
289
|
+
| claude | n/a — hosted connector has no filtered query | in-session Notion page-fetch capability | in-session Notion search capability |
|
|
290
|
+
| codex | in-session Notion data-source-query capability | in-session Notion fetch capability | in-session Notion search capability |
|
|
291
|
+
| gemini | n/a — hosted connector has no filtered query | in-session Notion page-fetch capability | in-session Notion search capability |
|
|
292
|
+
|
|
293
|
+
The exact tool names depend on which Notion connector your harness has
|
|
294
|
+
loaded — pick them from your tool menu at session start by capability.
|
|
295
|
+
For Claude / Gemini sessions: call the listing capability against the
|
|
296
|
+
data source and post-filter in this skill (the structured-filter
|
|
297
|
+
capability is typically Codex-only). For Codex sessions: pass the
|
|
298
|
+
SQLite-style `WHERE` clause directly to the data-source-query
|
|
299
|
+
capability. See the `notion` skill body for full property-naming and
|
|
300
|
+
write-tier conventions.
|
|
224
301
|
<!-- /mode:delegated-same:notion -->
|
|
225
302
|
<!-- mode:delegated-cross:notion -->
|
|
226
303
|
The `/api/notion/query|search|pages` routes return 410 in delegated
|
|
@@ -249,6 +326,19 @@ Do NOT call `/api/notion/{query,search,pages}` directly (returns
|
|
|
249
326
|
tools — that connector reads a different workspace than the user's
|
|
250
327
|
delegated one.
|
|
251
328
|
<!-- /mode:delegated-cross:notion -->
|
|
329
|
+
<!-- mode:native:notion -->
|
|
330
|
+
Notion is in native mode — the `/api/notion/{query,search,pages}`
|
|
331
|
+
routes return 410 `{"error":"integration_native"}` and the daemon
|
|
332
|
+
does not host an `/exec` proxy. Use your session backend's native
|
|
333
|
+
Notion MCP tools directly; the materialized `notion` skill body
|
|
334
|
+
(`SKILL.native.<session-backend>.md`) lists the per-backend tool
|
|
335
|
+
names and the canonical search / fetch call shapes. Resolve
|
|
336
|
+
`<databaseId>` first via the un-gated config dump
|
|
337
|
+
(`curl -s http://localhost:8321/api/notion/databases`) and pass the
|
|
338
|
+
UUID to the connector's data-source / search tool. Do NOT call
|
|
339
|
+
`/api/notion/*` (410) or `/api/integrations/notion/exec` (also 410
|
|
340
|
+
in native mode).
|
|
341
|
+
<!-- /mode:native:notion -->
|
|
252
342
|
<!-- mode:disabled:notion -->
|
|
253
343
|
Notion is disabled — there is no live source. Treat the observation
|
|
254
344
|
as preview-only and proceed without a Notion fetch.
|
|
@@ -233,6 +233,25 @@ recipe — they always emit the full section schema.
|
|
|
233
233
|
Roadmap writes serialize via an optional exclusive lock so a
|
|
234
234
|
mid-session refresh is not interleaved with a DM handler PATCH.
|
|
235
235
|
|
|
236
|
+
**Lock endpoint paths — get the order right:**
|
|
237
|
+
|
|
238
|
+
| Operation | Method | Path |
|
|
239
|
+
|---|---|---|
|
|
240
|
+
| Acquire | `POST` | `/api/context/lock/roadmap` |
|
|
241
|
+
| Release | `DELETE` | `/api/context/lock/roadmap` |
|
|
242
|
+
|
|
243
|
+
**Common mistakes (NOT registered):**
|
|
244
|
+
|
|
245
|
+
- `POST /api/context/roadmap/lock` — order reversed
|
|
246
|
+
- `POST /api/context/roadmap/write-lock` — order reversed and wrong noun
|
|
247
|
+
- `POST /api/context/lock/roadmap-write` — wrong noun
|
|
248
|
+
|
|
249
|
+
Any of these return `404 {"error":"unknown_route", ...}` with a hint
|
|
250
|
+
pointing at the correct path — re-read the table above and resend. The
|
|
251
|
+
correct lock endpoints are Autonomous-tier, so no bearer token is
|
|
252
|
+
required; if you see `401 {"error":"unauthorized"}` from a path you
|
|
253
|
+
believe is correct, the path is still wrong.
|
|
254
|
+
|
|
236
255
|
- If `<roadmap_write_lock_id>` is in your context, include
|
|
237
256
|
`X-Lock-Id: <roadmap_write_lock_id>` on every PUT / PATCH to
|
|
238
257
|
`/api/context/roadmap`.
|
|
@@ -35,11 +35,52 @@ user but compound into duplicate DMs/notifications at fire time.
|
|
|
35
35
|
confirm no recurring rule already covers this cadence (e.g. a daily
|
|
36
36
|
09:00 inbox triage). If covered, skip — the recurring instance will
|
|
37
37
|
regenerate on its own.
|
|
38
|
+
4. **`confirm_dedup_key` check (mandatory for `confirm:` sub-flow rows
|
|
39
|
+
only).** When scheduling a `dm_session` row with
|
|
40
|
+
`taskContext.sub_flow="confirm"`, additionally filter
|
|
41
|
+
`GET /api/schedule?status=pending,running` by
|
|
42
|
+
`taskContext.confirm_dedup_key`. Skip if any match exists —
|
|
43
|
+
regardless of `scheduledFor` distance or description match. The
|
|
44
|
+
confirm sub-flow's chained-fire model (see `scheduled.dm.md`
|
|
45
|
+
§"Confirmation follow-up" Step 3) and a hot-thread defer (Step 1
|
|
46
|
+
check 1) both inherit the same dedup_key, so a successor or defer
|
|
47
|
+
row legitimately occupies the queue with the same key — a second
|
|
48
|
+
gate firing for the same topic MUST yield to it rather than
|
|
49
|
+
double-asking.
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
curl -s "http://localhost:8321/api/schedule?status=pending,running" \
|
|
53
|
+
| jq --arg k "<gate>:<stable-topic>" \
|
|
54
|
+
'[.items[] | select(.taskContext.confirm_dedup_key == $k)] | length'
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
If the count is `≥ 1`, log to `## Agent Log` and proceed without
|
|
58
|
+
scheduling:
|
|
59
|
+
```
|
|
60
|
+
- HH:MM [confirm] skipped <dedup_key>: row already pending
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**`confirm_dedup_key` shape contract.** The key is
|
|
64
|
+
`<gate>:<stable-topic>` — for example
|
|
65
|
+
`create_project:la-pm-masters`,
|
|
66
|
+
`roadmap_ambiguous:tokyo-trip-date`,
|
|
67
|
+
`managed_task_dedup:<existing-task-id>`. The gate scope ensures
|
|
68
|
+
two unrelated gates can't collide on the same topic name; the
|
|
69
|
+
topic component MUST be deterministic from the topic itself
|
|
70
|
+
(no timestamps, no message IDs, no random nonces) so re-fires of
|
|
71
|
+
the same gate produce the same key and this pre-flight catches
|
|
72
|
+
them.
|
|
73
|
+
|
|
74
|
+
This rule layers on top of bullets 1-3, which catch the common
|
|
75
|
+
recurring / Agent-Plan duplicates. Bullet 4 catches the case
|
|
76
|
+
where two confirms target the same topic at different scheduled
|
|
77
|
+
times (e.g. one queued for the morning briefing, another the
|
|
78
|
+
gate would queue for `+4h`).
|
|
38
79
|
|
|
39
80
|
Log the skip to `## Agent Log`:
|
|
40
81
|
`- HH:MM [schedule] skipped <subject>: duplicate of <planId|row>`.
|
|
41
82
|
|
|
42
|
-
Only after all
|
|
83
|
+
Only after all four clear do you create the new schedule.
|
|
43
84
|
|
|
44
85
|
## When the user wants a durable rule, not a wake-up
|
|
45
86
|
|
|
@@ -151,7 +192,7 @@ curl -s -X POST http://localhost:8321/api/schedule \
|
|
|
151
192
|
| `model` | No | `sonnet` (default) or `opus` |
|
|
152
193
|
| `taskContext` | No | Structured metadata object |
|
|
153
194
|
|
|
154
|
-
Rejects times in the past (> 1 min ago), same as `/api/schedule/dm`.
|
|
195
|
+
Response: `{ "status":"scheduled", "scheduleId":"123", "scheduledFor":"YYYY-MM-DD HH:MM:SS" }`. `scheduledFor` is the normalized UTC SQLite timestamp the daemon actually stored — log this verbatim instead of re-formatting the input `time`. Rejects times in the past (> 1 min ago), same as `/api/schedule/dm`.
|
|
155
196
|
|
|
156
197
|
### PATCH /api/schedule/:id — Edit a pending item
|
|
157
198
|
```bash
|
|
@@ -170,7 +211,7 @@ Param `status` (default `pending,running`): comma-separated `pending`, `running`
|
|
|
170
211
|
Param `roadmapEligible=true`: return only rows that may become
|
|
171
212
|
roadmap `Scheduled:` entries (`transient` / `low` excluded, `normal`
|
|
172
213
|
only beyond 7 days, `strategic` included).
|
|
173
|
-
Response: `{ "items":[{ "id","scheduledFor","taskType","description","prompt","status","createdAt" }] }` — `prompt` is `null` when no override is set.
|
|
214
|
+
Response: `{ "items":[{ "id","scheduledFor","taskType","description","prompt","status","model","taskContext","createdAt" }] }` — `prompt` is `null` when no override is set. `taskContext` is the parsed JSON object (or `null` when none was stored); use it for sub-flow-aware filtering, e.g. `jq '.items[] | select(.taskContext.confirm_dedup_key == "create_project:la-pm-masters")'`.
|
|
174
215
|
|
|
175
216
|
### DELETE /api/schedule/:id — Cancel a pending item
|
|
176
217
|
```bash
|
|
@@ -9,11 +9,31 @@ allowed-tools:
|
|
|
9
9
|
# today.md Guide
|
|
10
10
|
|
|
11
11
|
Output language: follow `<output_language_policy>`. today.md is
|
|
12
|
-
Policy B — the
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
Policy B — the **skeleton lines listed below stay English verbatim**;
|
|
13
|
+
bullets, narrative, and free-text fields under each H2 are written in
|
|
14
|
+
`<settings primary_language>`. Preserve user-customized headers verbatim.
|
|
15
|
+
|
|
16
|
+
**Skeleton (do NOT translate — exact-regex-validated on PUT):**
|
|
17
|
+
|
|
18
|
+
1. **Line 1** — `# YYYY-MM-DD (day-of-week)` H1 date line. The weekday
|
|
19
|
+
inside `(...)` is free-form and may be localized; the rest is fixed.
|
|
20
|
+
2. **Line 2** — `> Day type: …` blockquote (full pattern below). Field
|
|
21
|
+
labels (`Day type`, `Work focus`, `Study focus`, `Personal focus`),
|
|
22
|
+
values (`Weekday`/`Weekend`, `on`/`off`), pipe separators (` | `),
|
|
23
|
+
and the leading `> ` are **all English ASCII, fixed casing, fixed
|
|
24
|
+
spacing**. This is parsed by every downstream event handler.
|
|
25
|
+
3. **The six H2 headers** — `## User Schedule`, `## User Tasks`,
|
|
26
|
+
`## Agent Plan`, `## Agent Notes`, `## Agent Log`, `## Handoff` —
|
|
27
|
+
in this order.
|
|
28
|
+
|
|
29
|
+
A `PUT /api/context/today` whose line 1 or line 2 fails the exact regex
|
|
30
|
+
is rejected with 400 and the daemon does NOT write the file. Translating
|
|
31
|
+
any keyword on line 2 (the field labels, the `Weekday`/`Weekend` value,
|
|
32
|
+
or `on`/`off`) into the user's primary language is the most common
|
|
33
|
+
failure mode — keep it English even when the rest of today.md is being
|
|
34
|
+
written in another language. The `<output_language_policy>` skeleton
|
|
35
|
+
precedence rule already covers this; this paragraph just makes the
|
|
36
|
+
consequence explicit.
|
|
17
37
|
|
|
18
38
|
today.md has a **day-type header line** (second line) and **six required sections**.
|
|
19
39
|
|
|
@@ -43,6 +43,15 @@ enabled.
|
|
|
43
43
|
`external-services` skill — cross-backend variant for worked
|
|
44
44
|
examples).
|
|
45
45
|
<!-- /mode:delegated-cross:google_calendar -->
|
|
46
|
+
<!-- mode:native:google_calendar -->
|
|
47
|
+
Native mode → use this session backend's native Calendar
|
|
48
|
+
list-events MCP tool (same call shape as `delegated-same`). The
|
|
49
|
+
materialized `external-services` skill body
|
|
50
|
+
(`SKILL.native.<session-backend>.md`) lists the per-backend tool
|
|
51
|
+
names. The daemon does not proxy in native mode;
|
|
52
|
+
`/api/calendar/events` returns 410 and
|
|
53
|
+
`/api/integrations/google_calendar/exec` returns 410 too.
|
|
54
|
+
<!-- /mode:native:google_calendar -->
|
|
46
55
|
<!-- mode:disabled:google_calendar -->
|
|
47
56
|
Disabled → skip this skill; there is no calendar to source events from.
|
|
48
57
|
<!-- /mode:disabled:google_calendar -->
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wiki-ask
|
|
3
|
+
description: Load for wiki.ask. Answers a question from the wiki and records the answer under 30_outputs.
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Bash(curl *)
|
|
6
|
+
- Bash(jq *)
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Wiki Ask
|
|
10
|
+
|
|
11
|
+
You run under process key `wiki.ask`.
|
|
12
|
+
|
|
13
|
+
Read `<wiki_command>` for the user's `question`. Search and read relevant `20_wiki/` notes first; read `10_raw/` only when the wiki notes need source verification.
|
|
14
|
+
|
|
15
|
+
Write the answer to:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
POST /api/wiki/{{workspace_name}}/files/30_outputs/<YYYY-MM-DD>-<slug>.md
|
|
19
|
+
x-process-key: wiki.ask
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The output must include the question, short answer, evidence, source links, and follow-up gaps. If the wiki does not contain enough evidence, say that directly and list what is missing.
|
|
23
|
+
|
|
24
|
+
### Completion message (mandatory)
|
|
25
|
+
|
|
26
|
+
End the turn with a short final assistant message that the daemon forwards back to the channel the bang command came from. This is what the user actually reads on their phone — make it the answer in plain prose:
|
|
27
|
+
|
|
28
|
+
- Lead with the answer in one short paragraph (3–5 lines max).
|
|
29
|
+
- Cite the wiki pages you drew from inline (`see [[<slug>]]`).
|
|
30
|
+
- End with `Full answer: 30_outputs/<YYYY-MM-DD>-<slug>.md` so the user can dig deeper.
|
|
31
|
+
- On insufficient evidence: `Wiki has no entry for <topic>. Missing: <one-line gap>.` and skip the file pointer.
|
|
32
|
+
|