@open-everywhere/provider-notion 0.1.0

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 (186) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +21 -0
  3. package/README.md +48 -0
  4. package/agent/channels/notion-acting-identity.ts +88 -0
  5. package/agent/channels/notion-ancestry-trust.ts +458 -0
  6. package/agent/channels/notion-api.ts +1290 -0
  7. package/agent/channels/notion-bot-user.ts +250 -0
  8. package/agent/channels/notion-catch-up.ts +339 -0
  9. package/agent/channels/notion-credentials.ts +417 -0
  10. package/agent/channels/notion-engagement.ts +372 -0
  11. package/agent/channels/notion-event-normalizer.ts +587 -0
  12. package/agent/channels/notion-identity.ts +271 -0
  13. package/agent/channels/notion-ingress-drain.ts +289 -0
  14. package/agent/channels/notion-ingress.ts +182 -0
  15. package/agent/channels/notion-message-ops.ts +140 -0
  16. package/agent/channels/notion-origin-codec.ts +38 -0
  17. package/agent/channels/notion-post-arm.ts +189 -0
  18. package/agent/channels/notion-question-return.ts +223 -0
  19. package/agent/channels/notion-read.ts +283 -0
  20. package/agent/channels/notion-scope.ts +560 -0
  21. package/agent/channels/notion-stop.ts +169 -0
  22. package/agent/channels/notion-supervisor.ts +856 -0
  23. package/agent/channels/notion-webhook-timing.ts +131 -0
  24. package/agent/channels/notion-webhook-verifier.ts +55 -0
  25. package/agent/channels/notion-webhook.ts +963 -0
  26. package/agent/channels/notion-work-search.ts +74 -0
  27. package/agent/channels/notion-work.ts +144 -0
  28. package/agent/channels/notion.ts +1242 -0
  29. package/agent/contributions.ts +39 -0
  30. package/agent/docs-generated.ts +15 -0
  31. package/agent/memory/blocks.ts +295 -0
  32. package/agent/memory/memory.ts +622 -0
  33. package/agent/provider-events.ts +198 -0
  34. package/agent/register.ts +144 -0
  35. package/agent/schedules/notion-ingress.ts +20 -0
  36. package/agent/surface-parity.ts +105 -0
  37. package/agent/tools/notion_search.ts +110 -0
  38. package/agent/tools/read_notion_comments.ts +250 -0
  39. package/agent/tools/read_notion_page.ts +351 -0
  40. package/dist/agent/channels/notion-acting-identity.d.ts +23 -0
  41. package/dist/agent/channels/notion-acting-identity.d.ts.map +1 -0
  42. package/dist/agent/channels/notion-acting-identity.js +85 -0
  43. package/dist/agent/channels/notion-acting-identity.js.map +1 -0
  44. package/dist/agent/channels/notion-ancestry-trust.d.ts +208 -0
  45. package/dist/agent/channels/notion-ancestry-trust.d.ts.map +1 -0
  46. package/dist/agent/channels/notion-ancestry-trust.js +331 -0
  47. package/dist/agent/channels/notion-ancestry-trust.js.map +1 -0
  48. package/dist/agent/channels/notion-api.d.ts +655 -0
  49. package/dist/agent/channels/notion-api.d.ts.map +1 -0
  50. package/dist/agent/channels/notion-api.js +938 -0
  51. package/dist/agent/channels/notion-api.js.map +1 -0
  52. package/dist/agent/channels/notion-bot-user.d.ts +107 -0
  53. package/dist/agent/channels/notion-bot-user.d.ts.map +1 -0
  54. package/dist/agent/channels/notion-bot-user.js +192 -0
  55. package/dist/agent/channels/notion-bot-user.js.map +1 -0
  56. package/dist/agent/channels/notion-catch-up.d.ts +64 -0
  57. package/dist/agent/channels/notion-catch-up.d.ts.map +1 -0
  58. package/dist/agent/channels/notion-catch-up.js +289 -0
  59. package/dist/agent/channels/notion-catch-up.js.map +1 -0
  60. package/dist/agent/channels/notion-credentials.d.ts +210 -0
  61. package/dist/agent/channels/notion-credentials.d.ts.map +1 -0
  62. package/dist/agent/channels/notion-credentials.js +360 -0
  63. package/dist/agent/channels/notion-credentials.js.map +1 -0
  64. package/dist/agent/channels/notion-engagement.d.ts +219 -0
  65. package/dist/agent/channels/notion-engagement.d.ts.map +1 -0
  66. package/dist/agent/channels/notion-engagement.js +283 -0
  67. package/dist/agent/channels/notion-engagement.js.map +1 -0
  68. package/dist/agent/channels/notion-event-normalizer.d.ts +194 -0
  69. package/dist/agent/channels/notion-event-normalizer.d.ts.map +1 -0
  70. package/dist/agent/channels/notion-event-normalizer.js +542 -0
  71. package/dist/agent/channels/notion-event-normalizer.js.map +1 -0
  72. package/dist/agent/channels/notion-identity.d.ts +119 -0
  73. package/dist/agent/channels/notion-identity.d.ts.map +1 -0
  74. package/dist/agent/channels/notion-identity.js +205 -0
  75. package/dist/agent/channels/notion-identity.js.map +1 -0
  76. package/dist/agent/channels/notion-ingress-drain.d.ts +66 -0
  77. package/dist/agent/channels/notion-ingress-drain.d.ts.map +1 -0
  78. package/dist/agent/channels/notion-ingress-drain.js +185 -0
  79. package/dist/agent/channels/notion-ingress-drain.js.map +1 -0
  80. package/dist/agent/channels/notion-ingress.d.ts +64 -0
  81. package/dist/agent/channels/notion-ingress.d.ts.map +1 -0
  82. package/dist/agent/channels/notion-ingress.js +130 -0
  83. package/dist/agent/channels/notion-ingress.js.map +1 -0
  84. package/dist/agent/channels/notion-message-ops.d.ts +3 -0
  85. package/dist/agent/channels/notion-message-ops.d.ts.map +1 -0
  86. package/dist/agent/channels/notion-message-ops.js +126 -0
  87. package/dist/agent/channels/notion-message-ops.js.map +1 -0
  88. package/dist/agent/channels/notion-origin-codec.d.ts +7 -0
  89. package/dist/agent/channels/notion-origin-codec.d.ts.map +1 -0
  90. package/dist/agent/channels/notion-origin-codec.js +32 -0
  91. package/dist/agent/channels/notion-origin-codec.js.map +1 -0
  92. package/dist/agent/channels/notion-post-arm.d.ts +3 -0
  93. package/dist/agent/channels/notion-post-arm.d.ts.map +1 -0
  94. package/dist/agent/channels/notion-post-arm.js +185 -0
  95. package/dist/agent/channels/notion-post-arm.js.map +1 -0
  96. package/dist/agent/channels/notion-question-return.d.ts +77 -0
  97. package/dist/agent/channels/notion-question-return.d.ts.map +1 -0
  98. package/dist/agent/channels/notion-question-return.js +183 -0
  99. package/dist/agent/channels/notion-question-return.js.map +1 -0
  100. package/dist/agent/channels/notion-read.d.ts +62 -0
  101. package/dist/agent/channels/notion-read.d.ts.map +1 -0
  102. package/dist/agent/channels/notion-read.js +257 -0
  103. package/dist/agent/channels/notion-read.js.map +1 -0
  104. package/dist/agent/channels/notion-scope.d.ts +188 -0
  105. package/dist/agent/channels/notion-scope.d.ts.map +1 -0
  106. package/dist/agent/channels/notion-scope.js +433 -0
  107. package/dist/agent/channels/notion-scope.js.map +1 -0
  108. package/dist/agent/channels/notion-stop.d.ts +48 -0
  109. package/dist/agent/channels/notion-stop.d.ts.map +1 -0
  110. package/dist/agent/channels/notion-stop.js +141 -0
  111. package/dist/agent/channels/notion-stop.js.map +1 -0
  112. package/dist/agent/channels/notion-supervisor.d.ts +462 -0
  113. package/dist/agent/channels/notion-supervisor.d.ts.map +1 -0
  114. package/dist/agent/channels/notion-supervisor.js +482 -0
  115. package/dist/agent/channels/notion-supervisor.js.map +1 -0
  116. package/dist/agent/channels/notion-webhook-timing.d.ts +35 -0
  117. package/dist/agent/channels/notion-webhook-timing.d.ts.map +1 -0
  118. package/dist/agent/channels/notion-webhook-timing.js +99 -0
  119. package/dist/agent/channels/notion-webhook-timing.js.map +1 -0
  120. package/dist/agent/channels/notion-webhook-verifier.d.ts +5 -0
  121. package/dist/agent/channels/notion-webhook-verifier.d.ts.map +1 -0
  122. package/dist/agent/channels/notion-webhook-verifier.js +53 -0
  123. package/dist/agent/channels/notion-webhook-verifier.js.map +1 -0
  124. package/dist/agent/channels/notion-webhook.d.ts +242 -0
  125. package/dist/agent/channels/notion-webhook.d.ts.map +1 -0
  126. package/dist/agent/channels/notion-webhook.js +675 -0
  127. package/dist/agent/channels/notion-webhook.js.map +1 -0
  128. package/dist/agent/channels/notion-work-search.d.ts +9 -0
  129. package/dist/agent/channels/notion-work-search.d.ts.map +1 -0
  130. package/dist/agent/channels/notion-work-search.js +69 -0
  131. package/dist/agent/channels/notion-work-search.js.map +1 -0
  132. package/dist/agent/channels/notion-work.d.ts +68 -0
  133. package/dist/agent/channels/notion-work.d.ts.map +1 -0
  134. package/dist/agent/channels/notion-work.js +126 -0
  135. package/dist/agent/channels/notion-work.js.map +1 -0
  136. package/dist/agent/channels/notion.d.ts +95 -0
  137. package/dist/agent/channels/notion.d.ts.map +1 -0
  138. package/dist/agent/channels/notion.js +1081 -0
  139. package/dist/agent/channels/notion.js.map +1 -0
  140. package/dist/agent/contributions.d.ts +32 -0
  141. package/dist/agent/contributions.d.ts.map +1 -0
  142. package/dist/agent/contributions.js +37 -0
  143. package/dist/agent/contributions.js.map +1 -0
  144. package/dist/agent/docs-generated.d.ts +3 -0
  145. package/dist/agent/docs-generated.d.ts.map +1 -0
  146. package/dist/agent/docs-generated.js +13 -0
  147. package/dist/agent/docs-generated.js.map +1 -0
  148. package/dist/agent/memory/blocks.d.ts +58 -0
  149. package/dist/agent/memory/blocks.d.ts.map +1 -0
  150. package/dist/agent/memory/blocks.js +264 -0
  151. package/dist/agent/memory/blocks.js.map +1 -0
  152. package/dist/agent/memory/memory.d.ts +157 -0
  153. package/dist/agent/memory/memory.d.ts.map +1 -0
  154. package/dist/agent/memory/memory.js +471 -0
  155. package/dist/agent/memory/memory.js.map +1 -0
  156. package/dist/agent/provider-events.d.ts +3 -0
  157. package/dist/agent/provider-events.d.ts.map +1 -0
  158. package/dist/agent/provider-events.js +196 -0
  159. package/dist/agent/provider-events.js.map +1 -0
  160. package/dist/agent/register.d.ts +5 -0
  161. package/dist/agent/register.d.ts.map +1 -0
  162. package/dist/agent/register.js +128 -0
  163. package/dist/agent/register.js.map +1 -0
  164. package/dist/agent/schedules/notion-ingress.d.ts +6 -0
  165. package/dist/agent/schedules/notion-ingress.d.ts.map +1 -0
  166. package/dist/agent/schedules/notion-ingress.js +16 -0
  167. package/dist/agent/schedules/notion-ingress.js.map +1 -0
  168. package/dist/agent/surface-parity.d.ts +3 -0
  169. package/dist/agent/surface-parity.d.ts.map +1 -0
  170. package/dist/agent/surface-parity.js +99 -0
  171. package/dist/agent/surface-parity.js.map +1 -0
  172. package/dist/agent/tools/notion_search.d.ts +56 -0
  173. package/dist/agent/tools/notion_search.d.ts.map +1 -0
  174. package/dist/agent/tools/notion_search.js +100 -0
  175. package/dist/agent/tools/notion_search.js.map +1 -0
  176. package/dist/agent/tools/read_notion_comments.d.ts +57 -0
  177. package/dist/agent/tools/read_notion_comments.d.ts.map +1 -0
  178. package/dist/agent/tools/read_notion_comments.js +236 -0
  179. package/dist/agent/tools/read_notion_comments.js.map +1 -0
  180. package/dist/agent/tools/read_notion_page.d.ts +53 -0
  181. package/dist/agent/tools/read_notion_page.d.ts.map +1 -0
  182. package/dist/agent/tools/read_notion_page.js +327 -0
  183. package/dist/agent/tools/read_notion_page.js.map +1 -0
  184. package/package.json +231 -0
  185. package/tsconfig.build.json +22 -0
  186. package/tsconfig.json +15 -0
@@ -0,0 +1,462 @@
1
+ import { type VendorEventTime, shouldRotate, type ExternalPolicy, type IngestedChatMessage, type NormalizedWake, type WakeEngagementTier, type WakeMessageInput, type WakeTrust, type UnifiedWindowWake, type SessionTailWakeRow, type SeatCatchUpRequest, type SeatCatchUpResult } from "@open-everywhere/core/agent/adapter-api.js";
2
+ import { type NotionComment } from "./notion-api.js";
3
+ import type { NotionOwnBotIds } from "./notion-bot-user.js";
4
+ import type { OpenEverywhereNotionAuth } from "./notion-identity.js";
5
+ import type { NotionDeliveryTrust } from "./notion-ancestry-trust.js";
6
+ import type { NotionSessionState } from "./notion-webhook.js";
7
+ import type { NotionVia } from "./notion-scope.js";
8
+ /** The reserved pseudo-thread sentinel for a supervisor generation (mirrors Slack's). */
9
+ export declare function notionSupervisorSentinel(generation: number): string;
10
+ /** The reserved continuation token for a page's supervisor session at a given generation:
11
+ * `notion:<pageId>:oe-sup:g<generation>`. Contains the `:oe-sup:g` infix hooks/spend.ts keys on,
12
+ * and is stable+explicit by construction (a custom-channel token eve never re-anchors — so,
13
+ * UNLIKE Slack, no non-empty state.threadTs re-anchor sentinel is needed; design §3.1). */
14
+ export declare function notionSupervisorToken(pageId: string, generation: number): string;
15
+ /** How a comment addresses the doc supervisor. `drop` = never wake (loop/bot guards); `direct` =
16
+ * a structured bot @mention, the guaranteed-engage conversation-driver treatment; `channel-watch`
17
+ * = judged by the standing supervisor (the ambient default — most comments). */
18
+ export type NotionAddressing = "direct" | "channel-watch" | "drop";
19
+ export interface NotionClassification {
20
+ readonly addressing: NotionAddressing;
21
+ readonly reason: string;
22
+ }
23
+ /**
24
+ * The Notion synthetic-mention (name-drop) convention. Notion CANNOT @mention an internal
25
+ * integration (notion-webhook.ts — the structured `mentionsUser` path is STRUCTURALLY DEAD for the
26
+ * agent), so a person addresses the doc agent by NAME instead: the deployment's configured names
27
+ * (OE_AGENT_NAME / OE_AGENT_SHORT_NAME, defaulting to the brand "open everywhere" / "oe" when unset)
28
+ * or the platform-resolved integration name (botName). This is the ONLY ambient-INDEPENDENT directed
29
+ * input Notion has, so — unlike Slack/GitHub/Linear, where a name-drop stays a judged input because a
30
+ * real @mention is available — here it is promoted to `direct`.
31
+ *
32
+ * The name set + word-boundary matcher live in core (identity/bot-name.ts matchesAgentName), which
33
+ * is ALSO what the addressed link-claim recogniser strips its leading token with (hooks/link-claim.ts)
34
+ * — one source of truth for "what does this agent answer to". Word-boundary matched (`\b`) so the
35
+ * short "oe" token never fires inside "Zoe"/"poet"/"does". A hit flows through the SAME seam a real
36
+ * @mention would: planNotionSingleWindow stamps `direct-mention`, which marks the wake as OWED a
37
+ * reply and tells the seat so. 🔴 THE STAMP DELIVERS NOTHING BY ITSELF (OPE-1982): the terminal-prose
38
+ * bridge it used to arm is deleted, so the reply lands via createCommentReply only when the seat
39
+ * calls `reply` — on its own turn, or on the ONE corrective re-drive a prose ending earns.
40
+ */
41
+ export declare function notionNameDrop(text: string, botName?: string): boolean;
42
+ /**
43
+ * Decide how the doc supervisor should treat one comment. The self-reply loop guard is HARDENED
44
+ * here (design §4.2), in cost order:
45
+ * 1. UNRESOLVED PRIMARY bot user id ⇒ DROP (fail closed) — self-identity is a precondition for the
46
+ * loop guard; without it the agent would loop on its own replies (each createCommentReply fires a
47
+ * fresh comment.created). This is the critical hardening over the old `if (botUserId && …)`.
48
+ * 2. SELF-authored ⇒ DROP — our own posted reply. The comparison is `created_by.id` against
49
+ * {@link NotionOwnBotIds.all}: EVERY configured integration's bot user id, not only the one that
50
+ * verified this delivery (OPE-1921). THAT IS THE WHOLE GUARD.
51
+ * 🔴 THE SET IS WHAT MAKES IT A GUARD ON A DEPLOYMENT RATHER THAN ON ONE INTEGRATION. Two
52
+ * integrations can both see one page, so a reply integration A posted is delivered on B's
53
+ * subscription too. Compared against B's id alone it matched nothing, read as a person and woke
54
+ * a turn; A's subscription then saw B's answer. Each reply is a NEW comment id, so the OPE-1906
55
+ * once-guard cannot bound that loop — only recognising our own words can.
56
+ * 3. UNIDENTIFIED AUTHOR (no `created_by.id`) ⇒ DROP (fail closed) — step 2 is the only check that
57
+ * can recognise our own words, so a comment whose author id we cannot read defeats it.
58
+ * 🔴 WITHOUT THIS STEP THE GUARD FALLS BACK ON `created_by.type`, A FIELD NOTION MAY OMIT
59
+ * (OPE-1857, notion-api.ts NotionComment): a comment's `created_by` is a PARTIAL user, so an
60
+ * id-less author reached step 4 with nothing to test, read as a person, and woke a turn. That
61
+ * is the same fail-closed posture step 1 takes for the other half of the comparison — an
62
+ * identity we cannot establish never wakes the agent, in EITHER direction.
63
+ * 4. BOT/integration-authored (created_by.type present and not "person") ⇒ DROP — the Slack
64
+ * authorIsBot analog, prevents bot-to-bot loops. A BACKSTOP for a foreign bot, never the
65
+ * self-guard: an ABSENT `type` says nothing, and steps 2-3 have already answered "is it ours".
66
+ * 5. INCOMPLETE OWN-ID SET ⇒ DROP (fail closed, OPE-1921) — one configured integration's bot user
67
+ * id did not resolve, so step 2 could not have recognised that integration's own reply. An
68
+ * author Notion states is a `person` is still admitted; an author it says NOTHING about is
69
+ * exactly the ambiguity the loop rides, so it drops.
70
+ * 🔴 IT COSTS AVAILABILITY AND THE TRADE IS DELIBERATE — see {@link NotionOwnBotIds.complete}.
71
+ * A deployment that cannot resolve one integration's id is deaf to every comment Notion does not
72
+ * mark `person`-authored until it can. 🔴 THAT IS NOT ONLY AMBIENT CHATTER: this step sits ABOVE
73
+ * steps 6 and 7, so an addressed structured @mention, an addressed name-drop and an
74
+ * `oe link <code>` identity claim all drop with it. Failing OPEN instead buys an unbounded reply
75
+ * loop between two of our own integrations, which no once-guard can stop.
76
+ * 6. STRUCTURED bot @mention ⇒ direct (guaranteed engage). Structurally unreachable for an
77
+ * internal integration today, but kept as the canonical addressed signal. Tested against the
78
+ * PRIMARY id alone: a structured mention names ONE bot user, and answering a mention of a
79
+ * sibling integration would put this integration in a conversation it was not addressed in.
80
+ * 7. NAME-DROP ⇒ direct ({@link notionNameDrop}). Notion's ONLY addressed path (no integration
81
+ * @mention), so a brand/name hit is promoted to the owed-a-reply treatment, not left as a
82
+ * judged input — this is the deliberate Notion-specific divergence from Slack/GitHub/Linear.
83
+ * 8. otherwise ⇒ channel-watch (judged by the standing doc supervisor).
84
+ *
85
+ * 🔴 THIS FUNCTION GUARDS ONE COMMENT, NOT ONE WAKE. It cannot tell a second delivery of the SAME
86
+ * comment from the first, because both carry identical bytes. The delivery once-guard is the other
87
+ * half of the loop defence and lives at the ingress
88
+ * (notion-engagement.ts `firstNotionDispatchOfComment`, called by notion-webhook.ts).
89
+ */
90
+ export declare function classifyNotionComment(comment: NotionComment, own: NotionOwnBotIds, botName?: string): NotionClassification;
91
+ /** The host-frozen reply-target facts one comment.created delivery resolves (the webhook core's
92
+ * dispatch fields) — everything {@link planNotionSingleWindow} needs to mint the wake origin. */
93
+ export interface NotionSingleWindowTarget {
94
+ /** The trigger comment's inline discussion thread — createCommentReply's discussion_id target.
95
+ * Empty ⇒ no freezable reply target ⇒ NO window (fail closed, never an unresolvable wake). */
96
+ readonly discussionId: string;
97
+ readonly pageId?: string;
98
+ readonly workspaceId?: string | null;
99
+ /** The Notion integration this delivery VERIFIED under (OPE-467) — frozen into the origin so the
100
+ * unified reply posts under the credential that fetched the trigger comment. */
101
+ readonly credentialId?: string;
102
+ /** The first latency anchor (OPE-1716), recorded on the ingress row. A Notion delivery carries no
103
+ * vendor clock this seam can read, so the caller passes its own FRONT-DOOR RECEIPT — which makes
104
+ * the vendor→ingress segment a lower bound, and the row's `vendorTsSource` says so. */
105
+ readonly vendorTs?: VendorEventTime;
106
+ }
107
+ /**
108
+ * The ONE single-window decision for a Notion delivery (channels/unified-window.ts
109
+ * singleWindowMentionPolicy is the SHARED seam — the exact function the GitHub reference's
110
+ * native-suppression AND classifier consult, github.ts:261 / github-supervisor.ts:139): given
111
+ * the grain's `singleWindow`, whether the classified comment is a structured @mention
112
+ * (classifyNotionComment returned `direct`), and the PRIVACY FLOOR `privacyOk`, return the
113
+ * {@link UnifiedWindowWake} the dispatch should carry, or undefined for the byte-identical
114
+ * native path.
115
+ *
116
+ * `privacyOk` is the OPERATOR-VOUCH fact the caller resolves (notion.ts): identity/trust.ts
117
+ * isVouchedInternal on the page's workspaceKey/surfaceKey (or the OE_TRUST=internal blanket
118
+ * switch), fail-closed when unregistered. This is the SAME per-surface allowlist that gates
119
+ * Notion's shared MEMORY (notion-identity.ts / bindNotion), so a page is admitted to the shared
120
+ * cross-surface WINDOW exactly when the operator has vouched it internal — never inferred from a
121
+ * misleading API field (a Notion page's `public_url` is set ONLY by publish-to-web and is null
122
+ * for the common guest-shared vector, so it would admit an external guest's mention; the vouch
123
+ * register is the doctrine-correct floor — operator vouches, code enforces, no inference).
124
+ *
125
+ * Notion's mention signal lives in ONE webhook delivery (unlike Slack's dual-event), and its
126
+ * "native" handler IS this same supervisor dispatch — so suppress-native and divert are the SAME
127
+ * act here: a window-carrying wake is delivered through the unified channel instead of the notion
128
+ * channel's own send (notion.ts's wake dep), and both legs read THIS one verdict off the one
129
+ * parsed event — structurally never a double-handle, never a gap:
130
+ * • @mention on a singleWindow, VOUCHED-internal page → the seam suppresses the native session
131
+ * and stamps `addressing:"direct-mention"` (the terminal-prose delivery bridge's arm);
132
+ * • ambient (channel-watch) comment on the same page → Leg A: the window WITHOUT the addressed
133
+ * stamp (judged treatment in the shared window, prose stays hard-dropped);
134
+ * • un-vouched page, or singleWindow off, or no discussion id → undefined (the native
135
+ * per-doc/domain path, byte-identical — a mention there keeps today's `direct` wake).
136
+ */
137
+ export declare function planNotionSingleWindow(singleWindow: boolean, isMention: boolean, privacyOk: boolean, target: NotionSingleWindowTarget): UnifiedWindowWake | undefined;
138
+ /** One comment reshaped for the wake — the trigger, or a discussion-sibling backscroll message.
139
+ * `from` is resolved by the caller (self when the bot authored it, else human). */
140
+ export interface NotionWakeMessage {
141
+ readonly from: "human" | "self";
142
+ readonly id: string;
143
+ readonly authorId?: string;
144
+ readonly sentAt: string;
145
+ readonly text: string;
146
+ /** Authenticated parent block of an inline comment. Absent for page-level discussions. */
147
+ readonly anchorId?: string;
148
+ /**
149
+ * Resolved per-message trust tier (identity/wake-trust.ts — the audit-wedge F3 assignment). The
150
+ * live dispatch (notion.ts) resolves it off the binding gate + admin rosters, for the trigger AND
151
+ * every discussion sibling.
152
+ *
153
+ * 🔴 REQUIRED, NOT OPTIONAL (OPE-596) — see LinearSupervisorWakeInput.trigger.trust. The trigger
154
+ * used to default to `principal` on the direct path and a sibling to `peer`, both fail-OPEN, and
155
+ * since OPE-577 the tier decides the `<untrusted_external_data>` fence. A caller that cannot
156
+ * resolve a tier states the fail-closed one itself: `relay` for a machine author, `unauth` for an
157
+ * unvouchable human.
158
+ */
159
+ readonly trust: WakeTrust;
160
+ }
161
+ /**
162
+ * The SAME message BEFORE any author tier is resolved — what notion-webhook.ts produces (OPE-596).
163
+ *
164
+ * The webhook core reads the comment payload; it holds no binding context, so it cannot answer "what
165
+ * standing does this author carry?". The ROUTE answers that, once, for the trigger and every
166
+ * sibling alike (notion.ts `trustOf`, fail-closed to `relay`). This type states that split instead
167
+ * of leaving it to a convention: an untiered message is NOT a {@link NotionWakeMessage} and the
168
+ * compiler will not let one reach {@link buildNotionSupervisorWake}. Before OPE-596 the same two
169
+ * shapes shared one type and the builder defaulted the missing tier UPWARD, so a route leg that
170
+ * forgot the stamp would have rendered a stranger's comment as a member's.
171
+ */
172
+ export type NotionUntieredWakeMessage = Omit<NotionWakeMessage, "trust">;
173
+ export interface NotionSupervisorWakeInput {
174
+ /** direct (guaranteed) or channel-watch (judged) — `drop` never reaches here. */
175
+ readonly addressing: Exclude<NotionAddressing, "drop">;
176
+ readonly pageId: string;
177
+ readonly discussionId: string;
178
+ readonly trigger: NotionWakeMessage;
179
+ /** The OTHER comments in the same discussion, oldest-first — envelope backscroll siblings.
180
+ * Re-sent every wake (cheap at Notion volume) so the judge always has full thread context,
181
+ * even mid-session (design §3.2). Ignored on the `direct` path (renderWake returns the body
182
+ * verbatim there). */
183
+ readonly threadComments?: readonly NotionWakeMessage[];
184
+ /** The OUTGOING generation's recorded TAIL (OPE-794) — rendered BEFORE this wake's own thread
185
+ * comments, so the envelope reads oldest-first across the rotation boundary. Only a FRESH
186
+ * generation's first wake carries one. */
187
+ readonly tail?: readonly WakeMessageInput[];
188
+ /** This surface could not read its own page discussion since the seat's last wake (core
189
+ * channels/seat-catch-up.ts). Rendered as a trusted `<system-note>`; unset ⇒ no note. */
190
+ readonly catchUpUnavailable?: string;
191
+ /** Engagement calibration for the judged preamble (memory/domain.ts engagementTierFor —
192
+ * resolved by the caller; this core stays config-free). Unset ⇒ neutral ⇒ byte-identical. */
193
+ readonly engagementTier?: WakeEngagementTier;
194
+ /** Host-minted wake id (rendered `<wake wake-id=…>`) — SINGLE-WINDOW path only (channels/
195
+ * unified-window.ts): the id the model echoes to `reply` so the host resolves this wake's
196
+ * origin from the map. Unset ⇒ byte-identical (no attribute) — mirrors
197
+ * GitHubSupervisorWakeInput.wakeId. */
198
+ readonly wakeId?: string;
199
+ /** SINGLE-WINDOW addressed @mention (mirrors GitHubSupervisorWakeInput.directMention): render
200
+ * the wake as `direct-mention` — the full judged ENVELOPE (so the `wake-id` survives for the
201
+ * reply tool, the ONLY reply route on the unified channel) with the ADDRESSED preamble instead
202
+ * of the silence-biased watch one. Only meaningful alongside `addressing: "direct"` (the plan
203
+ * only sets it for a real @mention); unset ⇒ today's render, byte-identical — a plain `direct`
204
+ * wake stays the verbatim body. */
205
+ readonly directMention?: boolean;
206
+ /**
207
+ * This page carries an ENGAGED registry row — the seam's `deliver` verdict — so a JUDGED wake
208
+ * states `follow-up="thread-engaged"`, the envelope's own words for "you are already in this
209
+ * conversation and `stand_down` is how you leave" (instructions/access.ts's standing block).
210
+ *
211
+ * 🔴 THE ROW ALREADY SAYS IT AND THE ENVELOPE DID NOT (OPE-1711). `notionWakeAddressing` promotes
212
+ * the `notion.dispatched` row to `thread-follow` off this same verdict, so the deployment knows the
213
+ * page is enrolled and tells its audit trail — while the seat reads bare ambient activity. Ship
214
+ * #197 measured the cost of that gap on LINEAR, whose seam has the identical shape: a standing
215
+ * session declined an engaged follow-up as `user_requested_silence` on a stop asked in an earlier
216
+ * conversation. The fix is OPE-1673's, made on Slack and ported to both ticket surfaces.
217
+ *
218
+ * Like Slack's it does NOT touch `addressing`: `channel-watch` stays the honest silence bar for a
219
+ * standing session, and enrolment is a different fact from that bar. Unset/false ⇒ no attribute.
220
+ */
221
+ readonly threadEngaged?: boolean;
222
+ }
223
+ /**
224
+ * Build the NormalizedWake for one doc-supervisor turn. platform "notion", containerNoun "doc",
225
+ * locus.channel = the page, locus.thread = the discussion, backscroll = the discussion's other
226
+ * comments as oldest-first envelope siblings, ending at the triggering comment. renderWake then
227
+ * emits the exact `{message, context}` shape every OE dispatch sends — the SAME renderer Slack
228
+ * uses, with NO platform branch. A `direct` wake carries no preamble/backscroll (the body is the
229
+ * driver, verbatim); a `channel-watch` wake gets the judged envelope + doc-noun preamble.
230
+ */
231
+ export declare function buildNotionSupervisorWake(input: NotionSupervisorWakeInput): NormalizedWake;
232
+ /** The live supervisor session pointer for a page, as the deps report it. `freshGeneration` is
233
+ * true for a brand-new OR just-rotated generation — its first wake carries the carried tail. */
234
+ export interface NotionSupervisorSession {
235
+ readonly token: string;
236
+ readonly generation: number;
237
+ readonly freshGeneration: boolean;
238
+ /** The OUTGOING generation's recorded tail, oldest-first — empty unless this is a fresh
239
+ * generation's first wake (OPE-794). */
240
+ readonly tail: readonly WakeMessageInput[];
241
+ /** The session's PREVIOUS wake time (the stored lastWakeAt, read BEFORE touchSession advances it),
242
+ * or null/absent when there is no prior delivered wake (a fresh/rotated generation). The cursor
243
+ * the memory-delta push (deps.memoryDelta) diffs against; unset ⇒ no delta computed. */
244
+ readonly lastWakeAt?: string | null;
245
+ }
246
+ /** Deps for {@link handleNotionSupervisorDispatch} — mirror SupervisorRouteDeps (slack-events.ts),
247
+ * injected so the core is unit-testable over a mock store + a capture `wake`. org is baked into
248
+ * the live impl's closures (a deployment fact — notion.ts), so it never crosses this boundary. */
249
+ export interface NotionSupervisorDeps {
250
+ /** Create-or-fetch the live supervisor session for this page's surfaceKey: mint generation 1 on
251
+ * first sighting, rotate to generation+1 when {@link shouldRotate} says it aged out, else
252
+ * return the current generation. */
253
+ readonly getOrCreateSession: (surfaceKey: string, pageId: string, atIso: string) => Promise<NotionSupervisorSession>;
254
+ /** Record one wake on the current generation (lastWakeAt/turnCount). Best-effort. */
255
+ readonly touchSession?: (surfaceKey: string, atIso: string) => Promise<void>;
256
+ /**
257
+ * THE SINCE-LAST-WAKE CATCH-UP, through the ONE shared path every surface takes
258
+ * (channels/seat-catch-up.ts `seatCatchUp`). Optional so older test doubles keep compiling
259
+ * (absent ⇒ no catch-up, the pre-OPE-1726 behaviour); fail-soft by construction.
260
+ */
261
+ readonly catchUp?: (req: SeatCatchUpRequest) => Promise<SeatCatchUpResult>;
262
+ /**
263
+ * THE §2.5 ENGAGEMENT MARK for an ADDRESSED wake (OPE-1501) — defaults to
264
+ * `channels/notion-engagement.ts`'s `markNotionEngaged`, which writes the live registry.
265
+ *
266
+ * 🔴 IT IS A DEP BECAUSE OF WHERE IT HAS TO RUN, not for testability alone. Notion is the one
267
+ * surface whose EXTERNAL-AUTHOR gate is not at the ingress: the webhook core dispatches, and the
268
+ * decision is made HERE, one step later. Marking at the ingress would let an author the operator
269
+ * excluded ENROL a page by naming the agent on it — no reply, but every later plain comment from
270
+ * anyone would then wake a turn — and would let that same suppressed name-drop CLEAR a
271
+ * stand-down, because `participating: true` lifts the `stopped` flag. So the mark sits below the
272
+ * suppression check, where the answer already exists, and this dep is how the webhook core's own
273
+ * test can drive it. Absent in a unit test ⇒ the live writer.
274
+ */
275
+ readonly markEngaged?: (d: NotionSupervisorDispatch) => Promise<void>;
276
+ /**
277
+ * Record this delivered wake onto the LIVE generation's TAIL ring (OPE-794). Injected because the
278
+ * entry has to be filed under an ORG and a registry key, and this core deliberately holds neither
279
+ * — the live wiring does. Absent (a unit test) ⇒ nothing is recorded and the dispatch is
280
+ * unchanged, which is the same posture `touchSession` takes.
281
+ */
282
+ readonly recordWake?: (entry: SessionTailWakeRow, token: string, surfaceKey: string) => Promise<void>;
283
+ /** Start/continue the supervisor session under its reserved token, posting the rendered wake.
284
+ * `window` is present ONLY on the SINGLE-WINDOW path (the dispatch input carried it): the
285
+ * wiring (notion.ts) then DIVERTS the wake through eve's cross-channel `receive` into the
286
+ * synthetic `unified` channel instead of this channel's own send. Absent ⇒ byte-identical. */
287
+ readonly wake: (input: {
288
+ token: string;
289
+ auth: OpenEverywhereNotionAuth;
290
+ message: string;
291
+ context: readonly string[];
292
+ state: NotionSessionState;
293
+ window?: UnifiedWindowWake;
294
+ }) => Promise<void>;
295
+ /** Compute the "changed since your last wake" `<system-reminder>` PUSH (memory/wake-delta.ts):
296
+ * given the session's previous wake time (`sinceIso`), this wake's time (`atIso`), and this
297
+ * session's own key (`selfKey` = its continuation token, to exclude its own writes), return the
298
+ * ready block or null. Injected so the pure dispatch stays testable; the live wiring (notion.ts)
299
+ * sets it ONLY when armed (supervisor + unified org gate), so unset ⇒ byte-identical. */
300
+ readonly memoryDelta?: (sinceIso: string, atIso: string, selfKey?: string) => Promise<string | null>;
301
+ /** Clock seam (defaults to the real clock). */
302
+ readonly now?: () => string;
303
+ }
304
+ /** Everything notion-webhook hands the supervisor dispatch: the classification + the wake parts +
305
+ * the identity/session facts. Built by the webhook core, consumed here. */
306
+ export interface NotionSupervisorDispatch {
307
+ readonly surfaceKey: string;
308
+ /**
309
+ * The Notion channel credential this delivery runs under (OPE-467) — the integration whose
310
+ * secret verified the signature, else (dev hatch only) the page's domain binding. Selected ONCE, by the webhook core,
311
+ * and carried here so the route's own Notion calls (the spend gate's visible refusal comment)
312
+ * cannot re-derive a DIFFERENT one. Nothing in this module reads it; it exists so there is
313
+ * exactly one selection per delivery rather than two rules that agree by luck.
314
+ */
315
+ readonly credentialId: string;
316
+ /** direct | channel-watch — `drop` is filtered upstream (never dispatched). */
317
+ readonly addressing: Exclude<NotionAddressing, "drop">;
318
+ readonly pageId: string;
319
+ readonly discussionId: string;
320
+ readonly workspaceId: string | null;
321
+ readonly auth: OpenEverywhereNotionAuth;
322
+ readonly trigger: NotionWakeMessage;
323
+ readonly threadComments: readonly NotionWakeMessage[];
324
+ /** Engagement calibration tier for the judged preamble (resolved by the webhook core). */
325
+ readonly engagementTier?: WakeEngagementTier;
326
+ /**
327
+ * The EXTERNAL-PARTICIPANT POLICY for this page (OPE-507), RESOLVED BY THE CALLER — this core
328
+ * stays config-free, exactly as {@link NotionSupervisorDispatch.engagementTier} does. The live
329
+ * wiring (notion.ts) resolves it as `resolveExternalPolicy(externalPolicyOverrideFor(surfaceKey,
330
+ * domains))`, so the org default and the domain override are both applied before it arrives here.
331
+ *
332
+ * Unset ⇒ the ORG DEFAULT alone (`resolveExternalPolicy()`), which ships `taint` ⇒ byte-identical
333
+ * to before this field existed. Every pure/test caller therefore stays unchanged.
334
+ */
335
+ readonly externalPolicy?: ExternalPolicy;
336
+ /** UNIFIED cross-surface grain resolved by the route leg (supervisorGrainFor, fail-soft false) —
337
+ * stamps the wake's platform address + P5 disclosure AND marks the session state `oeUnified`
338
+ * (the message-tool-only gate's key in notion.ts). Unset ⇒ byte-identical per-doc path. */
339
+ readonly unified?: boolean;
340
+ /** SINGLE-WINDOW wake plumbing, minted by the route leg via {@link planNotionSingleWindow} when
341
+ * the grain says `singleWindow` AND the page passed the privacy floor: the wakeId is rendered
342
+ * into the envelope by this core; the whole object is passed through to deps.wake, whose
343
+ * wiring registers the map entry and diverts into the unified channel. Unset ⇒ byte-identical. */
344
+ readonly window?: UnifiedWindowWake;
345
+ /**
346
+ * The ANCESTOR-TRUST verdict for this delivery's page (OPE-492), resolved ONCE by the webhook core
347
+ * and carried here for the ROUTE. Nothing in THIS module reads it. The route reads it twice:
348
+ * • the AUDIT ROW records WHICH refusal happened (`database-boundary`, `hop-limit`, `cycle`,
349
+ * `unresolvable`, `workspace-root`, `no-roots`) rather than only that the page was untrusted;
350
+ * • the SINGLE-WINDOW PRIVACY FLOOR accepts `trusted: true` as an internal signal (OPE-540 —
351
+ * notion.ts `notionSingleWindowPrivacyOk`), so the floor and the memory plane agree on one
352
+ * page. The floor only READS this verdict; it never re-derives it, so it stays synchronous.
353
+ * The trust also travels on {@link NotionSupervisorDispatch.auth} as the `trust_root` attribute,
354
+ * which is what `bindNotion` binds.
355
+ *
356
+ * Unset on a caller that declares no roots — the resolver returns `no-roots` with no I/O, and the
357
+ * webhook core omits the field. Both readers must treat the absent field as NOT trusted.
358
+ */
359
+ readonly trust?: NotionDeliveryTrust;
360
+ /** SINGLE-WINDOW addressed @mention (the plan's window carries `addressing:"direct-mention"`):
361
+ * render the wake as the addressed `direct-mention` variant (envelope kept, watch preamble
362
+ * swapped for the addressed one). Unset ⇒ today's renders, byte-identical. */
363
+ readonly directMention?: boolean;
364
+ /**
365
+ * The §2.5 ENGAGEMENT SEAM is what admitted this delivery (OPE-1510): the page carries an
366
+ * engagement row, and this PLAIN comment is a follow-up on it. Resolved ONCE by the webhook core —
367
+ * the one place that reads the registry — and carried here for the ROUTE, exactly as {@link
368
+ * NotionSupervisorDispatch.trust} is.
369
+ *
370
+ * 🔴 IT DOES NOT CHANGE HOW THE WAKE IS JUDGED. `addressing` stays `channel-watch`, so the
371
+ * silence bar is untouched. The field has two readers, and both only STATE the enrolment:
372
+ * • the route's `notion.dispatched` row says WHAT WOKE IT (`notionWakeAddressing`,
373
+ * channels/notion-engagement.ts);
374
+ * • the WAKE ENVELOPE says it to the seat as `follow-up="thread-engaged"` (OPE-1711 — it reaches
375
+ * {@link NotionSupervisorWakeInput.threadEngaged}, whose 🔴 carries the measurement).
376
+ * One verdict feeds both, so the row and the envelope can never disagree. Unset ⇒ the row reports
377
+ * the classifier's own value and the envelope states no contract, byte-identical to before.
378
+ */
379
+ readonly engagedFollowUp?: boolean;
380
+ /**
381
+ * HOW THE OPERATOR'S OWN CONFIG HOLDS THIS PAGE (OPE-1510): `roster` — a domain lists the page by
382
+ * id; `container` — a domain reaches it by a CONTAINER entry, which is the whole workspace or
383
+ * a same-level page glob (memory/domain.ts); `none` — no domain holds it. Resolved
384
+ * ONCE by the webhook core, by the same `notionPageDomain` read its addressed door gates on
385
+ * (channels/notion-scope.ts), and carried here for the ROUTE exactly as {@link
386
+ * NotionSupervisorDispatch.engagedFollowUp} is.
387
+ *
388
+ * 🔴 NOTHING IN THIS MODULE READS IT. It only lets the route's `notion.dispatched` row record the
389
+ * DOMAIN ORIGIN beside what woke the delivery, so a name-drop admitted by a claim is
390
+ * distinguishable from one on a page an operator listed. Unset ⇒ the row reads `none`.
391
+ */
392
+ readonly domainVia?: NotionVia;
393
+ }
394
+ /**
395
+ * The dispatch AS THE WEBHOOK CORE BUILDS IT (OPE-596) — every field of {@link
396
+ * NotionSupervisorDispatch} except that its messages carry no author tier yet (see {@link
397
+ * NotionUntieredWakeMessage}). The route leg (notion.ts) stamps the tier on the trigger and on every
398
+ * sibling, and that stamp is what turns this into a {@link NotionSupervisorDispatch} the supervisor
399
+ * core will accept. The two types are what stop the stamp being an optional step.
400
+ */
401
+ export interface NotionUntieredSupervisorDispatch extends Omit<NotionSupervisorDispatch, "trigger" | "threadComments"> {
402
+ readonly trigger: NotionUntieredWakeMessage;
403
+ readonly threadComments: readonly NotionUntieredWakeMessage[];
404
+ }
405
+ /**
406
+ * THE INGESTED SET for one Notion wake, graded for the non-member taint join (OPE-466 / OPE-516).
407
+ *
408
+ * 🔴 NOTION HAD NO AUTHOR LEG AT ALL BEFORE OPE-516, and it could not have had one. The join's
409
+ * `refuted` field is the SURFACE's positive refutation — Slack's `is_restricted`, Teams' Entra
410
+ * `userType: "guest"` — and Notion publishes NO membership fact about a comment author. So the
411
+ * question is answered from the operator's own AUTHOR-TRUST REGISTER instead
412
+ * (identity/author-trust.ts): on a workspace the operator has armed, an author they did not declare
413
+ * grades `external`. On an unarmed workspace the leg contributes nothing and this is a no-op.
414
+ *
415
+ * `refuted` is deliberately never set here. Leaving it absent is the honest statement — Notion has
416
+ * no verdict to give, and a hardcoded `false` would read as "we asked and it was fine".
417
+ *
418
+ * NOTION HAS NO GROUP CONCEPT, so no memberships are contributed and a Notion declaration is
419
+ * principal-keys-only. That is a platform fact, not a gap in this function.
420
+ *
421
+ * A `self` author (the bot's own prior comment) carries no `authorId` from the webhook core, and its
422
+ * resolved tier is the machine floor, so it can never reach the register leg — the join requires a
423
+ * positively-human tier.
424
+ *
425
+ * Pure and exported so the grading is testable without a store or a live wake.
426
+ */
427
+ export declare function notionIngestedMessages(d: {
428
+ readonly workspaceId: string | null;
429
+ readonly trigger: NotionWakeMessage;
430
+ readonly threadComments: readonly NotionWakeMessage[];
431
+ }): readonly IngestedChatMessage[];
432
+ /**
433
+ * THE EXTERNAL-AUTHOR DECISION for one Notion dispatch (OPE-507). Pure, exported so the three
434
+ * behaviours are testable without a store or a live wake.
435
+ *
436
+ * Notion's three answers, and why they are what they are:
437
+ * • the TRIGGER's author is excluded ⇒ NO WAKE AT ALL (`suppressed`). That covers behaviour 2
438
+ * (ambient never triggers on their comment) and behaviour 1 (their @mention is not acted on).
439
+ * • a SIBLING's author is excluded ⇒ the wake proceeds and that sibling's body is WITHHELD
440
+ * (behaviour 3): a permitted member's later comment still wakes the agent, and the excluded
441
+ * author's earlier comment reaches the model as the arrived-marker.
442
+ * • nothing is excluded, or the policy is `taint` ⇒ `withheldIds` is empty and every caller path
443
+ * is byte-identical to before this existed.
444
+ *
445
+ * 🔴 NOTION POSTS NO PRIVATE NOTICE, AND THAT IS DELIBERATE. Behaviour 1 owes the excluded sender a
446
+ * PRIVATE notice, and Notion has no private channel back to a commenter — a comment reply lands in
447
+ * the shared discussion, where everyone reading the doc sees it. Announcing "I will not act on your
448
+ * message" into a shared doc is a disclosure, not a notice, so the Notion answer is to do nothing.
449
+ * The surfaces that HAVE a private channel (a Discord DM, a Slack DM) post the notice there.
450
+ */
451
+ export declare function notionExternalAuthorDecision(d: {
452
+ readonly trigger: NotionWakeMessage;
453
+ readonly threadComments: readonly NotionWakeMessage[];
454
+ readonly ingested: readonly IngestedChatMessage[];
455
+ readonly policy: ExternalPolicy;
456
+ }): {
457
+ readonly suppressed: boolean;
458
+ readonly withheldIds: ReadonlySet<string>;
459
+ };
460
+ export declare function handleNotionSupervisorDispatch(d: NotionSupervisorDispatch, deps: NotionSupervisorDeps): Promise<void>;
461
+ export { shouldRotate };
462
+ //# sourceMappingURL=notion-supervisor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notion-supervisor.d.ts","sourceRoot":"","sources":["../../../agent/channels/notion-supervisor.ts"],"names":[],"mappings":"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"}