@open-everywhere/provider-github 0.0.0-stage โ†’ 0.1.1

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 (111) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +21 -0
  3. package/README.md +50 -2
  4. package/agent/channels/github-catch-up.ts +134 -0
  5. package/agent/channels/github-engagement.ts +381 -0
  6. package/agent/channels/github-identity.ts +376 -0
  7. package/agent/channels/github-installations.ts +152 -0
  8. package/agent/channels/github-message-ops.ts +62 -0
  9. package/agent/channels/github-origin-codec.ts +42 -0
  10. package/agent/channels/github-post-arm.ts +422 -0
  11. package/agent/channels/github-reaction-feedback.ts +489 -0
  12. package/agent/channels/github-reaction-scope.ts +312 -0
  13. package/agent/channels/github-read.ts +471 -0
  14. package/agent/channels/github-stop.ts +175 -0
  15. package/agent/channels/github-supervisor.ts +645 -0
  16. package/agent/channels/github-webhook-verifier.ts +56 -0
  17. package/agent/channels/github.ts +1458 -0
  18. package/agent/contributions.ts +31 -0
  19. package/agent/docs-generated.ts +15 -0
  20. package/agent/memory/memory.ts +265 -0
  21. package/agent/ops.ts +17 -0
  22. package/agent/provider-events.ts +114 -0
  23. package/agent/register.ts +130 -0
  24. package/agent/surface-parity.ts +116 -0
  25. package/dist/agent/channels/github-catch-up.d.ts +29 -0
  26. package/dist/agent/channels/github-catch-up.d.ts.map +1 -0
  27. package/dist/agent/channels/github-catch-up.js +105 -0
  28. package/dist/agent/channels/github-catch-up.js.map +1 -0
  29. package/dist/agent/channels/github-engagement.d.ts +223 -0
  30. package/dist/agent/channels/github-engagement.d.ts.map +1 -0
  31. package/dist/agent/channels/github-engagement.js +317 -0
  32. package/dist/agent/channels/github-engagement.js.map +1 -0
  33. package/dist/agent/channels/github-identity.d.ts +164 -0
  34. package/dist/agent/channels/github-identity.d.ts.map +1 -0
  35. package/dist/agent/channels/github-identity.js +295 -0
  36. package/dist/agent/channels/github-identity.js.map +1 -0
  37. package/dist/agent/channels/github-installations.d.ts +49 -0
  38. package/dist/agent/channels/github-installations.d.ts.map +1 -0
  39. package/dist/agent/channels/github-installations.js +114 -0
  40. package/dist/agent/channels/github-installations.js.map +1 -0
  41. package/dist/agent/channels/github-message-ops.d.ts +3 -0
  42. package/dist/agent/channels/github-message-ops.d.ts.map +1 -0
  43. package/dist/agent/channels/github-message-ops.js +58 -0
  44. package/dist/agent/channels/github-message-ops.js.map +1 -0
  45. package/dist/agent/channels/github-origin-codec.d.ts +7 -0
  46. package/dist/agent/channels/github-origin-codec.d.ts.map +1 -0
  47. package/dist/agent/channels/github-origin-codec.js +36 -0
  48. package/dist/agent/channels/github-origin-codec.js.map +1 -0
  49. package/dist/agent/channels/github-post-arm.d.ts +54 -0
  50. package/dist/agent/channels/github-post-arm.d.ts.map +1 -0
  51. package/dist/agent/channels/github-post-arm.js +339 -0
  52. package/dist/agent/channels/github-post-arm.js.map +1 -0
  53. package/dist/agent/channels/github-reaction-feedback.d.ts +97 -0
  54. package/dist/agent/channels/github-reaction-feedback.d.ts.map +1 -0
  55. package/dist/agent/channels/github-reaction-feedback.js +380 -0
  56. package/dist/agent/channels/github-reaction-feedback.js.map +1 -0
  57. package/dist/agent/channels/github-reaction-scope.d.ts +102 -0
  58. package/dist/agent/channels/github-reaction-scope.d.ts.map +1 -0
  59. package/dist/agent/channels/github-reaction-scope.js +296 -0
  60. package/dist/agent/channels/github-reaction-scope.js.map +1 -0
  61. package/dist/agent/channels/github-read.d.ts +135 -0
  62. package/dist/agent/channels/github-read.d.ts.map +1 -0
  63. package/dist/agent/channels/github-read.js +371 -0
  64. package/dist/agent/channels/github-read.js.map +1 -0
  65. package/dist/agent/channels/github-stop.d.ts +52 -0
  66. package/dist/agent/channels/github-stop.d.ts.map +1 -0
  67. package/dist/agent/channels/github-stop.js +145 -0
  68. package/dist/agent/channels/github-stop.js.map +1 -0
  69. package/dist/agent/channels/github-supervisor.d.ts +308 -0
  70. package/dist/agent/channels/github-supervisor.d.ts.map +1 -0
  71. package/dist/agent/channels/github-supervisor.js +339 -0
  72. package/dist/agent/channels/github-supervisor.js.map +1 -0
  73. package/dist/agent/channels/github-webhook-verifier.d.ts +5 -0
  74. package/dist/agent/channels/github-webhook-verifier.d.ts.map +1 -0
  75. package/dist/agent/channels/github-webhook-verifier.js +55 -0
  76. package/dist/agent/channels/github-webhook-verifier.js.map +1 -0
  77. package/dist/agent/channels/github.d.ts +139 -0
  78. package/dist/agent/channels/github.d.ts.map +1 -0
  79. package/dist/agent/channels/github.js +1232 -0
  80. package/dist/agent/channels/github.js.map +1 -0
  81. package/dist/agent/contributions.d.ts +12 -0
  82. package/dist/agent/contributions.d.ts.map +1 -0
  83. package/dist/agent/contributions.js +31 -0
  84. package/dist/agent/contributions.js.map +1 -0
  85. package/dist/agent/docs-generated.d.ts +3 -0
  86. package/dist/agent/docs-generated.d.ts.map +1 -0
  87. package/dist/agent/docs-generated.js +13 -0
  88. package/dist/agent/docs-generated.js.map +1 -0
  89. package/dist/agent/memory/memory.d.ts +54 -0
  90. package/dist/agent/memory/memory.d.ts.map +1 -0
  91. package/dist/agent/memory/memory.js +224 -0
  92. package/dist/agent/memory/memory.js.map +1 -0
  93. package/dist/agent/ops.d.ts +3 -0
  94. package/dist/agent/ops.d.ts.map +1 -0
  95. package/dist/agent/ops.js +16 -0
  96. package/dist/agent/ops.js.map +1 -0
  97. package/dist/agent/provider-events.d.ts +3 -0
  98. package/dist/agent/provider-events.d.ts.map +1 -0
  99. package/dist/agent/provider-events.js +112 -0
  100. package/dist/agent/provider-events.js.map +1 -0
  101. package/dist/agent/register.d.ts +4 -0
  102. package/dist/agent/register.d.ts.map +1 -0
  103. package/dist/agent/register.js +116 -0
  104. package/dist/agent/register.js.map +1 -0
  105. package/dist/agent/surface-parity.d.ts +3 -0
  106. package/dist/agent/surface-parity.d.ts.map +1 -0
  107. package/dist/agent/surface-parity.js +110 -0
  108. package/dist/agent/surface-parity.js.map +1 -0
  109. package/package.json +156 -4
  110. package/tsconfig.build.json +22 -0
  111. package/tsconfig.json +15 -0
@@ -0,0 +1,296 @@
1
+ // THE GITHUB REACTION-POLL SCOPE (OPE-1540) โ€” the two gates that decide whether one delivery is
2
+ // allowed to spend REST calls looking for reactions, and the durable record the first gate reads.
3
+ //
4
+ // WHY A GATE EXISTS AT ALL. GitHub pushes no reaction webhook, so the feedback arm
5
+ // (channels/github-reaction-feedback.ts) POLLS: every signature-verified `issue_comment`/`issues`
6
+ // delivery made it read the issue and a comment page, and only then could it learn that the agent
7
+ // has never commented in that conversation and there is nothing to look at. That is 2โ€“3 installation
8
+ // REST calls per delivery, on the SAME installation token the reply path mints. A repository taking
9
+ // 400 deliveries an hour spent ~800โ€“1200 GETs an hour learning nothing, and the 429 pressure landed
10
+ // on the agent's own posts.
11
+ //
12
+ // โ”€โ”€ GATE 1: THE CONVERSATION MUST BE ONE THE AGENT IS IN, AND IT READS TWO RECORDS
13
+ //
14
+ // A reaction the arm can record is a reaction on the AGENT's own comment, so a conversation the agent
15
+ // has never commented in can hold none. Gate 1 answers "is the agent in this conversation" from two
16
+ // durable records, and admits on EITHER. Both are keyed store reads; neither costs a REST call.
17
+ //
18
+ // 1. THE POST CLAIM, written by this bundle's own reply path (channels/github-post-arm.ts
19
+ // `liveGitHubPost`). That is the one place a GitHub comment leaves THIS BUNDLE โ€” every `reply`
20
+ // tool call, every unified-window reply and every ambient-supervisor answer.
21
+ // 2. THE ENGAGEMENT ROW, written by the ยง2.5 seam (channels/github-engagement.ts) when somebody
22
+ // @mentions the app in a container.
23
+ //
24
+ // ๐Ÿ”ด THE SECOND READ EXISTS BECAUSE THIS BUNDLE IS NOT THE ONLY POSTER. eve's default posts the
25
+ // `input.requested` comment, which this bundle does not override, and it still posts a NATIVE
26
+ // terminal completion on the paths that fall back to it โ€” a review thread's inline reply, and a
27
+ // state with no post anchor (`channels/github.ts`). (An ordinary native terminal completion claims
28
+ // here now: it posts through `liveGitHubPost` since OPE-1681, so that example is no longer one.) Those comments carry the app's login and attract reactions exactly as a `reply`
29
+ // does, and NOTHING in this bundle sees them go out โ€” so a post-claim-only gate would refuse those
30
+ // conversations forever, not merely until the next reply. The engagement row is what covers them: the
31
+ // native leg wakes only on an @mention (which marks the row) or on a plain comment in a container
32
+ // already marked, so every conversation eve can post in has one.
33
+ //
34
+ // ๐Ÿ”ด IT ADMITS A LITTLE MORE THAN "HAS POSTED", ON PURPOSE. A container somebody @mentioned the app
35
+ // in where the app then said nothing is admitted and costs a poll. That is the safe direction โ€” the
36
+ // alternative is a reaction the deployment can never record โ€” and gate 2 caps what it can cost.
37
+ //
38
+ // ๐Ÿ”ด THE POST CLAIM IS A `notice_claim`, AND THE LIFETIME IS THE POINT. "The agent has commented
39
+ // here" never stops being true, so the record must never expire: a TTL would blind the poll to a
40
+ // quiet conversation's reactions the moment the TTL lapsed, and re-writing the mark needs a post
41
+ // nobody is going to make. `claimNotice`/`noticeClaimed` (operational/store.ts) is the tree's
42
+ // at-most-once claim with no TTL and no prune, which is exactly this shape. Growth is one row per
43
+ // conversation the agent has ever commented in โ€” bounded by conversations, never by deliveries.
44
+ //
45
+ // ๐Ÿ”ด WHAT THE CUT-OVER COSTS, STATED. Both records start from what already exists: engagement rows
46
+ // are already there for every container an @mention ever reached, and the post claim starts EMPTY. So
47
+ // a conversation the agent only ever answered ambiently โ€” no @mention, hence no engagement row โ€” and
48
+ // has not answered since this shipped is not polled until it answers there again. The reaction arm
49
+ // landed one day before this gate (OPE-1502, PR #587), so the window of reactions that can fall into
50
+ // that gap is one day wide. It is a real gap, not a theoretical one.
51
+ //
52
+ // FAIL-OPEN on a store error. An unreadable record answers "the agent is in this conversation", so a
53
+ // store blip costs REST calls rather than silently stopping the feedback signal. It is the opposite
54
+ // posture from the reaction DEDUPE next door (channels/github-reaction-feedback.ts), which fails
55
+ // CLOSED โ€” these two gates bound a COST, and that one bounds what the audit log claims happened.
56
+ //
57
+ // โ”€โ”€ GATE 2: A PER-REPOSITORY HOURLY BUDGET
58
+ //
59
+ // Gate 1 bounds the poll to conversations the agent is in, which is the big cut. It does NOT bound
60
+ // what one very busy conversation can spend: a hundred comments an hour in a pull request the agent
61
+ // replied to is a hundred polls. So a second gate caps the polls one REPOSITORY may run in one clock
62
+ // hour, and the trip is AUDITED โ€” a silently capped feedback signal reads exactly like a feature that
63
+ // stopped working.
64
+ //
65
+ // ๐Ÿ”ด THE COUNTER IS APPROXIMATE UNDER CONCURRENCY, AND THAT IS ACCEPTED. It is a read-then-write over
66
+ // the opaque `task_result` KV, not an atomic increment, so two deliveries racing on the same repo can
67
+ // both read N and write N+1 โ€” the hour's true count can exceed the budget by roughly the number of
68
+ // concurrent deliveries. A rate budget is a cost bound, not a security control: over-counting would
69
+ // drop feedback that should have been recorded, under-counting costs a few extra GETs. The cheap,
70
+ // non-atomic direction is the one whose failure mode is the harmless one.
71
+ //
72
+ // ๐Ÿ”ด THE TTL IS COUPLED, SO IT IS NOT A KNOB. `task_result`'s prune is ORG-WIDE and uses the CALLING
73
+ // writer's own ttl (operational/store.ts, the task_result section), so every consumer must pass the
74
+ // same six hours. {@link GITHUB_POLL_BUDGET_TTL_MS} exists to be that number and nothing else โ€” a
75
+ // shorter one here would start deleting `model/turn-state.ts`'s live rows on every delivery.
76
+ import { appendAudit, deploymentOrg, getOperationalStore, } from "@open-everywhere/core/agent/adapter-api.js";
77
+ import { githubConversationKey } from "./github-identity.js";
78
+ /** How many reaction polls one repository may run in one clock hour. Sized so an ordinarily busy
79
+ * repository never reaches it โ€” the gate is a ceiling on a runaway conversation, not a throttle on
80
+ * normal traffic. One ADMITTED poll costs up to 13 GETs (the issue read, one or two comment pages,
81
+ * and up to `GITHUB_REACTION_POLL_COMMENT_BUDGET` reaction reads), so this bounds a repository's
82
+ * worst hour to ~780 GETs on the installation token the reply path shares. The everyday cost is far
83
+ * below that: most polls read three. */
84
+ export const GITHUB_REACTION_POLL_HOURLY_BUDGET = 60;
85
+ /** The `task_result` retention every consumer of that table shares. See the header: it is coupled,
86
+ * not tunable. Six hours, the same window `model/turn-state.ts` and the three other consumers use. */
87
+ const GITHUB_POLL_BUDGET_TTL_MS = 6 * 60 * 60 * 1000;
88
+ /** The audit action a tripped budget writes. Queryable over the control plane's audit route, the
89
+ * same way `github.ambient_skipped` answers "why did the ambient leg stay quiet". */
90
+ export const GITHUB_REACTION_POLL_BUDGET_ACTION = "github.reaction_poll_budget";
91
+ /** The audit action an UNREADABLE CLAIM STORE writes, once per poll. The dedupe next door fails
92
+ * CLOSED, so a store that cannot answer "is this recorded" stops every feedback row for as long as
93
+ * it stays down โ€” and a silent zero reads exactly like a quiet week. This row is the signal. It
94
+ * carries the same audit ACTION shape as the budget trip above, so an operator reads both off the
95
+ * control plane's audit route; the GRAIN differs, and {@link auditGitHubReactionClaimUnreadable}
96
+ * says how. */
97
+ export const GITHUB_REACTION_CLAIM_UNREADABLE_ACTION = "github.reaction_claim_unreadable";
98
+ /** How long a reply may wait on the best-effort post claim below.
99
+ *
100
+ * ๐Ÿ”ด THE CEILING IS THE POINT, NOT THE NUMBER. `liveGitHubPost` marks the conversation AFTER the
101
+ * comment has already landed, so this write can only ever delay the reply tool's RETURN โ€” and with
102
+ * no ceiling a slow store held that return for as long as it liked, on the turn path. Two seconds is
103
+ * far more than a keyed claim needs and far less than a turn can notice. */
104
+ export const GITHUB_POSTED_MARK_TIMEOUT_MS = 2000;
105
+ /** How long the trip row's once-per-hour guard holds. It is the bucket width, not a dedupe window:
106
+ * the key already carries the hour, so this only has to outlive the hour it names. */
107
+ const BUDGET_AUDIT_TTL_MS = 2 * 60 * 60 * 1000;
108
+ /** The claim key for "the agent has commented in this conversation". `githubConversationKey` is the
109
+ * SAME `owner/repo#N` anchor the engagement registry and the stop registry address, so the mark and
110
+ * every other per-conversation record in this bundle name the container the same way. */
111
+ function githubPostedClaimKey(owner, repo, number) {
112
+ const anchor = githubConversationKey(owner, repo, number);
113
+ return anchor ? `github-posted:${anchor}` : undefined;
114
+ }
115
+ /** The hourly budget's key for one repository. The clock hour rides IN the key, so the counter needs
116
+ * no reset and a stale bucket simply stops being read. */
117
+ export function githubPollBudgetKey(owner, repo, atIso) {
118
+ return `github-reaction-poll-budget:${owner}/${repo}:${atIso.slice(0, 13)}`;
119
+ }
120
+ /**
121
+ * Record that the agent has commented in this conversation. Best-effort and idempotent โ€” a second
122
+ * post in the same conversation re-claims a key that is already claimed, which the store answers
123
+ * false to and this function ignores. NEVER THROWS: a lost mark costs a later poll, never a reply.
124
+ *
125
+ * ๐Ÿ”ด IT IS ALSO BOUNDED, WHICH IS THE OTHER HALF OF THAT CONTRACT. The one caller is
126
+ * `liveGitHubPost`, on the reply tool's own path, and it calls this AFTER the comment has landed. An
127
+ * unbounded await therefore could not lose a reply but could hold the tool's return for as long as
128
+ * the store took โ€” a real hazard on a tree that already stalls in its post-turn closeout. So the
129
+ * write RACES {@link GITHUB_POSTED_MARK_TIMEOUT_MS}: a store slower than that is treated exactly
130
+ * like the store that throws, and costs a later poll rather than the turn.
131
+ *
132
+ * The abandoned write is not cancelled โ€” nothing here can cancel a store call โ€” so it carries its
133
+ * own settled handler and may still land after this returns. That is the harmless direction: the
134
+ * claim is idempotent and its only reader is the next poll.
135
+ */
136
+ export async function markGitHubConversationPosted(owner, repo, number, atIso) {
137
+ const key = githubPostedClaimKey(owner, repo, number);
138
+ if (!key)
139
+ return;
140
+ let write;
141
+ try {
142
+ // The `.then(_, _)` is what keeps an abandoned rejection from surfacing as an unhandled one:
143
+ // after the race gives up, nothing else is holding this promise.
144
+ write = getOperationalStore()
145
+ .claimNotice(deploymentOrg(), key, atIso)
146
+ .then(() => undefined, () => undefined);
147
+ }
148
+ catch {
149
+ // A store that cannot even be resolved. The reply already landed; there is nothing to wait on.
150
+ return;
151
+ }
152
+ // `unref` so the ceiling never keeps a host alive on its own, and `clearTimeout` so a write that
153
+ // beat it leaves no pending timer behind.
154
+ let timer;
155
+ const ceiling = new Promise((resolve) => {
156
+ timer = setTimeout(resolve, GITHUB_POSTED_MARK_TIMEOUT_MS);
157
+ timer.unref?.();
158
+ });
159
+ try {
160
+ await Promise.race([write, ceiling]);
161
+ }
162
+ finally {
163
+ clearTimeout(timer);
164
+ }
165
+ }
166
+ /**
167
+ * Is the agent IN this conversation โ€” has this bundle's reply path posted here, or did an @mention
168
+ * engage the container? Either answers yes; see the header for why both reads are needed.
169
+ *
170
+ * FAIL-OPEN on a store error, and on a delivery that names no container: an unanswerable question
171
+ * admits the poll, whose own parse then refuses a delivery that names nothing.
172
+ */
173
+ export async function githubConversationInScope(surfaceKey, owner, repo, number) {
174
+ const key = githubPostedClaimKey(owner, repo, number);
175
+ const anchor = githubConversationKey(owner, repo, number);
176
+ if (!key || !anchor)
177
+ return true;
178
+ const org = deploymentOrg();
179
+ try {
180
+ if (await getOperationalStore().noticeClaimed(org, key))
181
+ return true;
182
+ // ๐Ÿ”ด THE STORE, NOT `getThreadEngagement`. That helper swallows its own failure and answers
183
+ // null, so an unreadable registry would be indistinguishable from an un-engaged container and
184
+ // this gate would fail CLOSED on a store blip โ€” the one direction the header forbids. Reading
185
+ // the store directly lets the catch below take the fail-open answer for BOTH records. The
186
+ // coordinates are the helper's own: `p.org` and `p.surfaceKey`, keyed by the container anchor.
187
+ return (await getOperationalStore().getEngagement(org, surfaceKey, anchor)) !== null;
188
+ }
189
+ catch {
190
+ return true;
191
+ }
192
+ }
193
+ /**
194
+ * Spend one poll from this repository's hourly budget.
195
+ *
196
+ * Admits and counts while the hour has room; refuses once the budget is spent, and writes ONE
197
+ * {@link GITHUB_REACTION_POLL_BUDGET_ACTION} row for that hour rather than one per refused delivery โ€”
198
+ * the refusals are the loud part of a busy hour, and an unthrottled row per delivery would be the
199
+ * same flood in the audit log that the budget exists to stop in GitHub's API.
200
+ *
201
+ * FAIL-OPEN on a store error: an unreadable counter admits the poll. A budget is a cost bound, so a
202
+ * store blip must never silence the feedback signal.
203
+ */
204
+ export async function spendGitHubPollBudget(owner, repo, atIso, budget = GITHUB_REACTION_POLL_HOURLY_BUDGET) {
205
+ const org = deploymentOrg();
206
+ const key = githubPollBudgetKey(owner, repo, atIso);
207
+ let used = 0;
208
+ try {
209
+ const raw = await getOperationalStore().getTaskResult(org, key);
210
+ const parsed = raw ? JSON.parse(raw) : undefined;
211
+ used = typeof parsed?.polls === "number" && Number.isFinite(parsed.polls) ? parsed.polls : 0;
212
+ }
213
+ catch {
214
+ return { admitted: true, polls: 0 };
215
+ }
216
+ if (used >= budget) {
217
+ await auditBudgetTrip(org, owner, repo, atIso, used, budget);
218
+ return { admitted: false, polls: used };
219
+ }
220
+ const polls = used + 1;
221
+ try {
222
+ await getOperationalStore().putTaskResult(org, key, JSON.stringify({ polls }), atIso, GITHUB_POLL_BUDGET_TTL_MS);
223
+ }
224
+ catch {
225
+ // The count is lost for this delivery; the poll still runs. Under-counting costs GETs, never a row.
226
+ }
227
+ return { admitted: true, polls };
228
+ }
229
+ /**
230
+ * Write the one row that says this poll's claim store could not be read.
231
+ *
232
+ * ๐Ÿ”ด WHY IT EXISTS. The reaction dedupe (channels/github-reaction-feedback.ts) fails CLOSED on an
233
+ * unreadable claim โ€” an unknown answer counts as ALREADY RECORDED โ€” which is the right posture for
234
+ * what the audit log claims happened, and a silent one. A store that stays unreadable therefore
235
+ * records nothing at all, forever, and the operator sees a feature that looks healthy and reports
236
+ * zero. This row is the difference between "nobody reacted" and "the store is down".
237
+ *
238
+ * ONE ROW PER POLL, never one per reaction: a busy comment page holds dozens of reactions and one
239
+ * broken store would write a row for each. `skipped` carries the count instead, so the row is as
240
+ * loud as the flood would have been. That is a DIFFERENT GRAIN from the budget trip below, which
241
+ * `markEventSeen` throttles to one row per repository per hour โ€” this one has no throttle, because a
242
+ * poll that could not read the store is a distinct event and the count is the thing being reported.
243
+ *
244
+ * ๐Ÿ”ด WHAT BOUNDS THE VOLUME, HONESTLY. The poll reaches here only past gate 2, so an ordinary hour
245
+ * holds at most {@link GITHUB_REACTION_POLL_HOURLY_BUDGET} of these per repository โ€” but only WHILE
246
+ * THE BUDGET COUNTER IS WRITABLE. Gate 2 fails open on a store error, so a fault that breaks the
247
+ * `task_result` write while `audit_log` inserts still land gives one row per delivery instead. That
248
+ * is the same trade the gate already made, and both directions of it are a cost, never a lost row.
249
+ *
250
+ * ๐Ÿ”ด AND IT IS NOT A SIGNAL FOR EVERY OUTAGE. `appendAudit` writes through the SAME operational
251
+ * store whose claim read just threw, so a whole-store outage loses this row too โ€” best-effort, one
252
+ * retry, then a drop-counter tick and a `[open-everywhere:audit] dropped a โ€ฆ` warn (core
253
+ * agent/audit/audit.ts). This row is what makes a PARTIAL fault legible โ€” a missing `notice_claim`
254
+ * table, a table-level grant โ€” and the audit drop counter is what makes the total one legible. The
255
+ * operator doc states the same split.
256
+ *
257
+ * Best-effort, like every other write in this module: nothing here may cost the ingress its ack.
258
+ */
259
+ export async function auditGitHubReactionClaimUnreadable(owner, repo, atIso, skipped) {
260
+ try {
261
+ await appendAudit({
262
+ ts: atIso,
263
+ org: deploymentOrg(),
264
+ platform: "github",
265
+ workspace: owner,
266
+ surface: `github/${owner}/${repo}`,
267
+ action: GITHUB_REACTION_CLAIM_UNREADABLE_ACTION,
268
+ detail: { skipped, hour: atIso.slice(0, 13) },
269
+ });
270
+ }
271
+ catch {
272
+ // Nothing here may cost the ingress its ack.
273
+ }
274
+ }
275
+ /** The trip row, at most once per repository per hour. Both the throttle and the write are
276
+ * best-effort: a budget that cannot audit itself still refuses the poll. */
277
+ async function auditBudgetTrip(org, owner, repo, atIso, used, budget) {
278
+ try {
279
+ const first = await getOperationalStore().markEventSeen(org, `${githubPollBudgetKey(owner, repo, atIso)}:tripped`, atIso, BUDGET_AUDIT_TTL_MS);
280
+ if (!first)
281
+ return;
282
+ await appendAudit({
283
+ ts: atIso,
284
+ org,
285
+ platform: "github",
286
+ workspace: owner,
287
+ surface: `github/${owner}/${repo}`,
288
+ action: GITHUB_REACTION_POLL_BUDGET_ACTION,
289
+ detail: { budget, polls: used, hour: atIso.slice(0, 13) },
290
+ });
291
+ }
292
+ catch {
293
+ // Nothing here may cost the ingress its ack.
294
+ }
295
+ }
296
+ //# sourceMappingURL=github-reaction-scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-reaction-scope.js","sourceRoot":"","sources":["../../../agent/channels/github-reaction-scope.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,135 @@
1
+ import { type AdapterReadFetch, type BindableContext, type PrFetchFn, type RenderedLine, type RetryPolicy, type WakeReadAddress } from "@open-everywhere/core/agent/adapter-api.js";
2
+ /**
3
+ * The 429 budget ONE READ may spend, across every call it makes (OPE-1299).
4
+ *
5
+ * ๐Ÿ”ด THE DEFECT WAS MULTIPLICATION, NOT THE PER-CALL POLICY. `withRetryAfterLoose`'s budget is
6
+ * per call, and both reads here walk several: `readChannel` issues up to three (`issues.get`, then
7
+ * one or two `issues.comments.list` pages) and `readThread` up to {@link MAX_REVIEW_PAGES}
8
+ * `pulls.comments.list` pages (it fetches no issue object โ€” the review-comment walk is the whole
9
+ * read). Under the shared 60 s default that is ~3 and ~5 minutes of waiting for ONE `read_channel` /
10
+ * `read_thread` tool call, and nothing bounded the sum.
11
+ *
12
+ * So the whole read shares ONE deadline, read fresh per call ({@link walkRetry}). The first call
13
+ * still gets the full budget โ€” a single-call read is not tightened at all, which is why this costs
14
+ * no extra failures on the ordinary path โ€” and each later call gets only what is left. The worst
15
+ * case for a whole read becomes this number instead of a multiple of it.
16
+ *
17
+ * ๐Ÿ”ด THIS IS THE SEAM'S OWN POLICY, NOT A CALLER'S. `ReadAdapter.readChannel`/`readThread`
18
+ * (core's channels/channel-read.ts) take no options object, and every one of the six adapters
19
+ * already spends the trailing parameter on its own transport seam โ€” so widening the interface to
20
+ * carry a policy is a cross-provider change, and no production caller could pass one until it
21
+ * happened. Slack answered the same question the same way: `PROBE_OPERATIONS`
22
+ * (providers/slack/agent/channels/slack-web-api.ts) is a table the seam applies itself, with an
23
+ * explicit dependency still winning. `getJson`'s `retry` argument keeps that property here โ€” a test
24
+ * passes its own policy and this default never reaches it.
25
+ *
26
+ * 60 s, matching `DEFAULT_TOTAL_BUDGET_MS`: a read that 429s out degrades the turn's context rather
27
+ * than losing an answer, so the budget buys latency back without making a first attempt any more
28
+ * likely to fail.
29
+ */
30
+ export declare const READ_WALK_BUDGET_MS = 60000;
31
+ /**
32
+ * The clock and sleep one walk runs on. Absent in production โ€” the adapter takes the real ones.
33
+ *
34
+ * ๐Ÿ”ด IT IS HERE SO THE SHARED BUDGET IS TESTABLE AT ALL. The claim this seam makes is about the
35
+ * SECOND and later calls of a walk, and a walk under the real clock can only be observed by waiting
36
+ * out its real waits. `github-read-test.ts` ยง 8 drives a clock that advances on each recorded sleep,
37
+ * which is what lets one assertion separate "one deadline for the walk" from "one budget per call".
38
+ */
39
+ export interface ReadWalkSeam {
40
+ readonly now?: () => number;
41
+ readonly sleep?: (ms: number) => Promise<void>;
42
+ }
43
+ /** The policy one call inside a walk takes: whatever is left of the walk's shared deadline. Zero is
44
+ * a real value the primitive honours โ€” at the deadline, a retry gives up instead of waiting. */
45
+ export declare function walkRetry(deadlineMs: number, seam?: ReadWalkSeam): RetryPolicy;
46
+ /** One GitHub conversation's address, parsed out of the container id. */
47
+ export interface GitHubContainer {
48
+ /** The repo owner, as GitHub spells it โ€” the API path segment, never a sanitized key segment. */
49
+ readonly owner: string;
50
+ readonly repo: string;
51
+ /** `owner/repo` โ€” the form every core SCM helper takes. */
52
+ readonly repoFull: string;
53
+ /** The issue or PR number. */
54
+ readonly number: number;
55
+ }
56
+ /**
57
+ * Parse `owner/repo#number` โ€” the container id {@link githubReadAdapter.wakeAddress} mints.
58
+ *
59
+ * Returns `undefined` on anything else rather than guessing a part. A partial address would fetch
60
+ * another repo's conversation of the same number, which is the silent mis-address the whole
61
+ * wake-container design refuses (core channels/wake-container.ts).
62
+ */
63
+ export declare function parseGithubContainer(container: string): GitHubContainer | undefined;
64
+ /** The live transport. Injected in every read below so the whole adapter drives offline โ€” the same
65
+ * DI shape slack-read / discord-read take. */
66
+ /** THE package's ONE read transport. Exported so channels/github-reaction-feedback.ts borrows it
67
+ * rather than reaching for `globalThis.fetch` itself โ€” a second reach would be a second transport
68
+ * outside this module's retry seam, which `test:github-write-seam` ยง4 exists to refuse. */
69
+ export declare const liveGithubReadFetch: PrFetchFn;
70
+ /**
71
+ * `operation` is the vendor route name (OPE-1255) `withRetryAfterLoose`'s `RateLimitExhaustedError`
72
+ * reports on exhaustion โ€” this read-only transport was, until now, the ONE issue/PR reader in this
73
+ * package with no 429 backoff (`docs/extending/provider-rate-limits.md`).
74
+ *
75
+ * Exported so its retry behaviour is unit-tested directly (github-read-test.ts), the same way
76
+ * `github-rate-limit-test.ts` drives `githubWrite` directly rather than through a full reply.
77
+ *
78
+ * `retry` reaches no caller OUTSIDE this file โ€” `ReadAdapter.readChannel`/`readThread`
79
+ * (channels/channel-read.ts) take no options object. Since OPE-1299 the adapter itself passes one:
80
+ * each read builds a shared deadline and hands every call what is left of it
81
+ * ({@link READ_WALK_BUDGET_MS}, {@link walkRetry}), so a multi-call read is bounded as a whole.
82
+ */
83
+ export declare function getJson<T>(fetchFn: PrFetchFn, url: string, token: string, operation: string, retry?: RetryPolicy): Promise<T>;
84
+ /** The raw shapes this adapter reads. Only the fields it renders are declared. */
85
+ interface RawGitHubUser {
86
+ readonly login?: string;
87
+ readonly type?: string;
88
+ }
89
+ interface RawComment {
90
+ readonly id?: number;
91
+ readonly body?: string | null;
92
+ readonly user?: RawGitHubUser;
93
+ readonly created_at?: string;
94
+ readonly in_reply_to_id?: number | null;
95
+ }
96
+ /**
97
+ * The review comments belonging to ONE thread, oldest-first โ€” the thread's own root plus every
98
+ * comment that replies into it. PURE, and exported for the render test.
99
+ *
100
+ * GitHub sets `in_reply_to_id` to the thread's ROOT on every reply, not to the comment being
101
+ * answered, so one equality covers a thread of any depth. The root itself carries no
102
+ * `in_reply_to_id`, which is why it is matched by id.
103
+ */
104
+ export declare function reviewThreadLines(comments: readonly RawComment[], rootId: string): RenderedLine[];
105
+ export declare const githubReadAdapter: {
106
+ platform: "github";
107
+ /**
108
+ * OPE-929 โ€” GitHub's own spelling of "which container and which thread is this turn in".
109
+ *
110
+ * The CONTAINER is the conversation key `owner/repo#number`, read off the binding's
111
+ * `anchorChannelId`: `bindGitHub` already mints it there through `githubConversationKey`, so this
112
+ * adds no second derivation. A turn with no conversation anchor (a supervisor seed, a degraded
113
+ * binding) reports none, and the caller refuses loudly rather than reading the repo's newest
114
+ * issue.
115
+ *
116
+ * The THREAD ROOT is present only on a REVIEW-THREAD turn โ€” an inline comment on a PR's diff.
117
+ * An issue comment and a PR TIMELINE comment are at the top level of their conversation, so they
118
+ * report no thread root and `read_thread` refuses them honestly. That is the same answer a
119
+ * base-channel Discord turn gets, and for the same reason.
120
+ */
121
+ wakeAddress(ctx: BindableContext): WakeReadAddress | undefined;
122
+ /**
123
+ * The issue-or-PR conversation: its opening post, then its newest timeline comments. `channel` is
124
+ * the container id โ€” see {@link parseGithubContainer}.
125
+ */
126
+ readChannel(ctx: BindableContext, channel: string, limit?: number, fetchFn?: PrFetchFn, walk?: ReadWalkSeam): Promise<AdapterReadFetch>;
127
+ /**
128
+ * One REVIEW THREAD on a PR โ€” the inline discussion `threadTs` roots. An issue has no review
129
+ * threads, so a read there comes back empty and the neutral render says so; it never invents a
130
+ * thread out of the timeline.
131
+ */
132
+ readThread(ctx: BindableContext, channel: string, threadTs: string, limit?: number, fetchFn?: PrFetchFn, walk?: ReadWalkSeam): Promise<AdapterReadFetch>;
133
+ };
134
+ export {};
135
+ //# sourceMappingURL=github-read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-read.d.ts","sourceRoot":"","sources":["../../../agent/channels/github-read.ts"],"names":[],"mappings":"AAmEA,OAAO,EAQL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,4CAA4C,CAAC;AAapD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAE1C;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAED;iGACiG;AACjG,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,GAAE,YAAiB,GAAG,WAAW,CAOlF;AAED,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,iGAAiG;IACjG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8BAA8B;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAWnF;AAED;+CAC+C;AAC/C;;4FAE4F;AAC5F,eAAO,MAAM,mBAAmB,EAAkC,SAAS,CAAC;AAE5E;;;;;;;;;;;;GAYG;AACH,wBAAsB,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAInI;AAED,kFAAkF;AAClF,UAAU,aAAa;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AASD,UAAU,UAAU;IAClB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzC;AAqJD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,SAAS,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE,CAGjG;AAED,eAAO,MAAM,iBAAiB;IAC5B,QAAQ,EAAE,QAAQ;IAClB;;;;;;;;;;;;;OAaG;IACH,WAAW,MAAM,eAAe,GAAG,eAAe,GAAG,SAAS;IAM9D;;;OAGG;IACG,WAAW,MACV,eAAe,WACX,MAAM,UACP,MAAM,YACL,SAAS,SACZ,YAAY,GACjB,OAAO,CAAC,gBAAgB,CAAC;IAqB5B;;;;OAIG;IACG,UAAU,MACT,eAAe,WACX,MAAM,YACL,MAAM,UACR,MAAM,YACL,SAAS,SACZ,YAAY,GACjB,OAAO,CAAC,gBAAgB,CAAC;CAmB7B,CAAC"}