iterate 0.2.6 → 0.3.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 (218) hide show
  1. package/README.md +86 -76
  2. package/THIRD_PARTY_NOTICES.md +55 -0
  3. package/bin/iterate.js +18 -3
  4. package/dist/api-url-B6404M82.mjs +17 -0
  5. package/dist/api-url-B6404M82.mjs.map +1 -0
  6. package/dist/app-ref-BipL0feU.mjs +35 -0
  7. package/dist/app-ref-BipL0feU.mjs.map +1 -0
  8. package/dist/app-ref-C1CrgXqX.mjs +7 -0
  9. package/dist/app-ref-C1CrgXqX.mjs.map +1 -0
  10. package/dist/app-ref-DYai_om1.mjs +7 -0
  11. package/dist/app-ref-DYai_om1.mjs.map +1 -0
  12. package/dist/cli-D0c-pDL_.mjs +1010 -0
  13. package/dist/cli-D0c-pDL_.mjs.map +1 -0
  14. package/dist/client.d.ts +3 -0
  15. package/dist/client.mjs +4 -0
  16. package/dist/cloudflare-BTm90gQ4.mjs +951 -0
  17. package/dist/cloudflare-BTm90gQ4.mjs.map +1 -0
  18. package/dist/contract-s4FW4eES.mjs +309 -0
  19. package/dist/contract-s4FW4eES.mjs.map +1 -0
  20. package/dist/document-review/index.d.ts +5 -0
  21. package/dist/document-review/types.d.ts +107 -0
  22. package/dist/document-review.mjs +7015 -0
  23. package/dist/document-review.mjs.map +1 -0
  24. package/dist/durable-object-processor-durability-CNsTjAJS.mjs +205 -0
  25. package/dist/durable-object-processor-durability-CNsTjAJS.mjs.map +1 -0
  26. package/dist/idempotency-DleloJNt.mjs +28 -0
  27. package/dist/idempotency-DleloJNt.mjs.map +1 -0
  28. package/dist/index.mjs +1 -1
  29. package/dist/itx/api-url.d.ts +6 -0
  30. package/dist/itx/itx-node-client.d.ts +65 -0
  31. package/dist/itx/itx-session.d.ts +215 -0
  32. package/dist/itx/owned-rpc-session.d.ts +14 -0
  33. package/dist/itx/query-client.d.ts +10 -0
  34. package/dist/itx-api.generated.d.ts +6195 -0
  35. package/dist/itx-session-sjud8GiT.mjs +534 -0
  36. package/dist/itx-session-sjud8GiT.mjs.map +1 -0
  37. package/dist/live-state-BJNqOwFw.mjs +299 -0
  38. package/dist/live-state-BJNqOwFw.mjs.map +1 -0
  39. package/dist/next/api.d.ts +479 -0
  40. package/dist/next/api.mjs +0 -0
  41. package/dist/next/app-server.d.ts +44 -0
  42. package/dist/next/app-server.mjs +479 -0
  43. package/dist/next/app-server.mjs.map +1 -0
  44. package/dist/next/app-session.d.ts +49 -0
  45. package/dist/next/app-session.mjs +238 -0
  46. package/dist/next/app-session.mjs.map +1 -0
  47. package/dist/next/app.d.ts +29 -0
  48. package/dist/next/app.mjs +141 -0
  49. package/dist/next/app.mjs.map +1 -0
  50. package/dist/next/client/live-state.d.ts +63 -0
  51. package/dist/next/client/oauth.d.ts +12 -0
  52. package/dist/next/client/react.d.ts +109 -0
  53. package/dist/next/client/socket.d.ts +6 -0
  54. package/dist/next/client.mjs +156 -0
  55. package/dist/next/client.mjs.map +1 -0
  56. package/dist/next/expression.d.ts +146 -0
  57. package/dist/next/expression.mjs +399 -0
  58. package/dist/next/expression.mjs.map +1 -0
  59. package/dist/next/lib.d.ts +56 -0
  60. package/dist/next/lib.mjs +199 -0
  61. package/dist/next/lib.mjs.map +1 -0
  62. package/dist/next/oauth-scopes.d.ts +32 -0
  63. package/dist/next/oauth-scopes.mjs +40 -0
  64. package/dist/next/oauth-scopes.mjs.map +1 -0
  65. package/dist/next/oauth.mjs +29 -0
  66. package/dist/next/oauth.mjs.map +1 -0
  67. package/dist/next/principal.d.ts +64 -0
  68. package/dist/next/principal.mjs +98 -0
  69. package/dist/next/principal.mjs.map +1 -0
  70. package/dist/next/project-ingress.d.ts +37 -0
  71. package/dist/next/project-ingress.mjs +75 -0
  72. package/dist/next/project-ingress.mjs.map +1 -0
  73. package/dist/next/react.mjs +285 -0
  74. package/dist/next/react.mjs.map +1 -0
  75. package/dist/next/sdk/auth.d.ts +5 -0
  76. package/dist/next/sdk/index.d.ts +112 -0
  77. package/dist/next/sdk.mjs +139 -0
  78. package/dist/next/sdk.mjs.map +1 -0
  79. package/dist/next/stream/processor.d.ts +378 -0
  80. package/dist/next/stream/processor.mjs +582 -0
  81. package/dist/next/stream/processor.mjs.map +1 -0
  82. package/dist/next/stream/run.d.ts +58 -0
  83. package/dist/next/stream/run.mjs +40 -0
  84. package/dist/next/stream/run.mjs.map +1 -0
  85. package/dist/next-node.d.ts +15 -0
  86. package/dist/next-node.mjs +51 -0
  87. package/dist/next-node.mjs.map +1 -0
  88. package/dist/node.d.ts +3 -0
  89. package/dist/node.mjs +185 -0
  90. package/dist/node.mjs.map +1 -0
  91. package/dist/processor-host-capabilities-BMFH3KTM.mjs +56 -0
  92. package/dist/processor-host-capabilities-BMFH3KTM.mjs.map +1 -0
  93. package/dist/processors/cloudflare.d.ts +3 -0
  94. package/dist/processors/durable-object-processor-durability.d.ts +79 -0
  95. package/dist/processors/event-consumption-metrics.d.ts +82 -0
  96. package/dist/processors/idempotency.d.ts +13 -0
  97. package/dist/processors/index.d.ts +12 -0
  98. package/dist/processors/processor-contracts.d.ts +342 -0
  99. package/dist/processors/processor-facet.d.ts +186 -0
  100. package/dist/processors/processor-host-capabilities.d.ts +60 -0
  101. package/dist/processors/prompt-sections.d.ts +17 -0
  102. package/dist/processors/rpc-types.d.ts +515 -0
  103. package/dist/processors/schemas.d.ts +102 -0
  104. package/dist/processors/stream-handle.d.ts +45 -0
  105. package/dist/processors/stream-processor-keepalive.d.ts +95 -0
  106. package/dist/processors/stream-processor-registry.d.ts +233 -0
  107. package/dist/processors/stream-processor-runner.d.ts +289 -0
  108. package/dist/processors/stream-processor.d.ts +339 -0
  109. package/dist/processors/stream-runtime-metrics.d.ts +107 -0
  110. package/dist/processors/testing.d.ts +302 -0
  111. package/dist/processors-BoNyeBfQ.mjs +10 -0
  112. package/dist/processors-BoNyeBfQ.mjs.map +1 -0
  113. package/dist/processors-cloudflare.mjs +3 -0
  114. package/dist/processors-testing.mjs +435 -0
  115. package/dist/processors-testing.mjs.map +1 -0
  116. package/dist/processors.mjs +52 -0
  117. package/dist/processors.mjs.map +1 -0
  118. package/dist/protocol-DnK_f2m6.mjs +251 -0
  119. package/dist/protocol-DnK_f2m6.mjs.map +1 -0
  120. package/dist/sdk/capnweb/index.d.ts +2 -0
  121. package/dist/sdk/capnweb/live-state/compact.d.ts +5 -0
  122. package/dist/sdk/capnweb/live-state/diff.d.ts +41 -0
  123. package/dist/sdk/capnweb/live-state/engine.d.ts +44 -0
  124. package/dist/sdk/capnweb/live-state/index.d.ts +41 -0
  125. package/dist/sdk/capnweb/live-state/protocol.d.ts +87 -0
  126. package/dist/sdk/capnweb/live-state/retain.d.ts +23 -0
  127. package/dist/sdk/capnweb/live-state/store.d.ts +20 -0
  128. package/dist/sdk/capnweb/live-state/types.d.ts +11 -0
  129. package/dist/sdk/capnweb/react.d.ts +45 -0
  130. package/dist/sdk/capnweb/react.mjs +316 -0
  131. package/dist/sdk/capnweb/react.mjs.map +1 -0
  132. package/dist/sdk/capnweb.mjs +4 -0
  133. package/dist/sdk/itx/react.d.ts +191 -0
  134. package/dist/sdk/itx/react.mjs +383 -0
  135. package/dist/sdk/itx/react.mjs.map +1 -0
  136. package/dist/sdk-DMB-IM11.mjs +933 -0
  137. package/dist/sdk-DMB-IM11.mjs.map +1 -0
  138. package/dist/sdk.d.ts +339 -0
  139. package/dist/sdk.mjs +2 -0
  140. package/dist/serve-itx.d.ts +46 -0
  141. package/dist/starter-apps/flake-dashboard/app-ref.d.ts +31 -0
  142. package/dist/starter-apps/flake-dashboard/configured-worker.mjs +1055 -0
  143. package/dist/starter-apps/flake-dashboard/configured-worker.mjs.map +1 -0
  144. package/dist/starter-apps/flake-dashboard/contract.d.ts +4839 -0
  145. package/dist/starter-apps/flake-dashboard/contract.mjs +2 -0
  146. package/dist/starter-apps/flake-dashboard/index.d.ts +17 -0
  147. package/dist/starter-apps/flake-dashboard/index.mjs +56 -0
  148. package/dist/starter-apps/flake-dashboard/index.mjs.map +1 -0
  149. package/dist/starter-apps/flake-dashboard/worker.d.ts +4607 -0
  150. package/dist/starter-apps/github-ai-linter/ai-linter.d.ts +8914 -0
  151. package/dist/starter-apps/github-ai-linter/configured-worker.mjs +17987 -0
  152. package/dist/starter-apps/github-ai-linter/configured-worker.mjs.map +1 -0
  153. package/dist/starter-apps/github-ai-linter/contract.d.ts +9193 -0
  154. package/dist/starter-apps/github-ai-linter/index.d.ts +10 -0
  155. package/dist/starter-apps/github-ai-linter/index.mjs +36 -0
  156. package/dist/starter-apps/github-ai-linter/index.mjs.map +1 -0
  157. package/dist/starter-apps/github-ai-linter/prompt.d.ts +13 -0
  158. package/dist/starter-apps/github-ai-linter/review-bot.d.ts +808 -0
  159. package/dist/starter-apps/github-ai-linter/rules.d.ts +34 -0
  160. package/dist/starter-apps/github-ai-linter/worker-ref.d.ts +19 -0
  161. package/dist/starter-apps/github-ai-linter/worker.d.ts +19 -0
  162. package/dist/starter-apps/github-ai-linter/worker.mjs +947 -0
  163. package/dist/starter-apps/github-ai-linter/worker.mjs.map +1 -0
  164. package/dist/starter-apps/guestbook/app-ref.d.ts +27 -0
  165. package/dist/starter-apps/guestbook/client.d.ts +7 -0
  166. package/dist/starter-apps/guestbook/client.mjs +59 -0
  167. package/dist/starter-apps/guestbook/configured-worker.mjs +205 -0
  168. package/dist/starter-apps/guestbook/configured-worker.mjs.map +1 -0
  169. package/dist/starter-apps/guestbook/index.d.ts +9 -0
  170. package/dist/starter-apps/guestbook/index.mjs +31 -0
  171. package/dist/starter-apps/guestbook/index.mjs.map +1 -0
  172. package/dist/starter-apps/guestbook/processor.d.ts +2267 -0
  173. package/dist/starter-apps/guestbook/worker.d.ts +26 -0
  174. package/dist/starter-apps/guestbook/worker.mjs +191 -0
  175. package/dist/starter-apps/guestbook/worker.mjs.map +1 -0
  176. package/dist/starter-apps/media/configured-worker.mjs +577 -0
  177. package/dist/starter-apps/media/configured-worker.mjs.map +1 -0
  178. package/dist/starter-apps/media/index.mjs +36 -0
  179. package/dist/starter-apps/media/index.mjs.map +1 -0
  180. package/dist/starter-apps/media/ref.mjs +20 -0
  181. package/dist/starter-apps/media/ref.mjs.map +1 -0
  182. package/dist/starter-apps/media/worker.mjs +579 -0
  183. package/dist/starter-apps/media/worker.mjs.map +1 -0
  184. package/dist/starter-apps/notes/configured-worker.mjs +6134 -0
  185. package/dist/starter-apps/notes/configured-worker.mjs.map +1 -0
  186. package/dist/starter-apps/notes/index.mjs +23 -0
  187. package/dist/starter-apps/notes/index.mjs.map +1 -0
  188. package/dist/starter-apps/notes/ref.mjs +21 -0
  189. package/dist/starter-apps/notes/ref.mjs.map +1 -0
  190. package/dist/starter-apps/notes/worker.mjs +427 -0
  191. package/dist/starter-apps/notes/worker.mjs.map +1 -0
  192. package/dist/starter-apps/todo/client.mjs +59 -0
  193. package/dist/starter-apps/todo/configured-worker.mjs +2864 -0
  194. package/dist/starter-apps/todo/configured-worker.mjs.map +1 -0
  195. package/dist/starter-apps/todo/index.d.ts +8 -0
  196. package/dist/starter-apps/todo/index.mjs +29 -0
  197. package/dist/starter-apps/todo/index.mjs.map +1 -0
  198. package/dist/stream-processor-keepalive-DAQTP6m3.mjs +2082 -0
  199. package/dist/stream-processor-keepalive-DAQTP6m3.mjs.map +1 -0
  200. package/dist/usingCtx-inzbY1Qz.mjs +57 -0
  201. package/dist/usingCtx-mZx5nsAW.mjs +11800 -0
  202. package/dist/usingCtx-mZx5nsAW.mjs.map +1 -0
  203. package/dist/worker-ref-DZxPDmb_.mjs +390 -0
  204. package/dist/worker-ref-DZxPDmb_.mjs.map +1 -0
  205. package/menubar/Iterate.entitlements +12 -0
  206. package/menubar/Iterate.swift +914 -0
  207. package/menubar/IterateIcon.swift +145 -0
  208. package/menubar/README.md +28 -0
  209. package/menubar/build-menubar-app.sh +59 -0
  210. package/package.json +235 -18
  211. package/dist/cli-DMS4kJph.mjs +0 -868
  212. package/dist/cli-DMS4kJph.mjs.map +0 -1
  213. package/dist/config-DtnR7Lv7.mjs +0 -170
  214. package/dist/config-DtnR7Lv7.mjs.map +0 -1
  215. package/dist/index.d.mts.map +0 -1
  216. package/dist/stream-tui/agent-chat-terminal.d.mts +0 -1
  217. package/dist/stream-tui/agent-chat-terminal.mjs +0 -933
  218. package/dist/stream-tui/agent-chat-terminal.mjs.map +0 -1
@@ -0,0 +1,390 @@
1
+ import { h as defineProcessorContract } from "./stream-processor-keepalive-DAQTP6m3.mjs";
2
+ import "./processors.mjs";
3
+ import { z } from "zod";
4
+ //#region src/starter-apps/github-ai-linter/contract.ts
5
+ /**
6
+ * Keep the vocabulary flat. These names are also copied into the linter
7
+ * agent's developer task, so changing one here deliberately breaks an old
8
+ * prompt instead of leaving two almost-compatible protocols alive.
9
+ *
10
+ * The const assertion preserves exact event literals for contract typing. It
11
+ * is safe because this object is static vocabulary and is never mutated.
12
+ */
13
+ const githubAiLinterEventTypes = {
14
+ analysisRequested: "events.iterate.com/github-ai-linter/analysis-requested",
15
+ diagnosticReported: "events.iterate.com/github-ai-linter/diagnostic-reported",
16
+ diagnosticSuppressed: "events.iterate.com/github-ai-linter/diagnostic-suppressed",
17
+ analysisSettled: "events.iterate.com/github-ai-linter/analysis-settled",
18
+ reviewPublicationRequested: "events.iterate.com/github-ai-linter/review-publication-requested",
19
+ reviewPublicationSettled: "events.iterate.com/github-ai-linter/review-publication-settled"
20
+ };
21
+ const PositiveSafeInteger = z.number().int().positive().max(Number.MAX_SAFE_INTEGER);
22
+ const StreamOffset = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
23
+ const RuleName = z.string().regex(/^[a-z0-9-]+(?:\/[a-z0-9-]+)*$/);
24
+ const GithubAiLinterRule = z.object({
25
+ files: z.array(z.string().min(1)).min(1),
26
+ invariant: z.string().min(1),
27
+ severity: z.enum(["error", "warning"]),
28
+ suggestions: z.enum(["allowed", "forbidden"]).default("allowed")
29
+ });
30
+ const GithubAiLinterAnalysisRequested = z.object({
31
+ appSlug: z.string().min(1),
32
+ baseSha: z.string().min(1),
33
+ connection: z.string().min(1),
34
+ headSha: z.string().min(1),
35
+ policyVersion: z.string().min(1),
36
+ promptVersion: z.string().min(1),
37
+ pullRequestNumber: PositiveSafeInteger,
38
+ repository: z.object({
39
+ id: PositiveSafeInteger,
40
+ owner: z.string().min(1),
41
+ repo: z.string().min(1)
42
+ }),
43
+ rules: z.record(RuleName, GithubAiLinterRule),
44
+ rulesCommit: z.string().min(1)
45
+ });
46
+ const SourceSpanSchema = z.object({
47
+ endColumn: PositiveSafeInteger.optional(),
48
+ endLine: PositiveSafeInteger,
49
+ startColumn: PositiveSafeInteger.optional(),
50
+ startLine: PositiveSafeInteger
51
+ }).refine(({ endLine, startLine }) => endLine >= startLine, "a source span must end on or after its start line");
52
+ const WholeLineSpanSchema = z.object({
53
+ endLine: PositiveSafeInteger,
54
+ startLine: PositiveSafeInteger
55
+ }).refine(({ endLine, startLine }) => endLine >= startLine, "a source span must end on or after its start line");
56
+ const GithubAiLinterDiagnostic = z.object({
57
+ /**
58
+ * Cross-analysis identity. Unlike the GitHub line, this should survive
59
+ * nearby edits: rule + filename + a short semantic anchor is the intended
60
+ * input. The prompt explicitly forbids line numbers and prose here.
61
+ */
62
+ diagnosticKey: z.string().min(1).max(500),
63
+ filename: z.string().min(1).max(2e3),
64
+ fix: z.object({
65
+ content: z.string().max(5e4),
66
+ /**
67
+ * The first slice only publishes human-applied GitHub suggestions.
68
+ * A future `fix` kind may authorize an automated branch update, but it
69
+ * must be a separate explicit protocol: never reinterpret an archived
70
+ * suggestion as permission to mutate code.
71
+ */
72
+ kind: z.literal("suggestion"),
73
+ span: WholeLineSpanSchema
74
+ }).optional(),
75
+ help: z.string().min(1).max(8e3).optional(),
76
+ /**
77
+ * Oxlint diagnostics can carry several labels. The first label is the
78
+ * primary one and supplies GitHub's inline location in this first version;
79
+ * later labels remain structured context for a richer renderer.
80
+ */
81
+ labels: z.array(z.object({
82
+ message: z.string().min(1).max(4e3).optional(),
83
+ span: SourceSpanSchema
84
+ })).min(1).max(20),
85
+ message: z.string().min(1).max(8e3),
86
+ ruleName: RuleName,
87
+ severity: z.enum(["error", "warning"])
88
+ });
89
+ const GithubAiLinterDiagnosticReportedPayload = GithubAiLinterDiagnostic.extend({ analysisRequestOffset: StreamOffset });
90
+ const GithubAiLinterDiagnosticSuppressedPayload = z.object({
91
+ analysisRequestOffset: StreamOffset,
92
+ diagnosticOffset: StreamOffset,
93
+ directive: z.enum([
94
+ "disable",
95
+ "disable-line",
96
+ "disable-next-line"
97
+ ]),
98
+ filename: z.string().min(1).max(2e3),
99
+ line: PositiveSafeInteger,
100
+ reason: z.string().min(1).max(4e3)
101
+ });
102
+ const GithubAiLinterAssessment = z.object({
103
+ summary: z.string().min(1).max(2e4),
104
+ verdict: z.enum([
105
+ "approve",
106
+ "comment",
107
+ "request-changes"
108
+ ])
109
+ });
110
+ const GithubAiLinterAnalysisResult = z.discriminatedUnion("status", [
111
+ z.object({
112
+ assessment: GithubAiLinterAssessment,
113
+ status: z.literal("succeeded")
114
+ }),
115
+ z.object({
116
+ reason: z.string().min(1).max(8e3),
117
+ status: z.literal("cancelled")
118
+ }),
119
+ z.object({
120
+ error: z.string().min(1).max(8e3),
121
+ status: z.literal("failed")
122
+ })
123
+ ]);
124
+ const GithubAiLinterAnalysisSettledPayload = z.object({
125
+ analysisRequestOffset: StreamOffset,
126
+ result: GithubAiLinterAnalysisResult
127
+ });
128
+ const PublishedCheckRun = z.object({
129
+ id: PositiveSafeInteger,
130
+ url: z.string().url()
131
+ });
132
+ const GithubAiLinterPublicationResult = z.discriminatedUnion("status", [
133
+ z.object({
134
+ checkRun: PublishedCheckRun,
135
+ reason: z.string().min(1).max(8e3),
136
+ status: z.literal("skipped")
137
+ }),
138
+ z.object({
139
+ checkRun: PublishedCheckRun.optional(),
140
+ reviewId: PositiveSafeInteger,
141
+ reviewUrl: z.string().url(),
142
+ status: z.literal("succeeded")
143
+ }),
144
+ z.object({
145
+ reason: z.string().min(1).max(8e3),
146
+ status: z.literal("cancelled")
147
+ }),
148
+ z.object({
149
+ error: z.string().min(1).max(8e3),
150
+ status: z.literal("failed")
151
+ })
152
+ ]);
153
+ const PublicationState = z.discriminatedUnion("status", [
154
+ z.object({ status: z.literal("not-requested") }),
155
+ z.object({ status: z.literal("requested") }),
156
+ ...GithubAiLinterPublicationResult.options
157
+ ]);
158
+ const ReducedDiagnostic = z.object({
159
+ classification: z.enum([
160
+ "new",
161
+ "persistent",
162
+ "reintroduced"
163
+ ]).nullable(),
164
+ diagnostic: GithubAiLinterDiagnostic,
165
+ eventOffset: StreamOffset,
166
+ suppression: GithubAiLinterDiagnosticSuppressedPayload.nullable()
167
+ });
168
+ const AnalysisSummary = z.object({
169
+ analysisRequestOffset: StreamOffset,
170
+ baseSha: z.string().min(1),
171
+ diagnosticCount: z.number().int().nonnegative(),
172
+ headSha: z.string().min(1),
173
+ publication: PublicationState,
174
+ rulesCommit: z.string().min(1),
175
+ status: z.enum([
176
+ "running",
177
+ "succeeded",
178
+ "cancelled",
179
+ "failed"
180
+ ]),
181
+ suppressedDiagnosticCount: z.number().int().nonnegative()
182
+ });
183
+ const MaterializedAnalysis = z.object({
184
+ analysisRequestOffset: StreamOffset,
185
+ assessment: GithubAiLinterAssessment,
186
+ diagnostics: z.array(ReducedDiagnostic),
187
+ request: GithubAiLinterAnalysisRequested,
188
+ resolvedDiagnostics: z.array(GithubAiLinterDiagnostic)
189
+ });
190
+ const ActiveAnalysis = z.object({
191
+ /**
192
+ * There is deliberately no wall-clock expiry in the first slice. New pushes
193
+ * cancel old work, while the Agent processor's autonomous-turn breaker
194
+ * explicitly fails an analysis which cannot finish within its configured
195
+ * budget. A future time limit should likewise be a typed processor-authored
196
+ * settlement event driven by a durable alarm, not an implicit timestamp
197
+ * check that silently changes reduced state.
198
+ */
199
+ analysisRequestOffset: StreamOffset,
200
+ diagnostics: z.array(ReducedDiagnostic),
201
+ request: GithubAiLinterAnalysisRequested
202
+ });
203
+ const GithubAiLinterProcessorContract = defineProcessorContract({
204
+ slug: "github-ai-linter",
205
+ version: "0.4.0",
206
+ description: "Reduces one pull request's AI diagnostics and mechanically publishes its GitHub Check Run and optional advisory review.",
207
+ stateSchema: z.object({
208
+ /**
209
+ * These are intentionally lightweight headers, not copies of every prompt
210
+ * and diagnostic. The stream remains the canonical full history. If a PR
211
+ * eventually accumulates enough pushes for even these headers to matter,
212
+ * move cold headers to a paged read model rather than retaining full
213
+ * diagnostics in Durable Object state.
214
+ */
215
+ analyses: z.array(AnalysisSummary).default([]),
216
+ currentAnalysis: ActiveAnalysis.nullable().default(null),
217
+ latestSuccessfulAnalysis: MaterializedAnalysis.nullable().default(null),
218
+ /**
219
+ * This small semantic-key index is what lets a later result distinguish
220
+ * "new" from "reintroduced." A production-scale rule engine should replace
221
+ * it with a compact/bounded index; the event history already contains the
222
+ * authoritative data needed to rebuild one.
223
+ */
224
+ seenDiagnosticKeys: z.array(z.string()).default([])
225
+ }),
226
+ events: {
227
+ [githubAiLinterEventTypes.analysisRequested]: {
228
+ description: "Pins one pull-request head and immutable rules snapshot for analysis.",
229
+ payloadSchema: GithubAiLinterAnalysisRequested
230
+ },
231
+ [githubAiLinterEventTypes.diagnosticReported]: {
232
+ description: "One Oxlint-shaped diagnostic reported by the analysis agent.",
233
+ payloadSchema: GithubAiLinterDiagnosticReportedPayload
234
+ },
235
+ [githubAiLinterEventTypes.diagnosticSuppressed]: {
236
+ description: "Records that a source directive suppresses one reported diagnostic.",
237
+ payloadSchema: GithubAiLinterDiagnosticSuppressedPayload
238
+ },
239
+ [githubAiLinterEventTypes.analysisSettled]: {
240
+ description: "The sole terminal fact for an analysis request.",
241
+ payloadSchema: GithubAiLinterAnalysisSettledPayload
242
+ },
243
+ [githubAiLinterEventTypes.reviewPublicationRequested]: {
244
+ description: "Opens the durable obligation to publish one GitHub Check Run and, for findings, one immutable non-blocking review.",
245
+ payloadSchema: z.object({ analysisRequestOffset: StreamOffset })
246
+ },
247
+ [githubAiLinterEventTypes.reviewPublicationSettled]: {
248
+ description: "Records the terminal GitHub Check Run and review publication result.",
249
+ payloadSchema: z.object({
250
+ analysisRequestOffset: StreamOffset,
251
+ result: GithubAiLinterPublicationResult
252
+ })
253
+ }
254
+ },
255
+ processorDeps: [{ "events.iterate.com/agent/paused": {
256
+ description: "The generic Agent processor paused its autonomous turn loop.",
257
+ payloadSchema: z.object({
258
+ reason: z.string().optional(),
259
+ triggerOffset: StreamOffset.optional()
260
+ })
261
+ } }],
262
+ consumes: [...Object.values(githubAiLinterEventTypes), "events.iterate.com/agent/paused"],
263
+ emits: [
264
+ githubAiLinterEventTypes.analysisSettled,
265
+ githubAiLinterEventTypes.reviewPublicationRequested,
266
+ githubAiLinterEventTypes.reviewPublicationSettled
267
+ ]
268
+ });
269
+ //#endregion
270
+ //#region src/starter-apps/github-ai-linter/worker-ref.ts
271
+ const configuredWorkerEntrypoint = "node_modules/iterate/dist/starter-apps/github-ai-linter/configured-worker.mjs";
272
+ const REVIEW_BOT_SUBSCRIPTION_NAME = "review-bot";
273
+ const REVIEW_BOT_RELEVANT_WEBHOOK_CONDITION = [
274
+ "(payload.delivery.name = \"pull_request\" and",
275
+ "(payload.body.action = \"opened\" or",
276
+ "payload.body.action = \"ready_for_review\" or",
277
+ "payload.body.action = \"synchronize\"))",
278
+ "or",
279
+ "((payload.delivery.name = \"issue_comment\" or",
280
+ "payload.delivery.name = \"pull_request_review\" or",
281
+ "payload.delivery.name = \"pull_request_review_comment\") and",
282
+ "$count(payload.associations.mentionedUsers) > 0)"
283
+ ].join(" ");
284
+ /**
285
+ * The review router only needs lifecycle deliveries and explicit mentions.
286
+ * Filtering on the source stream keeps check/workflow webhook bursts out of
287
+ * the hosted processor while the offset prefix preserves the restore cutoff.
288
+ */
289
+ function reviewBotSubscriptionCondition(startAfterOffset) {
290
+ return `offset > ${startAfterOffset} and (${REVIEW_BOT_RELEVANT_WEBHOOK_CONDITION})`;
291
+ }
292
+ async function reviewBotSubscriptionEvent(sourceEvent, connection, config, startAfterOffset) {
293
+ return {
294
+ type: "events.iterate.com/stream/subscription-configured",
295
+ payload: {
296
+ name: REVIEW_BOT_SUBSCRIPTION_NAME,
297
+ filter: {
298
+ eventTypes: ["events.iterate.com/github/webhook-received"],
299
+ jsonataCondition: reviewBotSubscriptionCondition(startAfterOffset)
300
+ },
301
+ receiver: {
302
+ action: "wake-processor",
303
+ expression: [
304
+ "workers",
305
+ ["get", await reviewBotAppRef(connection, config)],
306
+ "processor",
307
+ "wakeStreamProcessor"
308
+ ]
309
+ }
310
+ },
311
+ idempotencyKey: `review-bot/subscription:${sourceEvent.path}:${sourceEvent.offset}`
312
+ };
313
+ }
314
+ async function pullRequestLinterSubscriptionEvent(input, config) {
315
+ return {
316
+ type: "events.iterate.com/stream/subscription-configured",
317
+ payload: {
318
+ name: "github-ai-linter",
319
+ filter: { eventTypes: GithubAiLinterProcessorContract.consumes },
320
+ receiver: {
321
+ action: "wake-processor",
322
+ expression: [
323
+ "workers",
324
+ ["get", await pullRequestLinterAppRef(input, config)],
325
+ "processor",
326
+ "wakeStreamProcessor"
327
+ ]
328
+ }
329
+ },
330
+ idempotencyKey: [
331
+ "github-ai-linter/subscription",
332
+ input.connection,
333
+ input.repositoryId,
334
+ input.pullRequestNumber,
335
+ `policy:${config.policyVersion}`,
336
+ "delivery:2",
337
+ `stream:${input.streamPath}`
338
+ ].join(":")
339
+ };
340
+ }
341
+ async function reviewBotAppRef(connection, config) {
342
+ return dynamicWorkerRef({
343
+ className: "ReviewBotApp",
344
+ config,
345
+ durableWorkerKey: `github-ai-linter-review-bot-${await durableIdentity(connection)}`
346
+ });
347
+ }
348
+ async function pullRequestLinterAppRef(input, config) {
349
+ return dynamicWorkerRef({
350
+ className: "GithubAiLinterApp",
351
+ config,
352
+ durableWorkerKey: `app-gh-linter-${await durableIdentity([
353
+ input.connection,
354
+ String(input.repositoryId),
355
+ String(input.pullRequestNumber),
356
+ input.streamPath
357
+ ].join("\0"))}`
358
+ });
359
+ }
360
+ function dynamicWorkerRef(input) {
361
+ return {
362
+ type: "stateful",
363
+ path: "/",
364
+ className: input.className,
365
+ durableWorkerKey: input.durableWorkerKey,
366
+ source: { createWorker: {
367
+ entryPoint: configuredWorkerEntrypoint,
368
+ files: {
369
+ type: "repo",
370
+ repoPath: "/repos/config",
371
+ include: ["package.json"]
372
+ },
373
+ minify: true,
374
+ virtualModules: { "iterate:github-ai-linter-config": `export default ${JSON.stringify(input.config)};` }
375
+ } }
376
+ };
377
+ }
378
+ /**
379
+ * Dynamic-worker durable keys have a 63-character ceiling and connection
380
+ * slugs are user-controlled. A truncated SHA-256 preserves stable identity
381
+ * without leaking or squeezing arbitrary coordinates into that limit.
382
+ */
383
+ async function durableIdentity(value) {
384
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
385
+ return [...new Uint8Array(digest).slice(0, 16)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
386
+ }
387
+ //#endregion
388
+ export { githubAiLinterEventTypes as a, GithubAiLinterProcessorContract as i, pullRequestLinterSubscriptionEvent as n, reviewBotSubscriptionEvent as r, REVIEW_BOT_SUBSCRIPTION_NAME as t };
389
+
390
+ //# sourceMappingURL=worker-ref-DZxPDmb_.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-ref-DZxPDmb_.mjs","names":[],"sources":["../src/starter-apps/github-ai-linter/contract.ts","../src/starter-apps/github-ai-linter/worker-ref.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { defineProcessorContract } from \"../../processors/index.ts\";\n\n/**\n * Keep the vocabulary flat. These names are also copied into the linter\n * agent's developer task, so changing one here deliberately breaks an old\n * prompt instead of leaving two almost-compatible protocols alive.\n *\n * The const assertion preserves exact event literals for contract typing. It\n * is safe because this object is static vocabulary and is never mutated.\n */\nexport const githubAiLinterEventTypes = {\n analysisRequested: \"events.iterate.com/github-ai-linter/analysis-requested\",\n diagnosticReported: \"events.iterate.com/github-ai-linter/diagnostic-reported\",\n diagnosticSuppressed: \"events.iterate.com/github-ai-linter/diagnostic-suppressed\",\n analysisSettled: \"events.iterate.com/github-ai-linter/analysis-settled\",\n reviewPublicationRequested: \"events.iterate.com/github-ai-linter/review-publication-requested\",\n reviewPublicationSettled: \"events.iterate.com/github-ai-linter/review-publication-settled\",\n} as const;\n\nconst PositiveSafeInteger = z.number().int().positive().max(Number.MAX_SAFE_INTEGER);\n// Stream offset zero is the valid \"before the first event\" coordinate in the\n// processor APIs. Keeping it distinct from GitHub IDs and source lines avoids\n// accidentally rejecting a request simply because it was the stream's first\n// committed event.\nconst StreamOffset = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);\nconst RuleName = z.string().regex(/^[a-z0-9-]+(?:\\/[a-z0-9-]+)*$/);\n\nconst GithubAiLinterRule = z.object({\n files: z.array(z.string().min(1)).min(1),\n invariant: z.string().min(1),\n severity: z.enum([\"error\", \"warning\"]),\n suggestions: z.enum([\"allowed\", \"forbidden\"]).default(\"allowed\"),\n});\n\nexport const GithubAiLinterAnalysisRequested = z.object({\n appSlug: z.string().min(1),\n baseSha: z.string().min(1),\n connection: z.string().min(1),\n headSha: z.string().min(1),\n policyVersion: z.string().min(1),\n promptVersion: z.string().min(1),\n pullRequestNumber: PositiveSafeInteger,\n repository: z.object({\n id: PositiveSafeInteger,\n owner: z.string().min(1),\n repo: z.string().min(1),\n }),\n rules: z.record(RuleName, GithubAiLinterRule),\n rulesCommit: z.string().min(1),\n});\n\nconst SourceSpanSchema = z\n .object({\n endColumn: PositiveSafeInteger.optional(),\n endLine: PositiveSafeInteger,\n startColumn: PositiveSafeInteger.optional(),\n startLine: PositiveSafeInteger,\n })\n .refine(\n ({ endLine, startLine }) => endLine >= startLine,\n \"a source span must end on or after its start line\",\n );\nconst WholeLineSpanSchema = z\n .object({\n endLine: PositiveSafeInteger,\n startLine: PositiveSafeInteger,\n })\n .refine(\n ({ endLine, startLine }) => endLine >= startLine,\n \"a source span must end on or after its start line\",\n );\n\nconst GithubAiLinterDiagnostic = z.object({\n /**\n * Cross-analysis identity. Unlike the GitHub line, this should survive\n * nearby edits: rule + filename + a short semantic anchor is the intended\n * input. The prompt explicitly forbids line numbers and prose here.\n */\n diagnosticKey: z.string().min(1).max(500),\n filename: z.string().min(1).max(2_000),\n fix: z\n .object({\n content: z.string().max(50_000),\n /**\n * The first slice only publishes human-applied GitHub suggestions.\n * A future `fix` kind may authorize an automated branch update, but it\n * must be a separate explicit protocol: never reinterpret an archived\n * suggestion as permission to mutate code.\n */\n kind: z.literal(\"suggestion\"),\n span: WholeLineSpanSchema,\n })\n .optional(),\n help: z.string().min(1).max(8_000).optional(),\n /**\n * Oxlint diagnostics can carry several labels. The first label is the\n * primary one and supplies GitHub's inline location in this first version;\n * later labels remain structured context for a richer renderer.\n */\n labels: z\n .array(\n z.object({\n message: z.string().min(1).max(4_000).optional(),\n span: SourceSpanSchema,\n }),\n )\n .min(1)\n .max(20),\n message: z.string().min(1).max(8_000),\n ruleName: RuleName,\n severity: z.enum([\"error\", \"warning\"]),\n});\n\nconst GithubAiLinterDiagnosticReportedPayload = GithubAiLinterDiagnostic.extend({\n analysisRequestOffset: StreamOffset,\n});\n\nconst GithubAiLinterDiagnosticSuppressedPayload = z.object({\n analysisRequestOffset: StreamOffset,\n diagnosticOffset: StreamOffset,\n directive: z.enum([\"disable\", \"disable-line\", \"disable-next-line\"]),\n filename: z.string().min(1).max(2_000),\n line: PositiveSafeInteger,\n reason: z.string().min(1).max(4_000),\n});\n\nconst GithubAiLinterAssessment = z.object({\n summary: z.string().min(1).max(20_000),\n verdict: z.enum([\"approve\", \"comment\", \"request-changes\"]),\n});\n\nconst GithubAiLinterAnalysisResult = z.discriminatedUnion(\"status\", [\n z.object({\n assessment: GithubAiLinterAssessment,\n status: z.literal(\"succeeded\"),\n }),\n z.object({\n reason: z.string().min(1).max(8_000),\n status: z.literal(\"cancelled\"),\n }),\n z.object({\n error: z.string().min(1).max(8_000),\n status: z.literal(\"failed\"),\n }),\n]);\n\nconst GithubAiLinterAnalysisSettledPayload = z.object({\n analysisRequestOffset: StreamOffset,\n result: GithubAiLinterAnalysisResult,\n});\n\nconst PublishedCheckRun = z.object({\n id: PositiveSafeInteger,\n url: z.string().url(),\n});\n\nexport const GithubAiLinterPublicationResult = z.discriminatedUnion(\"status\", [\n z.object({\n checkRun: PublishedCheckRun,\n reason: z.string().min(1).max(8_000),\n status: z.literal(\"skipped\"),\n }),\n z.object({\n // Optional only for replay compatibility with successful publication\n // events written before the linter began publishing Check Runs.\n checkRun: PublishedCheckRun.optional(),\n reviewId: PositiveSafeInteger,\n reviewUrl: z.string().url(),\n status: z.literal(\"succeeded\"),\n }),\n z.object({\n reason: z.string().min(1).max(8_000),\n status: z.literal(\"cancelled\"),\n }),\n z.object({\n error: z.string().min(1).max(8_000),\n status: z.literal(\"failed\"),\n }),\n]);\n\nconst PublicationState = z.discriminatedUnion(\"status\", [\n z.object({ status: z.literal(\"not-requested\") }),\n z.object({ status: z.literal(\"requested\") }),\n ...GithubAiLinterPublicationResult.options,\n]);\n\nconst ReducedDiagnostic = z.object({\n classification: z.enum([\"new\", \"persistent\", \"reintroduced\"]).nullable(),\n diagnostic: GithubAiLinterDiagnostic,\n eventOffset: StreamOffset,\n suppression: GithubAiLinterDiagnosticSuppressedPayload.nullable(),\n});\n\nconst AnalysisSummary = z.object({\n analysisRequestOffset: StreamOffset,\n baseSha: z.string().min(1),\n diagnosticCount: z.number().int().nonnegative(),\n headSha: z.string().min(1),\n publication: PublicationState,\n rulesCommit: z.string().min(1),\n status: z.enum([\"running\", \"succeeded\", \"cancelled\", \"failed\"]),\n suppressedDiagnosticCount: z.number().int().nonnegative(),\n});\n\nconst MaterializedAnalysis = z.object({\n analysisRequestOffset: StreamOffset,\n assessment: GithubAiLinterAssessment,\n diagnostics: z.array(ReducedDiagnostic),\n request: GithubAiLinterAnalysisRequested,\n resolvedDiagnostics: z.array(GithubAiLinterDiagnostic),\n});\n\nconst ActiveAnalysis = z.object({\n /**\n * There is deliberately no wall-clock expiry in the first slice. New pushes\n * cancel old work, while the Agent processor's autonomous-turn breaker\n * explicitly fails an analysis which cannot finish within its configured\n * budget. A future time limit should likewise be a typed processor-authored\n * settlement event driven by a durable alarm, not an implicit timestamp\n * check that silently changes reduced state.\n */\n analysisRequestOffset: StreamOffset,\n diagnostics: z.array(ReducedDiagnostic),\n request: GithubAiLinterAnalysisRequested,\n});\n\nexport const GithubAiLinterState = z.object({\n /**\n * These are intentionally lightweight headers, not copies of every prompt\n * and diagnostic. The stream remains the canonical full history. If a PR\n * eventually accumulates enough pushes for even these headers to matter,\n * move cold headers to a paged read model rather than retaining full\n * diagnostics in Durable Object state.\n */\n analyses: z.array(AnalysisSummary).default([]),\n currentAnalysis: ActiveAnalysis.nullable().default(null),\n latestSuccessfulAnalysis: MaterializedAnalysis.nullable().default(null),\n /**\n * This small semantic-key index is what lets a later result distinguish\n * \"new\" from \"reintroduced.\" A production-scale rule engine should replace\n * it with a compact/bounded index; the event history already contains the\n * authoritative data needed to rebuild one.\n */\n seenDiagnosticKeys: z.array(z.string()).default([]),\n});\n\nexport const GithubAiLinterProcessorContract = defineProcessorContract({\n slug: \"github-ai-linter\",\n version: \"0.4.0\",\n description:\n \"Reduces one pull request's AI diagnostics and mechanically publishes its GitHub Check Run and optional advisory review.\",\n stateSchema: GithubAiLinterState,\n events: {\n [githubAiLinterEventTypes.analysisRequested]: {\n description: \"Pins one pull-request head and immutable rules snapshot for analysis.\",\n payloadSchema: GithubAiLinterAnalysisRequested,\n },\n [githubAiLinterEventTypes.diagnosticReported]: {\n description: \"One Oxlint-shaped diagnostic reported by the analysis agent.\",\n payloadSchema: GithubAiLinterDiagnosticReportedPayload,\n },\n [githubAiLinterEventTypes.diagnosticSuppressed]: {\n description: \"Records that a source directive suppresses one reported diagnostic.\",\n payloadSchema: GithubAiLinterDiagnosticSuppressedPayload,\n },\n [githubAiLinterEventTypes.analysisSettled]: {\n description: \"The sole terminal fact for an analysis request.\",\n payloadSchema: GithubAiLinterAnalysisSettledPayload,\n },\n [githubAiLinterEventTypes.reviewPublicationRequested]: {\n description:\n \"Opens the durable obligation to publish one GitHub Check Run and, for findings, one immutable non-blocking review.\",\n payloadSchema: z.object({ analysisRequestOffset: StreamOffset }),\n },\n [githubAiLinterEventTypes.reviewPublicationSettled]: {\n description: \"Records the terminal GitHub Check Run and review publication result.\",\n payloadSchema: z.object({\n analysisRequestOffset: StreamOffset,\n result: GithubAiLinterPublicationResult,\n }),\n },\n },\n // `agent/paused` is owned by the platform Agent contract. This userspace\n // processor consumes it only to turn an exhausted analysis into a durable\n // terminal fact instead of leaving it visibly `running`.\n processorDeps: [\n {\n \"events.iterate.com/agent/paused\": {\n description: \"The generic Agent processor paused its autonomous turn loop.\",\n payloadSchema: z.object({\n reason: z.string().optional(),\n triggerOffset: StreamOffset.optional(),\n }),\n },\n },\n ],\n consumes: [...Object.values(githubAiLinterEventTypes), \"events.iterate.com/agent/paused\"],\n // `diagnostic-reported` and `diagnostic-suppressed` are declared above and\n // consumed here, but are not processor emissions: the generic Agent appends\n // them with its ordinary stream capability. This list is deliberately only\n // the mechanical processor's own consequences.\n emits: [\n githubAiLinterEventTypes.analysisSettled,\n githubAiLinterEventTypes.reviewPublicationRequested,\n githubAiLinterEventTypes.reviewPublicationSettled,\n ],\n});\n\nexport type GithubAiLinterProcessorContract = typeof GithubAiLinterProcessorContract;\nexport type GithubAiLinterState = z.infer<typeof GithubAiLinterState>;\nexport type GithubAiLinterAnalysisRequested = z.infer<typeof GithubAiLinterAnalysisRequested>;\nexport type GithubAiLinterPublicationResult = z.infer<typeof GithubAiLinterPublicationResult>;\n","import type { StatefulDynamicWorkerRef, StreamEvent, StreamEventInput } from \"../../sdk.ts\";\nimport { GithubAiLinterProcessorContract } from \"./contract.ts\";\nimport type { GithubAiLinterRuleSource } from \"./rules.ts\";\n\nexport type GithubAiLinterConfig = {\n /**\n * Operators bump this when rule selection or policy meaning changes. It is\n * part of analysis identity, so an unchanged pull-request head is analysed\n * again instead of colliding with an older task.\n */\n policyVersion: string;\n rules: GithubAiLinterRuleSource;\n};\n\nconst configuredWorkerEntrypoint =\n \"node_modules/iterate/dist/starter-apps/github-ai-linter/configured-worker.mjs\";\n\n// Subscription names are opaque, source-local identities under the\n// subscription-model redesign — the old `app-…#slug` placement-encoding\n// convention is dead. Plain contract-slug names read as\n// `subscriptions.get(\"review-bot\")`.\nexport const REVIEW_BOT_SUBSCRIPTION_NAME = \"review-bot\";\n\nconst REVIEW_BOT_RELEVANT_WEBHOOK_CONDITION = [\n '(payload.delivery.name = \"pull_request\" and',\n '(payload.body.action = \"opened\" or',\n 'payload.body.action = \"ready_for_review\" or',\n 'payload.body.action = \"synchronize\"))',\n \"or\",\n '((payload.delivery.name = \"issue_comment\" or',\n 'payload.delivery.name = \"pull_request_review\" or',\n 'payload.delivery.name = \"pull_request_review_comment\") and',\n \"$count(payload.associations.mentionedUsers) > 0)\",\n].join(\" \");\n\n/**\n * The review router only needs lifecycle deliveries and explicit mentions.\n * Filtering on the source stream keeps check/workflow webhook bursts out of\n * the hosted processor while the offset prefix preserves the restore cutoff.\n */\nfunction reviewBotSubscriptionCondition(startAfterOffset: number) {\n return `offset > ${startAfterOffset} and (${REVIEW_BOT_RELEVANT_WEBHOOK_CONDITION})`;\n}\n\nexport async function reviewBotSubscriptionEvent(\n sourceEvent: StreamEvent,\n connection: string,\n config: GithubAiLinterConfig,\n startAfterOffset: number,\n): Promise<StreamEventInput> {\n return {\n type: \"events.iterate.com/stream/subscription-configured\",\n payload: {\n name: REVIEW_BOT_SUBSCRIPTION_NAME,\n // A restored connection stream can contain thousands of old webhooks.\n // This cutoff gives a newly configured review bot future work only.\n // Config refreshes preserve the original cutoff in index.ts.\n filter: {\n eventTypes: [\"events.iterate.com/github/webhook-received\"],\n jsonataCondition: reviewBotSubscriptionCondition(startAfterOffset),\n },\n receiver: {\n action: \"wake-processor\",\n expression: [\n \"workers\",\n [\"get\", await reviewBotAppRef(connection, config)],\n \"processor\",\n \"wakeStreamProcessor\",\n ],\n },\n },\n idempotencyKey: `review-bot/subscription:${sourceEvent.path}:${sourceEvent.offset}`,\n };\n}\n\nexport async function pullRequestLinterSubscriptionEvent(\n input: {\n connection: string;\n pullRequestNumber: number;\n repositoryId: number;\n // A processor host permanently adopts its first stream coordinate. The\n // path keeps two project-controlled repo aliases for the same GitHub PR\n // from accidentally dialing the same Durable Object.\n streamPath: string;\n },\n config: GithubAiLinterConfig,\n): Promise<StreamEventInput> {\n return {\n type: \"events.iterate.com/stream/subscription-configured\",\n payload: {\n name: \"github-ai-linter\",\n // The processor contract is the one vocabulary authority. In particular,\n // it includes `agent/paused`, which turns an exhausted review into its\n // durable terminal analysis settlement.\n filter: {\n eventTypes: GithubAiLinterProcessorContract.consumes,\n },\n receiver: {\n action: \"wake-processor\",\n expression: [\n \"workers\",\n [\"get\", await pullRequestLinterAppRef(input, config)],\n \"processor\",\n \"wakeStreamProcessor\",\n ],\n },\n },\n // Every route coordinate which changes the worker ref is part of the key.\n // Policy changes and delivery-shape changes have independent revisions:\n // the latter prevents a persisted old filter from colliding with its\n // replacement under same-key/different-body validation. `delivery:2` is\n // the durable filter/receiver shape; bump it when either changes.\n idempotencyKey: [\n \"github-ai-linter/subscription\",\n input.connection,\n input.repositoryId,\n input.pullRequestNumber,\n `policy:${config.policyVersion}`,\n \"delivery:2\",\n `stream:${input.streamPath}`,\n ].join(\":\"),\n };\n}\n\nasync function reviewBotAppRef(\n connection: string,\n config: GithubAiLinterConfig,\n): Promise<StatefulDynamicWorkerRef> {\n return dynamicWorkerRef({\n className: \"ReviewBotApp\",\n config,\n durableWorkerKey: `github-ai-linter-review-bot-${await durableIdentity(connection)}`,\n });\n}\n\nasync function pullRequestLinterAppRef(\n input: {\n connection: string;\n pullRequestNumber: number;\n repositoryId: number;\n streamPath: string;\n },\n config: GithubAiLinterConfig,\n): Promise<StatefulDynamicWorkerRef> {\n const identity = [\n input.connection,\n String(input.repositoryId),\n String(input.pullRequestNumber),\n input.streamPath,\n ].join(\"\\0\");\n return dynamicWorkerRef({\n className: \"GithubAiLinterApp\",\n config,\n durableWorkerKey: `app-gh-linter-${await durableIdentity(identity)}`,\n });\n}\n\nfunction dynamicWorkerRef(input: {\n className: string;\n config: GithubAiLinterConfig;\n durableWorkerKey: string;\n}): StatefulDynamicWorkerRef {\n return {\n type: \"stateful\",\n path: \"/\",\n className: input.className,\n durableWorkerKey: input.durableWorkerKey,\n source: {\n createWorker: {\n entryPoint: configuredWorkerEntrypoint,\n files: {\n type: \"repo\",\n repoPath: \"/repos/config\",\n include: [\"package.json\"],\n },\n minify: true,\n virtualModules: {\n \"iterate:github-ai-linter-config\": `export default ${JSON.stringify(input.config)};`,\n },\n },\n },\n };\n}\n\n/**\n * Dynamic-worker durable keys have a 63-character ceiling and connection\n * slugs are user-controlled. A truncated SHA-256 preserves stable identity\n * without leaking or squeezing arbitrary coordinates into that limit.\n */\nasync function durableIdentity(value: string) {\n const digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(value));\n return [...new Uint8Array(digest).slice(0, 16)]\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n"],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <!--
4
+ Used only when building with a real SIGN_IDENTITY (see build-menubar-app.sh).
5
+ Local UserNotifications need no special entitlement — this is the hardened-
6
+ runtime baseline, and the place to add keys (e.g. aps-environment for remote
7
+ push, or app-sandbox) if this ever ships through the App Store / notarization.
8
+ -->
9
+ <plist version="1.0">
10
+ <dict>
11
+ </dict>
12
+ </plist>