@aitne-sh/aitne 0.1.4 → 0.1.6
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 +16 -0
- package/agent-assets/agent-profiles/_safety.md +29 -0
- 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 +123 -15
- package/agent-assets/skills/roadmap/SKILL.md +31 -4
- package/agent-assets/skills/schedule/SKILL.md +44 -3
- package/agent-assets/skills/today/SKILL.md +50 -11
- 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/routine.roadmap_refresh.md +7 -3
- package/agent-assets/task-flows/scheduled.dm.md +477 -0
- package/agent-assets/task-flows/setup.initial.md +50 -23
- 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 +10 -6
- package/scripts/check-redaction-coverage.mjs +0 -109
- package/scripts/commands.md +0 -0
- package/scripts/message-discipline-digest.mjs +0 -535
- package/scripts/poc/google-connector-inheritance/REPORT.md +0 -197
- package/scripts/poc/google-connector-inheritance/claude-sdk-probe.mjs +0 -79
- package/scripts/regen-skill-fixtures.mjs +0 -39
- package/scripts/remint-roadmap-ids.mjs +0 -257
- package/scripts/smoke-obsidian-api.mjs +0 -166
|
@@ -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
|
|
|
@@ -26,8 +26,10 @@ the update.
|
|
|
26
26
|
- Update `roadmap.md` or `projects/*.md` only for material project-state changes
|
|
27
27
|
- Schedule a wake-up if the observation implies a future reminder
|
|
28
28
|
5. Apply the smallest meaningful set of context updates.
|
|
29
|
-
6. Mark processed observations consumed
|
|
30
|
-
`
|
|
29
|
+
6. Mark processed observations consumed via the bulk endpoint
|
|
30
|
+
(`POST /api/observations/consume`) — see "POST /api/observations/consume"
|
|
31
|
+
in the API Reference below for the exact body shape and the
|
|
32
|
+
`correlationId` rule. There is no per-id variant.
|
|
31
33
|
|
|
32
34
|
## Skip Criteria
|
|
33
35
|
|
|
@@ -131,15 +133,105 @@ creating a duplicate. Subkind suffixes after the colon are by
|
|
|
131
133
|
convention (`roadmap_candidate:calendar`, `roadmap_candidate:vault`,
|
|
132
134
|
etc.) and are picked up by the prefix match on the GET route.
|
|
133
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
|
+
|
|
134
195
|
### POST /api/observations/consume
|
|
135
196
|
|
|
197
|
+
Marks one or more observations consumed. **Bulk-only** — there is no
|
|
198
|
+
per-id endpoint (`POST /api/observations/<id>/consume` returns 404).
|
|
199
|
+
Always use this shape, even for a single id.
|
|
200
|
+
|
|
201
|
+
Copy the `correlationId` value verbatim from the
|
|
202
|
+
`<event_correlation_id>…</event_correlation_id>` tag in your turn
|
|
203
|
+
context — do not paste the angle-bracket placeholder.
|
|
204
|
+
|
|
136
205
|
```bash
|
|
206
|
+
# Example: <event_correlation_id>hourly-2026-04-23T15:00:00Z-7af3</event_correlation_id>
|
|
207
|
+
# arrived in context, and observations 14 and 17 were processed.
|
|
137
208
|
curl -s -X POST http://localhost:8321/api/observations/consume \
|
|
138
209
|
-H 'Content-Type: application/json' \
|
|
139
|
-
-d '{"ids":
|
|
210
|
+
-d '{"ids":[14,17],"correlationId":"hourly-2026-04-23T15:00:00Z-7af3"}'
|
|
140
211
|
```
|
|
141
212
|
|
|
142
|
-
|
|
213
|
+
| Field | Type | Required | Notes |
|
|
214
|
+
|---|---|---|---|
|
|
215
|
+
| `ids` | `number[]` | yes | Integers, not strings. `["14"]` is rejected. |
|
|
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. |
|
|
217
|
+
|
|
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"`. |
|
|
143
235
|
|
|
144
236
|
### GET /api/observations/stats
|
|
145
237
|
|
|
@@ -192,17 +284,20 @@ involved. Resolve `<databaseId>` first by reading the un-gated
|
|
|
192
284
|
(`curl -s http://localhost:8321/api/notion/databases`) and then pass
|
|
193
285
|
the UUID to the connector's data-source / search tool:
|
|
194
286
|
|
|
195
|
-
| session backend | structured filter (data-source query)
|
|
196
|
-
|
|
197
|
-
| claude | n/a — connector has no filtered query
|
|
198
|
-
| codex |
|
|
199
|
-
| gemini | n/a — connector has no filtered query
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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.
|
|
206
301
|
<!-- /mode:delegated-same:notion -->
|
|
207
302
|
<!-- mode:delegated-cross:notion -->
|
|
208
303
|
The `/api/notion/query|search|pages` routes return 410 in delegated
|
|
@@ -231,6 +326,19 @@ Do NOT call `/api/notion/{query,search,pages}` directly (returns
|
|
|
231
326
|
tools — that connector reads a different workspace than the user's
|
|
232
327
|
delegated one.
|
|
233
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 -->
|
|
234
342
|
<!-- mode:disabled:notion -->
|
|
235
343
|
Notion is disabled — there is no live source. Treat the observation
|
|
236
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`.
|
|
@@ -246,6 +265,12 @@ mid-session refresh is not interleaved with a DM handler PATCH.
|
|
|
246
265
|
|
|
247
266
|
## roadmap.md API
|
|
248
267
|
|
|
268
|
+
Body submission follows `_safety.md` "Daemon-API body submission":
|
|
269
|
+
small POST / PATCH bodies use inline `-d '{...}'`; the full-file PUT
|
|
270
|
+
runs multi-KB and uses the stdin heredoc `-d @- <<'JSON'` shape.
|
|
271
|
+
Include `X-Lock-Id: <roadmap_write_lock_id>` on every PUT / PATCH
|
|
272
|
+
when that tag is in your context.
|
|
273
|
+
|
|
249
274
|
```bash
|
|
250
275
|
# Read
|
|
251
276
|
curl -s http://localhost:8321/api/context/roadmap
|
|
@@ -254,19 +279,21 @@ curl -s http://localhost:8321/api/context/roadmap
|
|
|
254
279
|
curl -s -X POST http://localhost:8321/api/context/roadmap/id \
|
|
255
280
|
-H 'Content-Type: application/json' \
|
|
256
281
|
-H 'X-Lock-Id: <roadmap_write_lock_id>' \
|
|
257
|
-
-d '{"creationDate":
|
|
282
|
+
-d '{"creationDate":"YYYY-MM-DD"}'
|
|
258
283
|
|
|
259
|
-
# Full replace (roadmap refresh —
|
|
284
|
+
# Full replace (roadmap refresh) — multi-KB body, use heredoc.
|
|
260
285
|
curl -s -X PUT http://localhost:8321/api/context/roadmap \
|
|
261
286
|
-H 'Content-Type: application/json' \
|
|
262
287
|
-H 'X-Lock-Id: <roadmap_write_lock_id>' \
|
|
263
|
-
-d
|
|
288
|
+
-d @- <<'JSON'
|
|
289
|
+
{"content":"# Roadmap\n> Last synced: 2026-04-23\n\n## Annual Goals\n- ...\n\n## Quarterly Focus\n- ...\n\n## Long-term Plans\n- [2026-Q3] ... <!-- id: rm-20260419-b8e7d4 -->\n\n## Agent Action Plan\n\n## Recurring\n- Every Friday: weekly review\n"}
|
|
290
|
+
JSON
|
|
264
291
|
|
|
265
292
|
# Section PATCH
|
|
266
293
|
curl -s -X PATCH http://localhost:8321/api/context/roadmap \
|
|
267
294
|
-H 'Content-Type: application/json' \
|
|
268
295
|
-H 'X-Lock-Id: <roadmap_write_lock_id>' \
|
|
269
|
-
-d '{"section":
|
|
296
|
+
-d '{"section":"long_term_plans","mode":"append","content":"- [2026-Q3] ...\n"}'
|
|
270
297
|
```
|
|
271
298
|
|
|
272
299
|
Snapshotting, mtime updates, and path validation are handled by the
|
|
@@ -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
|
|
|
@@ -186,15 +206,34 @@ PUT today.md must contain the H1 date line, day-type header quote, and all six s
|
|
|
186
206
|
|
|
187
207
|
## today.md API (subset of context API)
|
|
188
208
|
|
|
209
|
+
Body submission follows the rule in `_safety.md` "Daemon-API body
|
|
210
|
+
submission": small section PATCHes use inline `-d '{...}'`; full-file
|
|
211
|
+
PUT uses the stdin heredoc `-d @- <<'JSON'` shape because the body
|
|
212
|
+
runs multi-KB. Add `X-Lock-Id: <today_write_lock_id>` on every
|
|
213
|
+
PUT / PATCH when that tag is in your context.
|
|
214
|
+
|
|
189
215
|
```bash
|
|
190
|
-
|
|
191
|
-
curl -s
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
216
|
+
# Read
|
|
217
|
+
curl -s http://localhost:8321/api/context/today
|
|
218
|
+
|
|
219
|
+
# Full replace — Morning Routine only. Multi-KB body → heredoc.
|
|
220
|
+
curl -s -X PUT http://localhost:8321/api/context/today \
|
|
221
|
+
-H 'Content-Type: application/json' \
|
|
222
|
+
-H 'X-Lock-Id: <today_write_lock_id>' \
|
|
223
|
+
-d @- <<'JSON'
|
|
224
|
+
{"content":"# 2026-04-02 (Thursday)\n> Day type: Weekday | Work focus: on | Study focus: on | Personal focus: on\n\n## User Schedule\n- 14:00–15:00 Design review [work]\n\n## User Tasks\n- [ ] 11:00 Finalize Q2 draft [work]\n\n## Agent Plan\n- [ ] 08:55 DM reminder: standup [work] →DM\n\n## Agent Notes\n\n## Agent Log\n- 04:00 Morning Routine completed (day-type: Weekday)\n\n## Handoff\n- (none)\n"}
|
|
225
|
+
JSON
|
|
226
|
+
|
|
227
|
+
# Section operation — small body, inline `-d` is fine.
|
|
228
|
+
curl -s -X PATCH http://localhost:8321/api/context/today \
|
|
229
|
+
-H 'Content-Type: application/json' \
|
|
230
|
+
-H 'X-Lock-Id: <today_write_lock_id>' \
|
|
231
|
+
-d '{"section":"agent_log","mode":"append","content":"- 09:35 ..."}'
|
|
195
232
|
```
|
|
196
233
|
|
|
197
|
-
|
|
234
|
+
The H1 date and the `> Day type:` quote line are validated by exact
|
|
235
|
+
regex on PUT — keep both English-shaped exactly as the template. See
|
|
236
|
+
context skill for the full endpoint reference.
|
|
198
237
|
|
|
199
238
|
## Knowledge map — section shape (auto-curated)
|
|
200
239
|
|
|
@@ -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 -->
|