@cursor/july 0.1.95 → 0.1.96

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 (220) hide show
  1. package/AGENTS.md +3 -4
  2. package/dist/channels/deployments/types.d.ts +1 -1
  3. package/dist/channels/deployments/types.d.ts.map +1 -1
  4. package/dist/channels/deployments/types.js +1 -0
  5. package/dist/channels/origin/api.d.ts +59 -13
  6. package/dist/channels/origin/api.d.ts.map +1 -1
  7. package/dist/channels/origin/api.js +168 -27
  8. package/dist/channels/origin/binding.d.ts +2 -2
  9. package/dist/channels/origin/checks.d.ts +6 -6
  10. package/dist/channels/origin/checks.js +6 -6
  11. package/dist/channels/origin/cursor-account.d.ts +5 -3
  12. package/dist/channels/origin/cursor-account.d.ts.map +1 -1
  13. package/dist/channels/origin/cursor-account.js +5 -3
  14. package/dist/channels/slack/api.d.ts +9 -0
  15. package/dist/channels/slack/api.d.ts.map +1 -1
  16. package/dist/channels/slack/api.js +36 -5
  17. package/dist/channels/slack/defaults.d.ts.map +1 -1
  18. package/dist/channels/slack/defaults.js +17 -46
  19. package/dist/channels/slack/dispatch.d.ts +7 -1
  20. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  21. package/dist/channels/slack/dispatch.js +47 -23
  22. package/dist/channels/slack/inbound.d.ts +8 -0
  23. package/dist/channels/slack/inbound.d.ts.map +1 -1
  24. package/dist/channels/slack/inbound.js +32 -0
  25. package/dist/channels/slack/live-delivery.d.ts +26 -29
  26. package/dist/channels/slack/live-delivery.d.ts.map +1 -1
  27. package/dist/channels/slack/live-delivery.js +172 -73
  28. package/dist/channels/slack/manifest.d.ts.map +1 -1
  29. package/dist/channels/slack/manifest.js +5 -1
  30. package/dist/channels/slack/nudge-carrier.d.ts +2 -0
  31. package/dist/channels/slack/nudge-carrier.d.ts.map +1 -1
  32. package/dist/channels/slack/nudge-carrier.js +48 -1
  33. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  34. package/dist/channels/slack/slack-channel.js +2 -2
  35. package/dist/docs/404.html +2 -2
  36. package/dist/docs/ab.html +4 -4
  37. package/dist/docs/assets/{app.BBj0klBO.js → app.jXleCmOc.js} +1 -1
  38. package/dist/docs/assets/chunks/@localSearchIndexroot.DFoGuETX.js +1 -0
  39. package/dist/docs/assets/chunks/{VPLocalSearchBox.CUEXpL78.js → VPLocalSearchBox.8LhyglIT.js} +1 -1
  40. package/dist/docs/assets/chunks/{theme.DabmQnia.js → theme.9ged-pr2.js} +2 -2
  41. package/dist/docs/assets/index.md.CI93Ltlb.js +5 -0
  42. package/dist/docs/assets/{index.md.BoHaMdeZ.lean.js → index.md.CI93Ltlb.lean.js} +1 -1
  43. package/dist/docs/assets/{reference_cli.md.BsMOxDvh.js → reference_cli.md.CCnG-nJx.js} +2 -1
  44. package/dist/docs/assets/templates_code-wiki.md.CDYZIBFN.js +2 -0
  45. package/dist/docs/assets/templates_code-wiki.md.CDYZIBFN.lean.js +1 -0
  46. package/dist/docs/building-with-agents.html +4 -4
  47. package/dist/docs/concepts.html +4 -4
  48. package/dist/docs/deployment.html +4 -4
  49. package/dist/docs/evals.html +4 -4
  50. package/dist/docs/guides/agent-to-agent.html +4 -4
  51. package/dist/docs/guides/cloud-runtime.html +4 -4
  52. package/dist/docs/guides/convert-automation.html +4 -4
  53. package/dist/docs/guides/github.html +4 -4
  54. package/dist/docs/guides/human-in-the-loop.html +4 -4
  55. package/dist/docs/guides/mcp-oauth.html +4 -4
  56. package/dist/docs/guides/opentelemetry.html +4 -4
  57. package/dist/docs/guides/slack.html +4 -4
  58. package/dist/docs/guides/webhooks.html +4 -4
  59. package/dist/docs/hashmap.json +1 -1
  60. package/dist/docs/hillclimbing.html +4 -4
  61. package/dist/docs/index.html +6 -6
  62. package/dist/docs/index.md +3 -1
  63. package/dist/docs/llms-full.txt +102 -3
  64. package/dist/docs/llms.txt +1 -0
  65. package/dist/docs/quickstart.html +4 -4
  66. package/dist/docs/reference/agent-config.html +4 -4
  67. package/dist/docs/reference/artifacts.html +4 -4
  68. package/dist/docs/reference/channels.html +4 -4
  69. package/dist/docs/reference/cli.html +7 -6
  70. package/dist/docs/reference/cli.md +3 -2
  71. package/dist/docs/reference/connections.html +4 -4
  72. package/dist/docs/reference/hooks.html +4 -4
  73. package/dist/docs/reference/http-api.html +4 -4
  74. package/dist/docs/reference/instructions.html +4 -4
  75. package/dist/docs/reference/playground.html +4 -4
  76. package/dist/docs/reference/project-layout.html +4 -4
  77. package/dist/docs/reference/prompt.html +4 -4
  78. package/dist/docs/reference/schedules.html +4 -4
  79. package/dist/docs/reference/sessions.html +4 -4
  80. package/dist/docs/reference/skills.html +4 -4
  81. package/dist/docs/reference/subagents.html +4 -4
  82. package/dist/docs/reference/tools.html +4 -4
  83. package/dist/docs/scaffolding-agents.html +4 -4
  84. package/dist/docs/storage.html +4 -4
  85. package/dist/docs/templates/agentic-owners.html +4 -4
  86. package/dist/docs/templates/code-wiki.html +28 -0
  87. package/dist/docs/templates/code-wiki.md +91 -0
  88. package/dist/docs/templates/demo.html +5 -5
  89. package/dist/docs/templates/pr-autofixer.html +4 -4
  90. package/dist/docs/templates/security-help.html +4 -4
  91. package/dist/docs/templates/security-reviewer.html +5 -5
  92. package/dist/docs/templates/triage.html +4 -4
  93. package/dist/docs/troubleshooting.html +4 -4
  94. package/dist/files-backends/cursor-hosted.d.ts +26 -4
  95. package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
  96. package/dist/files-backends/cursor-hosted.js +32 -4
  97. package/dist/internal/advertise-tools.d.ts +2 -0
  98. package/dist/internal/advertise-tools.d.ts.map +1 -1
  99. package/dist/internal/advertise-tools.js +15 -1
  100. package/dist/internal/bounded.d.ts +7 -0
  101. package/dist/internal/bounded.d.ts.map +1 -0
  102. package/dist/internal/bounded.js +32 -0
  103. package/dist/internal/cli-deploy.d.ts.map +1 -1
  104. package/dist/internal/cli-deploy.js +7 -1
  105. package/dist/internal/conversation-mirror.d.ts +11 -8
  106. package/dist/internal/conversation-mirror.d.ts.map +1 -1
  107. package/dist/internal/conversation-mirror.js +116 -55
  108. package/dist/internal/cursor/backend-client.d.ts.map +1 -1
  109. package/dist/internal/cursor/backend-client.js +22 -48
  110. package/dist/internal/cursor/session-token.d.ts +45 -0
  111. package/dist/internal/cursor/session-token.d.ts.map +1 -0
  112. package/dist/internal/cursor/session-token.js +99 -0
  113. package/dist/internal/cursor-agent-template.d.ts +1 -1
  114. package/dist/internal/cursor-agent-template.d.ts.map +1 -1
  115. package/dist/internal/cursor-agent-template.js +1 -0
  116. package/dist/internal/framework-file-storage.d.ts +61 -0
  117. package/dist/internal/framework-file-storage.d.ts.map +1 -0
  118. package/dist/internal/framework-file-storage.js +204 -0
  119. package/dist/internal/framework-storage-selection.d.ts +11 -5
  120. package/dist/internal/framework-storage-selection.d.ts.map +1 -1
  121. package/dist/internal/framework-storage-selection.js +38 -11
  122. package/dist/internal/hosted-delivery.d.ts +7 -0
  123. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  124. package/dist/internal/hosted-delivery.js +4 -0
  125. package/dist/internal/init-project.d.ts.map +1 -1
  126. package/dist/internal/init-project.js +2 -0
  127. package/dist/internal/install-cursor-skills.d.ts.map +1 -1
  128. package/dist/internal/install-cursor-skills.js +1 -3
  129. package/dist/internal/managed-delivery.d.ts +80 -0
  130. package/dist/internal/managed-delivery.d.ts.map +1 -0
  131. package/dist/internal/managed-delivery.js +86 -0
  132. package/dist/internal/runtime-dispatch-runner.d.ts +5 -1
  133. package/dist/internal/runtime-dispatch-runner.d.ts.map +1 -1
  134. package/dist/internal/runtime-dispatch-runner.js +7 -0
  135. package/dist/internal/sdk-runner.d.ts +11 -0
  136. package/dist/internal/sdk-runner.d.ts.map +1 -1
  137. package/dist/internal/sdk-runner.js +39 -8
  138. package/dist/internal/server.js +1 -0
  139. package/dist/internal/session-engine.d.ts +13 -0
  140. package/dist/internal/session-engine.d.ts.map +1 -1
  141. package/dist/internal/session-engine.js +62 -3
  142. package/dist/internal/steering.d.ts +15 -0
  143. package/dist/internal/steering.d.ts.map +1 -0
  144. package/dist/internal/steering.js +18 -0
  145. package/dist/playground/assets/index-B1DDvBeC.css +1 -0
  146. package/dist/playground/assets/{index-CZA1uEWA.js → index-Cx9CclK_.js} +51 -51
  147. package/dist/playground/index.html +2 -2
  148. package/dist/storage-backends/cursor-hosted.d.ts +8 -5
  149. package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
  150. package/dist/storage-backends/cursor-hosted.js +4 -3
  151. package/dist/types.d.ts +2 -1
  152. package/dist/types.d.ts.map +1 -1
  153. package/docs/README.md +3 -1
  154. package/docs/reference/cli.md +3 -2
  155. package/docs/templates/code-wiki.md +96 -0
  156. package/package.json +2 -2
  157. package/skills/ab/SKILL.md +13 -97
  158. package/skills/create-agent/SKILL.md +123 -223
  159. package/skills/debug/SKILL.md +34 -68
  160. package/skills/evals/SKILL.md +55 -180
  161. package/skills/framework-map/SKILL.md +83 -145
  162. package/skills/github/SKILL.md +53 -111
  163. package/skills/hillclimb/SKILL.md +40 -163
  164. package/skills/mcp-auth/SKILL.md +48 -107
  165. package/skills/otel/SKILL.md +22 -68
  166. package/skills/setup-slack/SKILL.md +77 -208
  167. package/src/channels/deployments/types.ts +1 -0
  168. package/src/channels/origin/api.ts +242 -30
  169. package/src/channels/origin/binding.ts +2 -2
  170. package/src/channels/origin/checks.ts +6 -6
  171. package/src/channels/origin/cursor-account.ts +5 -3
  172. package/src/channels/slack/api.ts +41 -5
  173. package/src/channels/slack/defaults.ts +15 -49
  174. package/src/channels/slack/dispatch.ts +56 -22
  175. package/src/channels/slack/inbound.ts +43 -0
  176. package/src/channels/slack/live-delivery.ts +235 -114
  177. package/src/channels/slack/manifest.ts +5 -1
  178. package/src/channels/slack/nudge-carrier.ts +48 -1
  179. package/src/channels/slack/slack-channel.ts +2 -0
  180. package/src/files-backends/cursor-hosted.ts +40 -7
  181. package/src/internal/advertise-tools.ts +18 -2
  182. package/src/internal/bounded.ts +28 -0
  183. package/src/internal/cli-deploy.ts +12 -0
  184. package/src/internal/conversation-mirror.ts +145 -69
  185. package/src/internal/cursor/backend-client.ts +34 -58
  186. package/src/internal/cursor/session-token.ts +115 -0
  187. package/src/internal/cursor-agent-template.ts +1 -0
  188. package/src/internal/framework-file-storage.ts +222 -0
  189. package/src/internal/framework-storage-selection.ts +51 -11
  190. package/src/internal/hosted-delivery.ts +10 -0
  191. package/src/internal/init-project.ts +2 -0
  192. package/src/internal/install-cursor-skills.ts +1 -4
  193. package/src/internal/managed-delivery.ts +125 -0
  194. package/src/internal/runtime-dispatch-runner.ts +10 -0
  195. package/src/internal/sdk-runner.ts +56 -8
  196. package/src/internal/server.ts +2 -0
  197. package/src/internal/session-engine.ts +64 -4
  198. package/src/internal/steering.ts +17 -0
  199. package/src/storage-backends/cursor-hosted.ts +9 -7
  200. package/src/types.ts +2 -1
  201. package/templates/code-wiki/README.md +34 -0
  202. package/templates/code-wiki/agent/agent.ts +8 -0
  203. package/templates/code-wiki/agent/channels/github.ts +144 -0
  204. package/templates/code-wiki/agent/instructions.md +39 -0
  205. package/templates/code-wiki/agent/lib/repos.ts +5 -0
  206. package/templates/code-wiki/agent/lib/wiki.ts +22 -0
  207. package/templates/code-wiki/agent/tools/apply_wiki.ts +219 -0
  208. package/templates/code-wiki/evals/evals.config.ts +5 -0
  209. package/templates/code-wiki/evals/wiki.eval.ts +132 -0
  210. package/templates/code-wiki/init.json +25 -0
  211. package/templates/code-wiki/package.json +18 -0
  212. package/templates/code-wiki/tsconfig.json +12 -0
  213. package/dist/docs/assets/chunks/@localSearchIndexroot.oqPawjiD.js +0 -1
  214. package/dist/docs/assets/index.md.BoHaMdeZ.js +0 -5
  215. package/dist/internal/deployment-scm-event-stream.d.ts +0 -116
  216. package/dist/internal/deployment-scm-event-stream.d.ts.map +0 -1
  217. package/dist/internal/deployment-scm-event-stream.js +0 -474
  218. package/dist/playground/assets/index-CF7hUDnQ.css +0 -1
  219. package/src/internal/deployment-scm-event-stream.ts +0 -593
  220. /package/dist/docs/assets/{reference_cli.md.BsMOxDvh.lean.js → reference_cli.md.CCnG-nJx.lean.js} +0 -0
@@ -0,0 +1,22 @@
1
+ export const WIKI_DIR = "wiki";
2
+
3
+ const PAGE = /^[A-Za-z0-9._-]+\.md$/;
4
+
5
+ export function isWikiPath(path: string): boolean {
6
+ return path === WIKI_DIR || path.startsWith(`${WIKI_DIR}/`);
7
+ }
8
+
9
+ export function wikiPagePath(raw: string): string | undefined {
10
+ const path = raw.replace(/^\/+/, "");
11
+ if (path.includes("..") || path.includes("\\")) {
12
+ return undefined;
13
+ }
14
+ if (!path.startsWith(`${WIKI_DIR}/`) || !path.endsWith(".md")) {
15
+ return undefined;
16
+ }
17
+ const name = path.slice(WIKI_DIR.length + 1);
18
+ if (!PAGE.test(name)) {
19
+ return undefined;
20
+ }
21
+ return `${WIKI_DIR}/${name}`;
22
+ }
@@ -0,0 +1,219 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import type { HostGitHubClient } from "@cursor/july";
4
+ import { parseGitHubPrContinuationKey } from "@cursor/july/channels/github";
5
+ import { defineTool } from "@cursor/july/tools";
6
+ import { z } from "zod";
7
+ import { wikiPagePath } from "../lib/wiki.js";
8
+
9
+ const page = z.object({
10
+ path: z.string().min(1).max(160),
11
+ content: z.string().min(1).max(32_000),
12
+ });
13
+
14
+ type Page = z.infer<typeof page>;
15
+ type Octokit = Awaited<ReturnType<HostGitHubClient["getOctokit"]>>;
16
+
17
+ type Write = {
18
+ octokit: Octokit;
19
+ owner: string;
20
+ repo: string;
21
+ number: number;
22
+ label: string;
23
+ reason: string;
24
+ pages: Page[];
25
+ base: string;
26
+ branch: string;
27
+ };
28
+
29
+ export default defineTool({
30
+ description:
31
+ "Skip or open a wiki follow-up PR for this merged pull request. Call once.",
32
+ inputSchema: z.discriminatedUnion("verdict", [
33
+ z.object({
34
+ verdict: z.literal("skip"),
35
+ reason: z.string().min(1).max(280),
36
+ }),
37
+ z.object({
38
+ verdict: z.literal("update"),
39
+ reason: z.string().min(1).max(280),
40
+ pages: z.array(page).min(1).max(8),
41
+ }),
42
+ ]),
43
+ async execute(input, ctx) {
44
+ if (ctx.session.purpose === "eval") {
45
+ return { posted: false, reason: "eval", verdict: input.verdict };
46
+ }
47
+ if (input.verdict === "skip") {
48
+ return { posted: false, reason: input.reason, verdict: "skip" };
49
+ }
50
+ const ref = parseGitHubPrContinuationKey(ctx.session.continuationKey ?? "");
51
+ if (ref === undefined) {
52
+ throw new Error("apply_wiki requires a GitHub pull request session");
53
+ }
54
+ const base = (
55
+ await readFile(join(ctx.workspaceDir, "pr/base.ref"), "utf8")
56
+ ).trim();
57
+ const branch = wikiUpdateBranch(base);
58
+ if (branch === undefined) {
59
+ throw new Error("missing pr/base.ref");
60
+ }
61
+ const pages = input.pages.map((item) => {
62
+ const path = wikiPagePath(item.path);
63
+ if (path === undefined) {
64
+ throw new Error(`invalid wiki path: ${item.path}`);
65
+ }
66
+ return { path, content: item.content };
67
+ });
68
+ return openWikiPr({
69
+ octokit: await ctx.host.github.getOctokit(),
70
+ owner: ref.owner,
71
+ repo: ref.repo,
72
+ number: ref.number,
73
+ label: `${ref.owner}/${ref.repo}#${ref.number}`,
74
+ reason: input.reason,
75
+ pages,
76
+ base,
77
+ branch,
78
+ });
79
+ },
80
+ });
81
+
82
+ function wikiUpdateBranch(base: string): string | undefined {
83
+ if (base === "" || !/^[A-Za-z0-9._/-]+$/.test(base)) {
84
+ return undefined;
85
+ }
86
+ return `wiki/${base.replaceAll("/", "-")}`;
87
+ }
88
+
89
+ async function openWikiPr(input: Write) {
90
+ const repo = { owner: input.owner, repo: input.repo };
91
+ const existing = await input.octokit.rest.pulls.list({
92
+ ...repo,
93
+ state: "open",
94
+ head: `${input.owner}:${input.branch}`,
95
+ base: input.base,
96
+ per_page: 1,
97
+ });
98
+ const open = existing.data[0];
99
+ if (open !== undefined && citesSource(open.body, input.number)) {
100
+ return {
101
+ posted: false,
102
+ reason: "exists",
103
+ verdict: "update",
104
+ pr: input.label,
105
+ url: open.html_url,
106
+ };
107
+ }
108
+ const branchSha = await refSha(input.octokit, repo, input.branch);
109
+ const parent =
110
+ branchSha ?? (await refSha(input.octokit, repo, input.base));
111
+ if (parent === undefined) {
112
+ throw new Error(`missing base ref: ${input.base}`);
113
+ }
114
+ const { data: commit } = await input.octokit.rest.git.getCommit({
115
+ ...repo,
116
+ commit_sha: parent,
117
+ });
118
+ const blobs = await Promise.all(
119
+ input.pages.map(async (item) => {
120
+ const { data } = await input.octokit.rest.git.createBlob({
121
+ ...repo,
122
+ content: Buffer.from(item.content).toString("base64"),
123
+ encoding: "base64",
124
+ });
125
+ return {
126
+ path: item.path,
127
+ mode: "100644" as const,
128
+ type: "blob" as const,
129
+ sha: data.sha,
130
+ };
131
+ })
132
+ );
133
+ const { data: tree } = await input.octokit.rest.git.createTree({
134
+ ...repo,
135
+ base_tree: commit.tree.sha,
136
+ tree: blobs,
137
+ });
138
+ const { data: next } = await input.octokit.rest.git.createCommit({
139
+ ...repo,
140
+ message: `wiki: ${input.reason}`,
141
+ tree: tree.sha,
142
+ parents: [parent],
143
+ });
144
+ if (branchSha === undefined) {
145
+ await input.octokit.rest.git.createRef({
146
+ ...repo,
147
+ ref: `refs/heads/${input.branch}`,
148
+ sha: next.sha,
149
+ });
150
+ } else {
151
+ await input.octokit.rest.git.updateRef({
152
+ ...repo,
153
+ ref: `heads/${input.branch}`,
154
+ sha: next.sha,
155
+ });
156
+ }
157
+ if (open !== undefined) {
158
+ await input.octokit.rest.pulls.update({
159
+ ...repo,
160
+ pull_number: open.number,
161
+ body: appendSource(open.body ?? "", input.reason, input.number),
162
+ });
163
+ return {
164
+ posted: true,
165
+ verdict: "update",
166
+ pr: input.label,
167
+ url: open.html_url,
168
+ };
169
+ }
170
+ const { data: pull } = await input.octokit.rest.pulls.create({
171
+ ...repo,
172
+ title: `wiki: update from #${input.number}`,
173
+ head: input.branch,
174
+ base: input.base,
175
+ body: `${input.reason}\n\nSource: #${input.number}`,
176
+ });
177
+ return {
178
+ posted: true,
179
+ verdict: "update",
180
+ pr: input.label,
181
+ url: pull.html_url,
182
+ };
183
+ }
184
+
185
+ async function refSha(
186
+ octokit: Octokit,
187
+ repo: { owner: string; repo: string },
188
+ name: string
189
+ ): Promise<string | undefined> {
190
+ try {
191
+ const { data } = await octokit.rest.git.getRef({
192
+ ...repo,
193
+ ref: `heads/${name}`,
194
+ });
195
+ return data.object.sha;
196
+ } catch (error) {
197
+ if (isNotFound(error)) {
198
+ return undefined;
199
+ }
200
+ throw error;
201
+ }
202
+ }
203
+
204
+ function citesSource(body: string | null | undefined, number: number): boolean {
205
+ return new RegExp(`(?:^|\\n)Source:.*#${number}(?:\\s|$)`).test(body ?? "");
206
+ }
207
+
208
+ function appendSource(body: string, reason: string, number: number): string {
209
+ return `${body.trim()}\n\n${reason}\nSource: #${number}`;
210
+ }
211
+
212
+ function isNotFound(error: unknown): boolean {
213
+ return (
214
+ typeof error === "object" &&
215
+ error !== null &&
216
+ "status" in error &&
217
+ error.status === 404
218
+ );
219
+ }
@@ -0,0 +1,5 @@
1
+ import { defineEvalConfig } from "@cursor/july/evals";
2
+
3
+ export default defineEvalConfig({
4
+ maxConcurrency: 10,
5
+ });
@@ -0,0 +1,132 @@
1
+ import { defineEval } from "@cursor/july/evals";
2
+
3
+ function merged(title: string): string {
4
+ return [
5
+ "GitHub pull request trigger: acme/api#12",
6
+ "Action: closed",
7
+ "PR: https://github.com/acme/api/pull/12",
8
+ `Title: ${title}`,
9
+ "Head: feat/change (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)",
10
+ "Base: main",
11
+ "Author: sam",
12
+ "",
13
+ "This pull request merged. Read pr/files.txt, pr/diff.patch, and wiki/.",
14
+ ].join("\n");
15
+ }
16
+
17
+ const INDEX = [
18
+ "# Wiki",
19
+ "",
20
+ "- [Billing](billing.md): usage events posted to the warehouse",
21
+ "- [App](app.md): HTTP handlers and UI chrome",
22
+ "",
23
+ ].join("\n");
24
+
25
+ const BILLING = [
26
+ "# Billing",
27
+ "",
28
+ "Usage events are protobuf messages in `proto/billing.proto`.",
29
+ "Each event has `account_id` and `amount_cents`.",
30
+ "",
31
+ ].join("\n");
32
+
33
+ const APP = [
34
+ "# App",
35
+ "",
36
+ "The sidebar opener is a querySelector on `.opener`.",
37
+ "",
38
+ ].join("\n");
39
+
40
+ export default defineEval({
41
+ tags: ["smoke"],
42
+ cases: [
43
+ {
44
+ id: "skip-lint",
45
+ description: "A quote-style lint fix does not open a wiki PR.",
46
+ async test(t) {
47
+ await t.send(merged("Fix sidebar opener lint failure"), {
48
+ workspaceFiles: {
49
+ "pr/files.txt": "src/sidebar.ts\n",
50
+ "pr/diff.patch": [
51
+ "diff --git a/src/sidebar.ts b/src/sidebar.ts",
52
+ "-const opener = document.querySelector('.opener')",
53
+ '+const opener = document.querySelector(".opener");',
54
+ ].join("\n"),
55
+ "wiki/pages.txt": "wiki/_index.md\nwiki/app.md\n",
56
+ "wiki/_index.md": INDEX,
57
+ "wiki/app.md": APP,
58
+ },
59
+ });
60
+ t.succeeded();
61
+ t.calledTool("apply_wiki", { input: { verdict: "skip" } });
62
+ },
63
+ },
64
+ {
65
+ id: "update-contract",
66
+ description: "New billing proto fields update the billing page.",
67
+ async test(t) {
68
+ await t.send(merged("Add unified fields to billing events"), {
69
+ workspaceFiles: {
70
+ "pr/files.txt": "proto/billing.proto\n",
71
+ "pr/diff.patch": [
72
+ "diff --git a/proto/billing.proto b/proto/billing.proto",
73
+ " message UsageEvent {",
74
+ " string account_id = 1;",
75
+ " int64 amount_cents = 2;",
76
+ "+ string usage_unit = 12;",
77
+ "+ string workspace_id = 13;",
78
+ " }",
79
+ ].join("\n"),
80
+ "wiki/pages.txt": "wiki/_index.md\nwiki/billing.md\n",
81
+ "wiki/_index.md": INDEX,
82
+ "wiki/billing.md": BILLING,
83
+ },
84
+ });
85
+ t.succeeded();
86
+ t.calledTool("apply_wiki", { input: { verdict: "update" } });
87
+ },
88
+ },
89
+ {
90
+ id: "skip-docs",
91
+ description: "A markdown-only merge does not open a wiki PR.",
92
+ async test(t) {
93
+ await t.send(merged("Document factory delete in servicetests"), {
94
+ workspaceFiles: {
95
+ "pr/files.txt": "backend/server/src/factory/README.md\n",
96
+ "pr/diff.patch": [
97
+ "diff --git a/backend/server/src/factory/README.md b/backend/server/src/factory/README.md",
98
+ "+Drive environment delete from markdown servicetests.",
99
+ ].join("\n"),
100
+ "wiki/pages.txt": "wiki/_index.md\n",
101
+ "wiki/_index.md": INDEX,
102
+ },
103
+ });
104
+ t.succeeded();
105
+ t.calledTool("apply_wiki", { input: { verdict: "skip" } });
106
+ },
107
+ },
108
+ {
109
+ id: "skip-cherry-pick",
110
+ description: "A release-train cherry-pick does not open a wiki PR.",
111
+ async test(t) {
112
+ await t.send(
113
+ merged("[CP releases/3.19] Stop stale Project corner loaders"),
114
+ {
115
+ workspaceFiles: {
116
+ "pr/files.txt": "src/projects.ts\n",
117
+ "pr/diff.patch": [
118
+ "diff --git a/src/projects.ts b/src/projects.ts",
119
+ "+if (status.seq < last.seq) return;",
120
+ ].join("\n"),
121
+ "wiki/pages.txt": "wiki/_index.md\nwiki/app.md\n",
122
+ "wiki/_index.md": INDEX,
123
+ "wiki/app.md": APP,
124
+ },
125
+ }
126
+ );
127
+ t.succeeded();
128
+ t.calledTool("apply_wiki", { input: { verdict: "skip" } });
129
+ },
130
+ },
131
+ ],
132
+ });
@@ -0,0 +1,25 @@
1
+ {
2
+ "questions": [
3
+ {
4
+ "id": "repos",
5
+ "prompt": "Which GitHub repos should this agent watch for merges?",
6
+ "hint": "Comma-separated owner/repo. One GitHub owner.",
7
+ "placeholder": "acme/api, acme/web",
8
+ "parse": "owner-repo-list"
9
+ }
10
+ ],
11
+ "replace": [
12
+ {
13
+ "file": "agent/lib/repos.ts",
14
+ "find": "[\"owner/repo\"]",
15
+ "answer": "repos",
16
+ "as": "json-array"
17
+ },
18
+ {
19
+ "file": "README.md",
20
+ "find": "owner/repo",
21
+ "answer": "repos",
22
+ "as": "first"
23
+ }
24
+ ]
25
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "code-wiki",
3
+ "private": true,
4
+ "type": "module",
5
+ "description": "Keeps an in-repo wiki current after pull requests merge.",
6
+ "scripts": {
7
+ "check": "tsc --noEmit",
8
+ "dev": "agent-sdk dev"
9
+ },
10
+ "dependencies": {
11
+ "@cursor/july": "latest",
12
+ "zod": "^3.25.0"
13
+ },
14
+ "devDependencies": {
15
+ "@types/node": "^22.14.0",
16
+ "typescript": "^5.8.0"
17
+ }
18
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "noEmit": true,
8
+ "skipLibCheck": true,
9
+ "types": ["node"]
10
+ },
11
+ "include": ["agent/**/*", "evals/**/*"]
12
+ }