@cursor/july 0.1.95 → 0.1.97

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 (424) hide show
  1. package/AGENTS.md +3 -4
  2. package/README.md +3 -2
  3. package/dist/bin/agent-serve.js +14 -3
  4. package/dist/channels/deployments/types.d.ts +1 -1
  5. package/dist/channels/deployments/types.d.ts.map +1 -1
  6. package/dist/channels/deployments/types.js +1 -0
  7. package/dist/channels/origin/api.d.ts +72 -15
  8. package/dist/channels/origin/api.d.ts.map +1 -1
  9. package/dist/channels/origin/api.js +185 -28
  10. package/dist/channels/origin/binding.d.ts +13 -2
  11. package/dist/channels/origin/binding.d.ts.map +1 -1
  12. package/dist/channels/origin/binding.js +41 -25
  13. package/dist/channels/origin/checks.d.ts +6 -6
  14. package/dist/channels/origin/checks.js +6 -6
  15. package/dist/channels/origin/cursor-account.d.ts +5 -3
  16. package/dist/channels/origin/cursor-account.d.ts.map +1 -1
  17. package/dist/channels/origin/cursor-account.js +5 -3
  18. package/dist/channels/origin/index.d.ts +1 -0
  19. package/dist/channels/origin/index.d.ts.map +1 -1
  20. package/dist/channels/origin/index.js +1 -0
  21. package/dist/channels/origin/origin-channel.d.ts.map +1 -1
  22. package/dist/channels/origin/origin-channel.js +3 -0
  23. package/dist/channels/origin/reactions.d.ts +56 -0
  24. package/dist/channels/origin/reactions.d.ts.map +1 -0
  25. package/dist/channels/origin/reactions.js +67 -0
  26. package/dist/channels/origin/types.d.ts +11 -0
  27. package/dist/channels/origin/types.d.ts.map +1 -1
  28. package/dist/channels/slack/api.d.ts +9 -0
  29. package/dist/channels/slack/api.d.ts.map +1 -1
  30. package/dist/channels/slack/api.js +36 -5
  31. package/dist/channels/slack/approvals.d.ts +16 -0
  32. package/dist/channels/slack/approvals.d.ts.map +1 -1
  33. package/dist/channels/slack/approvals.js +86 -0
  34. package/dist/channels/slack/cli-project.d.ts +19 -0
  35. package/dist/channels/slack/cli-project.d.ts.map +1 -0
  36. package/dist/channels/slack/cli-project.js +234 -0
  37. package/dist/channels/slack/defaults.d.ts.map +1 -1
  38. package/dist/channels/slack/defaults.js +110 -81
  39. package/dist/channels/slack/dispatch.d.ts +7 -1
  40. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  41. package/dist/channels/slack/dispatch.js +47 -23
  42. package/dist/channels/slack/inbound.d.ts +8 -0
  43. package/dist/channels/slack/inbound.d.ts.map +1 -1
  44. package/dist/channels/slack/inbound.js +32 -0
  45. package/dist/channels/slack/init.d.ts +3 -2
  46. package/dist/channels/slack/init.d.ts.map +1 -1
  47. package/dist/channels/slack/init.js +5 -5
  48. package/dist/channels/slack/interactive.d.ts +2 -1
  49. package/dist/channels/slack/interactive.d.ts.map +1 -1
  50. package/dist/channels/slack/interactive.js +15 -4
  51. package/dist/channels/slack/live-delivery.d.ts +26 -29
  52. package/dist/channels/slack/live-delivery.d.ts.map +1 -1
  53. package/dist/channels/slack/live-delivery.js +172 -73
  54. package/dist/channels/slack/manifest.d.ts +1 -1
  55. package/dist/channels/slack/manifest.d.ts.map +1 -1
  56. package/dist/channels/slack/manifest.js +6 -2
  57. package/dist/channels/slack/nudge-carrier.d.ts +2 -0
  58. package/dist/channels/slack/nudge-carrier.d.ts.map +1 -1
  59. package/dist/channels/slack/nudge-carrier.js +48 -1
  60. package/dist/channels/slack/setup.d.ts +1 -1
  61. package/dist/channels/slack/setup.d.ts.map +1 -1
  62. package/dist/channels/slack/setup.js +10 -6
  63. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  64. package/dist/channels/slack/slack-channel.js +3 -2
  65. package/dist/channels/slack/tool-approval-events.d.ts.map +1 -1
  66. package/dist/channels/slack/tool-approval-events.js +91 -1
  67. package/dist/docs/404.html +2 -2
  68. package/dist/docs/ab.html +4 -4
  69. package/dist/docs/assets/{app.BBj0klBO.js → app.B3rWNYE1.js} +1 -1
  70. package/dist/docs/assets/chunks/@localSearchIndexroot.BU9nHdnQ.js +1 -0
  71. package/dist/docs/assets/chunks/{VPLocalSearchBox.CUEXpL78.js → VPLocalSearchBox.C1lhqJJR.js} +1 -1
  72. package/dist/docs/assets/chunks/{theme.DabmQnia.js → theme.B40_SXuv.js} +2 -2
  73. package/dist/docs/assets/{deployment.md.D9msOFOW.js → deployment.md.MFPKqsqI.js} +2 -2
  74. package/dist/docs/assets/{guides_mcp-oauth.md.DPYmBCbV.js → guides_mcp-oauth.md.CN-6YmTJ.js} +4 -4
  75. package/dist/docs/assets/{guides_mcp-oauth.md.DPYmBCbV.lean.js → guides_mcp-oauth.md.CN-6YmTJ.lean.js} +1 -1
  76. package/dist/docs/assets/guides_slack.md.VDXQV3ja.js +22 -0
  77. package/dist/docs/assets/guides_slack.md.VDXQV3ja.lean.js +1 -0
  78. package/dist/docs/assets/index.md.CVeRUOeZ.js +5 -0
  79. package/dist/docs/assets/{index.md.BoHaMdeZ.lean.js → index.md.CVeRUOeZ.lean.js} +1 -1
  80. package/dist/docs/assets/{reference_agent-config.md.Cp_x38Nl.js → reference_agent-config.md.BHeYMgme.js} +1 -1
  81. package/dist/docs/assets/{reference_cli.md.BsMOxDvh.js → reference_cli.md.RyZf5OTE.js} +10 -6
  82. package/dist/docs/assets/{reference_cli.md.BsMOxDvh.lean.js → reference_cli.md.RyZf5OTE.lean.js} +1 -1
  83. package/dist/docs/assets/{reference_connections.md.BH8Oc0D0.js → reference_connections.md.DxldvyIB.js} +4 -3
  84. package/dist/docs/assets/{reference_http-api.md.D89k1mdm.js → reference_http-api.md.5zOAbV86.js} +1 -1
  85. package/dist/docs/assets/reference_sessions.md.NxFP_CAC.js +1 -0
  86. package/dist/docs/assets/{reference_tools.md.BHeXn2id.js → reference_tools.md.B84gw9Ii.js} +1 -1
  87. package/dist/docs/assets/templates_agents-md.md.CXSMZljE.js +2 -0
  88. package/dist/docs/assets/templates_agents-md.md.CXSMZljE.lean.js +1 -0
  89. package/dist/docs/assets/templates_code-wiki.md.CDYZIBFN.js +2 -0
  90. package/dist/docs/assets/templates_code-wiki.md.CDYZIBFN.lean.js +1 -0
  91. package/dist/docs/assets/troubleshooting.md.DCiPBhYs.js +1 -0
  92. package/dist/docs/building-with-agents.html +4 -4
  93. package/dist/docs/concepts.html +4 -4
  94. package/dist/docs/deployment.html +7 -7
  95. package/dist/docs/deployment.md +5 -4
  96. package/dist/docs/evals.html +4 -4
  97. package/dist/docs/guides/agent-to-agent.html +4 -4
  98. package/dist/docs/guides/cloud-runtime.html +4 -4
  99. package/dist/docs/guides/convert-automation.html +4 -4
  100. package/dist/docs/guides/github.html +4 -4
  101. package/dist/docs/guides/human-in-the-loop.html +4 -4
  102. package/dist/docs/guides/mcp-oauth.html +8 -8
  103. package/dist/docs/guides/mcp-oauth.md +26 -8
  104. package/dist/docs/guides/opentelemetry.html +4 -4
  105. package/dist/docs/guides/slack.html +17 -33
  106. package/dist/docs/guides/slack.md +92 -201
  107. package/dist/docs/guides/webhooks.html +4 -4
  108. package/dist/docs/hashmap.json +1 -1
  109. package/dist/docs/hillclimbing.html +4 -4
  110. package/dist/docs/index.html +6 -6
  111. package/dist/docs/index.md +7 -3
  112. package/dist/docs/llms-full.txt +398 -653
  113. package/dist/docs/llms.txt +3 -2
  114. package/dist/docs/quickstart.html +4 -4
  115. package/dist/docs/reference/agent-config.html +6 -6
  116. package/dist/docs/reference/agent-config.md +2 -2
  117. package/dist/docs/reference/artifacts.html +4 -4
  118. package/dist/docs/reference/channels.html +4 -4
  119. package/dist/docs/reference/cli.html +14 -10
  120. package/dist/docs/reference/cli.md +39 -16
  121. package/dist/docs/reference/connections.html +9 -8
  122. package/dist/docs/reference/connections.md +6 -3
  123. package/dist/docs/reference/hooks.html +4 -4
  124. package/dist/docs/reference/http-api.html +6 -6
  125. package/dist/docs/reference/http-api.md +2 -1
  126. package/dist/docs/reference/instructions.html +4 -4
  127. package/dist/docs/reference/playground.html +4 -4
  128. package/dist/docs/reference/project-layout.html +4 -4
  129. package/dist/docs/reference/prompt.html +4 -4
  130. package/dist/docs/reference/schedules.html +4 -4
  131. package/dist/docs/reference/sessions.html +5 -5
  132. package/dist/docs/reference/sessions.md +4 -2
  133. package/dist/docs/reference/skills.html +4 -4
  134. package/dist/docs/reference/subagents.html +4 -4
  135. package/dist/docs/reference/tools.html +6 -6
  136. package/dist/docs/reference/tools.md +9 -2
  137. package/dist/docs/scaffolding-agents.html +4 -4
  138. package/dist/docs/storage.html +4 -4
  139. package/dist/docs/templates/agentic-owners.html +4 -4
  140. package/dist/docs/templates/agents-md.html +28 -0
  141. package/dist/docs/templates/agents-md.md +105 -0
  142. package/dist/docs/templates/code-wiki.html +28 -0
  143. package/dist/docs/templates/code-wiki.md +91 -0
  144. package/dist/docs/templates/demo.html +5 -5
  145. package/dist/docs/templates/pr-autofixer.html +4 -4
  146. package/dist/docs/templates/security-help.html +4 -4
  147. package/dist/docs/templates/security-reviewer.html +5 -5
  148. package/dist/docs/templates/triage.html +4 -4
  149. package/dist/docs/troubleshooting.html +5 -5
  150. package/dist/docs/troubleshooting.md +2 -2
  151. package/dist/evals/run-facts.d.ts.map +1 -1
  152. package/dist/evals/run-facts.js +27 -0
  153. package/dist/files-backends/cursor-hosted.d.ts +26 -4
  154. package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
  155. package/dist/files-backends/cursor-hosted.js +32 -4
  156. package/dist/internal/advertise-tools.d.ts +2 -0
  157. package/dist/internal/advertise-tools.d.ts.map +1 -1
  158. package/dist/internal/advertise-tools.js +30 -10
  159. package/dist/internal/approval-gate.d.ts +12 -13
  160. package/dist/internal/approval-gate.d.ts.map +1 -1
  161. package/dist/internal/approval-gate.js +16 -21
  162. package/dist/internal/bounded.d.ts +7 -0
  163. package/dist/internal/bounded.d.ts.map +1 -0
  164. package/dist/internal/bounded.js +32 -0
  165. package/dist/internal/chat-client.js +10 -0
  166. package/dist/internal/cli-deploy.d.ts +5 -0
  167. package/dist/internal/cli-deploy.d.ts.map +1 -1
  168. package/dist/internal/cli-deploy.js +57 -18
  169. package/dist/internal/cli-mcp-oauth.js +8 -18
  170. package/dist/internal/cli-slack-manual.d.ts +24 -2
  171. package/dist/internal/cli-slack-manual.d.ts.map +1 -1
  172. package/dist/internal/cli-slack-manual.js +251 -20
  173. package/dist/internal/cli-slack.d.ts +9 -2
  174. package/dist/internal/cli-slack.d.ts.map +1 -1
  175. package/dist/internal/cli-slack.js +29 -82
  176. package/dist/internal/conversation-mirror.d.ts +11 -8
  177. package/dist/internal/conversation-mirror.d.ts.map +1 -1
  178. package/dist/internal/conversation-mirror.js +116 -55
  179. package/dist/internal/cursor/account-mcp.d.ts +1 -0
  180. package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
  181. package/dist/internal/cursor/account-mcp.js +17 -0
  182. package/dist/internal/cursor/backend-client.d.ts.map +1 -1
  183. package/dist/internal/cursor/backend-client.js +22 -48
  184. package/dist/internal/cursor/session-token.d.ts +45 -0
  185. package/dist/internal/cursor/session-token.d.ts.map +1 -0
  186. package/dist/internal/cursor/session-token.js +99 -0
  187. package/dist/internal/cursor-agent-template.d.ts +1 -1
  188. package/dist/internal/cursor-agent-template.d.ts.map +1 -1
  189. package/dist/internal/cursor-agent-template.js +2 -0
  190. package/dist/internal/deploy-client.d.ts +17 -0
  191. package/dist/internal/deploy-client.d.ts.map +1 -1
  192. package/dist/internal/deploy-client.js +31 -10
  193. package/dist/internal/env-file.d.ts +19 -0
  194. package/dist/internal/env-file.d.ts.map +1 -0
  195. package/dist/internal/env-file.js +90 -0
  196. package/dist/internal/framework-file-storage.d.ts +61 -0
  197. package/dist/internal/framework-file-storage.d.ts.map +1 -0
  198. package/dist/internal/framework-file-storage.js +210 -0
  199. package/dist/internal/framework-storage-selection.d.ts +11 -5
  200. package/dist/internal/framework-storage-selection.d.ts.map +1 -1
  201. package/dist/internal/framework-storage-selection.js +38 -11
  202. package/dist/internal/hosted-delivery-protocol.d.ts +7 -0
  203. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
  204. package/dist/internal/hosted-delivery-protocol.js +7 -0
  205. package/dist/internal/hosted-delivery.d.ts +13 -0
  206. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  207. package/dist/internal/hosted-delivery.js +64 -19
  208. package/dist/internal/hosted-execution-diag.d.ts +48 -0
  209. package/dist/internal/hosted-execution-diag.d.ts.map +1 -0
  210. package/dist/internal/hosted-execution-diag.js +150 -0
  211. package/dist/internal/http-channel.d.ts.map +1 -1
  212. package/dist/internal/http-channel.js +81 -1
  213. package/dist/internal/init-project.d.ts.map +1 -1
  214. package/dist/internal/init-project.js +4 -0
  215. package/dist/internal/install-cursor-skills.d.ts.map +1 -1
  216. package/dist/internal/install-cursor-skills.js +1 -3
  217. package/dist/internal/logs-client.d.ts +5 -0
  218. package/dist/internal/logs-client.d.ts.map +1 -1
  219. package/dist/internal/logs-client.js +5 -0
  220. package/dist/internal/managed-delivery.d.ts +80 -0
  221. package/dist/internal/managed-delivery.d.ts.map +1 -0
  222. package/dist/internal/managed-delivery.js +86 -0
  223. package/dist/internal/mcp-endpoint.js +2 -3
  224. package/dist/internal/mcp-host.d.ts +10 -0
  225. package/dist/internal/mcp-host.d.ts.map +1 -1
  226. package/dist/internal/mcp-host.js +57 -8
  227. package/dist/internal/mcp-oauth-on-demand.d.ts +68 -0
  228. package/dist/internal/mcp-oauth-on-demand.d.ts.map +1 -0
  229. package/dist/internal/mcp-oauth-on-demand.js +287 -0
  230. package/dist/internal/mcp-oauth-persist.d.ts +42 -0
  231. package/dist/internal/mcp-oauth-persist.d.ts.map +1 -0
  232. package/dist/internal/mcp-oauth-persist.js +92 -0
  233. package/dist/internal/mcp-oauth.d.ts +1 -0
  234. package/dist/internal/mcp-oauth.d.ts.map +1 -1
  235. package/dist/internal/mcp-oauth.js +10 -2
  236. package/dist/internal/otel/collector.d.ts.map +1 -1
  237. package/dist/internal/otel/collector.js +22 -9
  238. package/dist/internal/runtime-dispatch-runner.d.ts +5 -1
  239. package/dist/internal/runtime-dispatch-runner.d.ts.map +1 -1
  240. package/dist/internal/runtime-dispatch-runner.js +7 -0
  241. package/dist/internal/sdk-runner.d.ts +11 -0
  242. package/dist/internal/sdk-runner.d.ts.map +1 -1
  243. package/dist/internal/sdk-runner.js +39 -8
  244. package/dist/internal/server.d.ts +3 -0
  245. package/dist/internal/server.d.ts.map +1 -1
  246. package/dist/internal/server.js +49 -21
  247. package/dist/internal/session-engine.d.ts +101 -3
  248. package/dist/internal/session-engine.d.ts.map +1 -1
  249. package/dist/internal/session-engine.js +577 -46
  250. package/dist/internal/sessions-client.d.ts +9 -7
  251. package/dist/internal/sessions-client.d.ts.map +1 -1
  252. package/dist/internal/sessions-client.js +3 -1
  253. package/dist/internal/steering.d.ts +15 -0
  254. package/dist/internal/steering.d.ts.map +1 -0
  255. package/dist/internal/steering.js +18 -0
  256. package/dist/internal/storage-coordinator.d.ts +7 -0
  257. package/dist/internal/storage-coordinator.d.ts.map +1 -1
  258. package/dist/internal/storage-coordinator.js +28 -5
  259. package/dist/internal/storage-roles.d.ts +5 -0
  260. package/dist/internal/storage-roles.d.ts.map +1 -1
  261. package/dist/internal/stream-progress.d.ts.map +1 -1
  262. package/dist/internal/stream-progress.js +10 -0
  263. package/dist/internal/tool-policy.d.ts +9 -1
  264. package/dist/internal/tool-policy.d.ts.map +1 -1
  265. package/dist/internal/tool-policy.js +13 -0
  266. package/dist/internal/trajectory.d.ts.map +1 -1
  267. package/dist/internal/trajectory.js +10 -0
  268. package/dist/internal/turn-outbox.d.ts +24 -0
  269. package/dist/internal/turn-outbox.d.ts.map +1 -0
  270. package/dist/internal/turn-outbox.js +80 -0
  271. package/dist/playground/assets/{index-CZA1uEWA.js → index-DrkI6y5O.js} +51 -51
  272. package/dist/playground/assets/index-DzNGwm7q.css +1 -0
  273. package/dist/playground/index.html +2 -2
  274. package/dist/storage-backends/cursor-hosted.d.ts +9 -6
  275. package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
  276. package/dist/storage-backends/cursor-hosted.js +16 -3
  277. package/dist/storage.d.ts +8 -0
  278. package/dist/storage.d.ts.map +1 -1
  279. package/dist/types.d.ts +65 -8
  280. package/dist/types.d.ts.map +1 -1
  281. package/docs/README.md +7 -3
  282. package/docs/deployment.md +5 -4
  283. package/docs/guides/mcp-oauth.md +26 -8
  284. package/docs/guides/slack.md +93 -202
  285. package/docs/reference/agent-config.md +2 -2
  286. package/docs/reference/cli.md +39 -16
  287. package/docs/reference/connections.md +6 -3
  288. package/docs/reference/http-api.md +2 -1
  289. package/docs/reference/sessions.md +4 -2
  290. package/docs/reference/tools.md +9 -2
  291. package/docs/templates/agents-md.md +110 -0
  292. package/docs/templates/code-wiki.md +96 -0
  293. package/docs/troubleshooting.md +2 -2
  294. package/package.json +2 -2
  295. package/skills/ab/SKILL.md +13 -97
  296. package/skills/create-agent/SKILL.md +124 -223
  297. package/skills/debug/SKILL.md +34 -68
  298. package/skills/evals/SKILL.md +55 -180
  299. package/skills/framework-map/SKILL.md +83 -145
  300. package/skills/github/SKILL.md +53 -111
  301. package/skills/hillclimb/SKILL.md +40 -163
  302. package/skills/mcp-auth/SKILL.md +51 -107
  303. package/skills/otel/SKILL.md +22 -68
  304. package/skills/setup-slack/SKILL.md +91 -212
  305. package/src/bin/agent-serve.ts +13 -1
  306. package/src/channels/deployments/types.ts +1 -0
  307. package/src/channels/origin/api.ts +264 -33
  308. package/src/channels/origin/binding.ts +57 -28
  309. package/src/channels/origin/checks.ts +6 -6
  310. package/src/channels/origin/cursor-account.ts +5 -3
  311. package/src/channels/origin/index.ts +1 -0
  312. package/src/channels/origin/origin-channel.ts +4 -0
  313. package/src/channels/origin/reactions.ts +82 -0
  314. package/src/channels/origin/types.ts +11 -0
  315. package/src/channels/slack/api.ts +41 -5
  316. package/src/channels/slack/approvals.ts +105 -0
  317. package/src/channels/slack/cli-project.ts +267 -0
  318. package/src/channels/slack/defaults.ts +122 -93
  319. package/src/channels/slack/dispatch.ts +56 -22
  320. package/src/channels/slack/inbound.ts +43 -0
  321. package/src/channels/slack/init.ts +10 -5
  322. package/src/channels/slack/interactive.ts +35 -9
  323. package/src/channels/slack/live-delivery.ts +235 -114
  324. package/src/channels/slack/manifest.ts +6 -2
  325. package/src/channels/slack/nudge-carrier.ts +48 -1
  326. package/src/channels/slack/setup.ts +10 -6
  327. package/src/channels/slack/slack-channel.ts +3 -0
  328. package/src/channels/slack/tool-approval-events.ts +93 -0
  329. package/src/evals/run-facts.ts +32 -0
  330. package/src/files-backends/cursor-hosted.ts +40 -7
  331. package/src/internal/advertise-tools.ts +49 -12
  332. package/src/internal/approval-gate.ts +20 -29
  333. package/src/internal/bounded.ts +28 -0
  334. package/src/internal/chat-client.ts +19 -0
  335. package/src/internal/cli-deploy.ts +91 -9
  336. package/src/internal/cli-mcp-oauth.ts +7 -21
  337. package/src/internal/cli-slack-manual.ts +350 -18
  338. package/src/internal/cli-slack.ts +40 -84
  339. package/src/internal/conversation-mirror.ts +145 -69
  340. package/src/internal/cursor/account-mcp.ts +21 -0
  341. package/src/internal/cursor/backend-client.ts +34 -58
  342. package/src/internal/cursor/session-token.ts +115 -0
  343. package/src/internal/cursor-agent-template.ts +2 -0
  344. package/src/internal/deploy-client.ts +43 -0
  345. package/src/internal/env-file.ts +84 -0
  346. package/src/internal/framework-file-storage.ts +228 -0
  347. package/src/internal/framework-storage-selection.ts +51 -11
  348. package/src/internal/hosted-delivery-protocol.ts +7 -0
  349. package/src/internal/hosted-delivery.ts +107 -24
  350. package/src/internal/hosted-execution-diag.ts +207 -0
  351. package/src/internal/http-channel.ts +99 -0
  352. package/src/internal/init-project.ts +4 -0
  353. package/src/internal/install-cursor-skills.ts +1 -4
  354. package/src/internal/logs-client.ts +5 -0
  355. package/src/internal/managed-delivery.ts +125 -0
  356. package/src/internal/mcp-endpoint.ts +13 -4
  357. package/src/internal/mcp-host.ts +77 -11
  358. package/src/internal/mcp-oauth-on-demand.ts +352 -0
  359. package/src/internal/mcp-oauth-persist.ts +127 -0
  360. package/src/internal/mcp-oauth.ts +17 -1
  361. package/src/internal/otel/collector.ts +30 -0
  362. package/src/internal/runtime-dispatch-runner.ts +10 -0
  363. package/src/internal/sdk-runner.ts +56 -8
  364. package/src/internal/server.ts +61 -9
  365. package/src/internal/session-engine.ts +723 -60
  366. package/src/internal/sessions-client.ts +17 -8
  367. package/src/internal/steering.ts +17 -0
  368. package/src/internal/storage-coordinator.ts +38 -8
  369. package/src/internal/storage-roles.ts +7 -0
  370. package/src/internal/stream-progress.ts +19 -0
  371. package/src/internal/tool-policy.ts +18 -0
  372. package/src/internal/trajectory.ts +10 -0
  373. package/src/internal/turn-outbox.ts +85 -0
  374. package/src/storage-backends/cursor-hosted.ts +22 -8
  375. package/src/storage.ts +12 -0
  376. package/src/types.ts +70 -9
  377. package/templates/agents-md/README.md +39 -0
  378. package/templates/agents-md/agent/agent.ts +8 -0
  379. package/templates/agents-md/agent/channels/github.ts +10 -0
  380. package/templates/agents-md/agent/channels/queue.ts +28 -0
  381. package/templates/agents-md/agent/channels/slack.ts +9 -0
  382. package/templates/agents-md/agent/instructions.md +39 -0
  383. package/templates/agents-md/agent/lib/collect.ts +439 -0
  384. package/templates/agents-md/agent/lib/config.ts +8 -0
  385. package/templates/agents-md/agent/lib/paths.ts +51 -0
  386. package/templates/agents-md/agent/schedules/weekly.ts +17 -0
  387. package/templates/agents-md/agent/tools/apply_agents.ts +226 -0
  388. package/templates/agents-md/evals/agents.eval.ts +135 -0
  389. package/templates/agents-md/evals/evals.config.ts +5 -0
  390. package/templates/agents-md/init.json +38 -0
  391. package/templates/agents-md/package.json +18 -0
  392. package/templates/agents-md/tsconfig.json +12 -0
  393. package/templates/code-wiki/README.md +34 -0
  394. package/templates/code-wiki/agent/agent.ts +8 -0
  395. package/templates/code-wiki/agent/channels/github.ts +144 -0
  396. package/templates/code-wiki/agent/instructions.md +39 -0
  397. package/templates/code-wiki/agent/lib/repos.ts +5 -0
  398. package/templates/code-wiki/agent/lib/wiki.ts +22 -0
  399. package/templates/code-wiki/agent/tools/apply_wiki.ts +219 -0
  400. package/templates/code-wiki/evals/evals.config.ts +5 -0
  401. package/templates/code-wiki/evals/wiki.eval.ts +132 -0
  402. package/templates/code-wiki/init.json +25 -0
  403. package/templates/code-wiki/package.json +18 -0
  404. package/templates/code-wiki/tsconfig.json +12 -0
  405. package/dist/docs/assets/chunks/@localSearchIndexroot.oqPawjiD.js +0 -1
  406. package/dist/docs/assets/guides_slack.md.C32HsdKk.js +0 -38
  407. package/dist/docs/assets/guides_slack.md.C32HsdKk.lean.js +0 -1
  408. package/dist/docs/assets/index.md.BoHaMdeZ.js +0 -5
  409. package/dist/docs/assets/reference_sessions.md.D0mIh4KK.js +0 -1
  410. package/dist/docs/assets/troubleshooting.md.Ctv3T8C2.js +0 -1
  411. package/dist/docs/design/agsh.md +0 -406
  412. package/dist/internal/deployment-scm-event-stream.d.ts +0 -116
  413. package/dist/internal/deployment-scm-event-stream.d.ts.map +0 -1
  414. package/dist/internal/deployment-scm-event-stream.js +0 -474
  415. package/dist/playground/assets/index-CF7hUDnQ.css +0 -1
  416. package/docs/design/agsh.md +0 -406
  417. package/src/internal/deployment-scm-event-stream.ts +0 -593
  418. /package/dist/docs/assets/{deployment.md.D9msOFOW.lean.js → deployment.md.MFPKqsqI.lean.js} +0 -0
  419. /package/dist/docs/assets/{reference_agent-config.md.Cp_x38Nl.lean.js → reference_agent-config.md.BHeYMgme.lean.js} +0 -0
  420. /package/dist/docs/assets/{reference_connections.md.BH8Oc0D0.lean.js → reference_connections.md.DxldvyIB.lean.js} +0 -0
  421. /package/dist/docs/assets/{reference_http-api.md.D89k1mdm.lean.js → reference_http-api.md.5zOAbV86.lean.js} +0 -0
  422. /package/dist/docs/assets/{reference_sessions.md.D0mIh4KK.lean.js → reference_sessions.md.NxFP_CAC.lean.js} +0 -0
  423. /package/dist/docs/assets/{reference_tools.md.BHeXn2id.lean.js → reference_tools.md.B84gw9Ii.lean.js} +0 -0
  424. /package/dist/docs/assets/{troubleshooting.md.Ctv3T8C2.lean.js → troubleshooting.md.DCiPBhYs.lean.js} +0 -0
@@ -0,0 +1,226 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import type { HostGitHubClient } from "@cursor/july";
4
+ import { defineTool } from "@cursor/july/tools";
5
+ import { z } from "zod";
6
+ import { agentsPath, parseRepo, updateBranch } from "../lib/paths.js";
7
+
8
+ const file = z.object({
9
+ path: z.string().min(1).max(240),
10
+ content: z.string().min(1).max(64_000),
11
+ });
12
+
13
+ type File = z.infer<typeof file>;
14
+ type Octokit = Awaited<ReturnType<HostGitHubClient["getOctokit"]>>;
15
+
16
+ type Write = {
17
+ octokit: Octokit;
18
+ owner: string;
19
+ repo: string;
20
+ window: string;
21
+ reason: string;
22
+ files: File[];
23
+ base: string;
24
+ branch: string;
25
+ };
26
+
27
+ export default defineTool({
28
+ description:
29
+ "Skip or open an AGENTS.md follow-up PR for this weekly review. Call once.",
30
+ needsApproval: (input) => input.verdict === "update",
31
+ effect: (input) => (input.verdict === "update" ? "write" : "read"),
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
+ files: z.array(file).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 dir = ctx.workspaceDir;
51
+ const repo = parseRepo(await readTrimmed(dir, "week/repo.txt"));
52
+ const base = await readTrimmed(dir, "week/base.ref");
53
+ const window = await readTrimmed(dir, "week/window.txt");
54
+ const branch = updateBranch(base);
55
+ if (repo === undefined || branch === undefined || window === "") {
56
+ throw new Error("missing week/repo.txt, week/base.ref, or week/window.txt");
57
+ }
58
+ const files = input.files.map((item) => {
59
+ const path = agentsPath(item.path);
60
+ if (path === undefined) {
61
+ throw new Error(`invalid AGENTS.md path: ${item.path}`);
62
+ }
63
+ return { path, content: item.content };
64
+ });
65
+ return openAgentsPr({
66
+ octokit: await ctx.host.github.getOctokit(),
67
+ owner: repo.owner,
68
+ repo: repo.repo,
69
+ window,
70
+ reason: input.reason,
71
+ files,
72
+ base,
73
+ branch,
74
+ });
75
+ },
76
+ });
77
+
78
+ async function openAgentsPr(input: Write) {
79
+ const repo = { owner: input.owner, repo: input.repo };
80
+ const existing = await input.octokit.rest.pulls.list({
81
+ ...repo,
82
+ state: "open",
83
+ head: `${input.owner}:${input.branch}`,
84
+ base: input.base,
85
+ per_page: 1,
86
+ });
87
+ const open = existing.data[0];
88
+ if (open !== undefined && citesWindow(open.body, input.window)) {
89
+ return {
90
+ posted: false,
91
+ reason: "exists",
92
+ verdict: "update",
93
+ window: input.window,
94
+ url: open.html_url,
95
+ };
96
+ }
97
+ const branchSha = await refSha(input.octokit, repo, input.branch);
98
+ const parent = branchSha ?? (await refSha(input.octokit, repo, input.base));
99
+ if (parent === undefined) {
100
+ throw new Error(`missing base ref: ${input.base}`);
101
+ }
102
+ const { data: commit } = await input.octokit.rest.git.getCommit({
103
+ ...repo,
104
+ commit_sha: parent,
105
+ });
106
+ const blobs = await Promise.all(
107
+ input.files.map(async (item) => {
108
+ const { data } = await input.octokit.rest.git.createBlob({
109
+ ...repo,
110
+ content: Buffer.from(item.content).toString("base64"),
111
+ encoding: "base64",
112
+ });
113
+ return {
114
+ path: item.path,
115
+ mode: "100644" as const,
116
+ type: "blob" as const,
117
+ sha: data.sha,
118
+ };
119
+ })
120
+ );
121
+ const { data: tree } = await input.octokit.rest.git.createTree({
122
+ ...repo,
123
+ base_tree: commit.tree.sha,
124
+ tree: blobs,
125
+ });
126
+ const { data: next } = await input.octokit.rest.git.createCommit({
127
+ ...repo,
128
+ message: `agents.md: ${input.reason}`,
129
+ tree: tree.sha,
130
+ parents: [parent],
131
+ });
132
+ if (branchSha === undefined) {
133
+ await input.octokit.rest.git.createRef({
134
+ ...repo,
135
+ ref: `refs/heads/${input.branch}`,
136
+ sha: next.sha,
137
+ });
138
+ } else {
139
+ await input.octokit.rest.git.updateRef({
140
+ ...repo,
141
+ ref: `heads/${input.branch}`,
142
+ sha: next.sha,
143
+ });
144
+ }
145
+ if (open !== undefined) {
146
+ await input.octokit.rest.pulls.update({
147
+ ...repo,
148
+ pull_number: open.number,
149
+ body: appendWindow(open.body ?? "", input.reason, input.window),
150
+ });
151
+ return {
152
+ posted: true,
153
+ verdict: "update",
154
+ window: input.window,
155
+ url: open.html_url,
156
+ };
157
+ }
158
+ const { data: pull } = await input.octokit.rest.pulls.create({
159
+ ...repo,
160
+ title: `agents.md: update for ${input.window}`,
161
+ head: input.branch,
162
+ base: input.base,
163
+ draft: true,
164
+ body: pullBody(input.reason, input.window),
165
+ });
166
+ return {
167
+ posted: true,
168
+ verdict: "update",
169
+ window: input.window,
170
+ url: pull.html_url,
171
+ };
172
+ }
173
+
174
+ async function readTrimmed(dir: string, rel: string): Promise<string> {
175
+ return (await readFile(join(dir, rel), "utf8")).trim();
176
+ }
177
+
178
+ async function refSha(
179
+ octokit: Octokit,
180
+ repo: { owner: string; repo: string },
181
+ name: string
182
+ ): Promise<string | undefined> {
183
+ try {
184
+ const { data } = await octokit.rest.git.getRef({
185
+ ...repo,
186
+ ref: `heads/${name}`,
187
+ });
188
+ return data.object.sha;
189
+ } catch (error) {
190
+ if (isNotFound(error)) {
191
+ return undefined;
192
+ }
193
+ throw error;
194
+ }
195
+ }
196
+
197
+ function pullBody(reason: string, window: string): string {
198
+ return `${reason}
199
+
200
+ Window: ${window}
201
+
202
+ This pull request rewrites AGENTS.md. Those files are always-applied agent instructions. Review the bodies, then mark the draft ready and merge.`;
203
+ }
204
+
205
+ function citesWindow(body: string | null | undefined, window: string): boolean {
206
+ return new RegExp(
207
+ `(?:^|\\n)Window: ${escapeRegExp(window)}(?:\\s|$)`
208
+ ).test(body ?? "");
209
+ }
210
+
211
+ function appendWindow(body: string, reason: string, window: string): string {
212
+ return `${body.trim()}\n\n${reason}\nWindow: ${window}`;
213
+ }
214
+
215
+ function escapeRegExp(value: string): string {
216
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
217
+ }
218
+
219
+ function isNotFound(error: unknown): boolean {
220
+ return (
221
+ typeof error === "object" &&
222
+ error !== null &&
223
+ "status" in error &&
224
+ error.status === 404
225
+ );
226
+ }
@@ -0,0 +1,135 @@
1
+ import { defineEval } from "@cursor/july/evals";
2
+
3
+ const WINDOW = "2026-08-26/2026-09-02";
4
+
5
+ function weekly(): string {
6
+ return [
7
+ `Weekly AGENTS.md review for acme/api (${WINDOW}).`,
8
+ "Read week/ and week/tree/. Call apply_agents once.",
9
+ ].join("\n");
10
+ }
11
+
12
+ const AGENTS = [
13
+ "# API",
14
+ "",
15
+ "Usage events are protobuf messages in `proto/billing.proto`.",
16
+ "Do not add ad-hoc billing columns on the request path.",
17
+ "",
18
+ ].join("\n");
19
+
20
+ const CHORE = [
21
+ "# Merged pull requests",
22
+ "",
23
+ "## #12 Fix sidebar opener lint failure",
24
+ "url: https://github.com/acme/api/pull/12",
25
+ "author: @sam",
26
+ "merged: 2026-08-28T16:00:00Z",
27
+ "files: src/sidebar.ts",
28
+ "",
29
+ "Quote style only.",
30
+ "",
31
+ ].join("\n");
32
+
33
+ const RULE = [
34
+ "# Merged pull requests",
35
+ "",
36
+ "## #18 Route every billing write through UsageEvent",
37
+ "url: https://github.com/acme/api/pull/18",
38
+ "author: @sam",
39
+ "merged: 2026-08-29T18:00:00Z",
40
+ "files: proto/billing.proto, src/billing.ts",
41
+ "",
42
+ "Adds usage_unit and workspace_id to UsageEvent.",
43
+ "",
44
+ "### comments",
45
+ "- @lee: always put new billing fields on UsageEvent. no request-path columns.",
46
+ "",
47
+ ].join("\n");
48
+
49
+ const SLACK = [
50
+ "## #eng-api",
51
+ "- <@U1>: lunch at 12",
52
+ "- <@U2>: yes, every new billing field goes on UsageEvent from now on",
53
+ "",
54
+ ].join("\n");
55
+
56
+ export default defineEval({
57
+ tags: ["smoke"],
58
+ cases: [
59
+ {
60
+ id: "skip-chore",
61
+ description: "A lint-only week does not open an AGENTS.md PR.",
62
+ async test(t) {
63
+ await t.send(weekly(), {
64
+ workspaceFiles: {
65
+ "week/window.txt": `${WINDOW}\n`,
66
+ "week/repo.txt": "acme/api\n",
67
+ "week/base.ref": "main\n",
68
+ "week/files.txt": "AGENTS.md\n",
69
+ "week/prs.md": CHORE,
70
+ "week/slack.md": "## #eng-api\n- <@U1>: lunch at 12\n",
71
+ "week/tree/AGENTS.md.txt": AGENTS,
72
+ },
73
+ });
74
+ t.succeeded();
75
+ t.calledTool("apply_agents", { input: { verdict: "skip" } });
76
+ },
77
+ },
78
+ {
79
+ id: "update-rule",
80
+ description: "A repeated billing rule parks the AGENTS.md write.",
81
+ async test(t) {
82
+ await t.send(weekly(), {
83
+ workspaceFiles: {
84
+ "week/window.txt": `${WINDOW}\n`,
85
+ "week/repo.txt": "acme/api\n",
86
+ "week/base.ref": "main\n",
87
+ "week/files.txt": "AGENTS.md\n",
88
+ "week/prs.md": RULE,
89
+ "week/slack.md": SLACK,
90
+ "week/tree/AGENTS.md.txt": "# API\n\nKeep handlers thin.\n",
91
+ },
92
+ });
93
+ t.parked();
94
+ t.calledTool("apply_agents", { input: { verdict: "update" } });
95
+ },
96
+ },
97
+ {
98
+ id: "skip-known",
99
+ description: "A rule already in AGENTS.md stays quiet.",
100
+ async test(t) {
101
+ await t.send(weekly(), {
102
+ workspaceFiles: {
103
+ "week/window.txt": `${WINDOW}\n`,
104
+ "week/repo.txt": "acme/api\n",
105
+ "week/base.ref": "main\n",
106
+ "week/files.txt": "AGENTS.md\n",
107
+ "week/prs.md": RULE,
108
+ "week/slack.md": SLACK,
109
+ "week/tree/AGENTS.md.txt": AGENTS,
110
+ },
111
+ });
112
+ t.succeeded();
113
+ t.calledTool("apply_agents", { input: { verdict: "skip" } });
114
+ },
115
+ },
116
+ {
117
+ id: "skip-empty",
118
+ description: "An empty week does not open an AGENTS.md PR.",
119
+ async test(t) {
120
+ await t.send(weekly(), {
121
+ workspaceFiles: {
122
+ "week/window.txt": `${WINDOW}\n`,
123
+ "week/repo.txt": "acme/api\n",
124
+ "week/base.ref": "main\n",
125
+ "week/files.txt": "\n",
126
+ "week/prs.md": "No merged pull requests this week.\n",
127
+ "week/slack.md": "No Slack channels configured.\n",
128
+ },
129
+ });
130
+ t.succeeded();
131
+ t.calledTool("apply_agents", { input: { verdict: "skip" } });
132
+ },
133
+ },
134
+ ],
135
+ });
@@ -0,0 +1,5 @@
1
+ import { defineEvalConfig } from "@cursor/july/evals";
2
+
3
+ export default defineEvalConfig({
4
+ maxConcurrency: 10,
5
+ });
@@ -0,0 +1,38 @@
1
+ {
2
+ "questions": [
3
+ {
4
+ "id": "repos",
5
+ "prompt": "Which GitHub repo should this agent maintain AGENTS.md for?",
6
+ "hint": "One owner/repo. Init once per app.",
7
+ "placeholder": "acme/api",
8
+ "parse": "owner-repo-list"
9
+ },
10
+ {
11
+ "id": "slack",
12
+ "prompt": "Which Slack channels should this agent read?",
13
+ "hint": "Comma-separated #names or channel ids. Invite the bot, including to private channels. Use none to skip Slack.",
14
+ "placeholder": "#eng-api, #api-private",
15
+ "default": "none"
16
+ }
17
+ ],
18
+ "replace": [
19
+ {
20
+ "file": "agent/lib/config.ts",
21
+ "find": "[\"owner/repo\"]",
22
+ "answer": "repos",
23
+ "as": "json-array"
24
+ },
25
+ {
26
+ "file": "agent/lib/config.ts",
27
+ "find": "[\"#eng\"]",
28
+ "answer": "slack",
29
+ "as": "json-array"
30
+ },
31
+ {
32
+ "file": "README.md",
33
+ "find": "owner/repo",
34
+ "answer": "repos",
35
+ "as": "first"
36
+ }
37
+ ]
38
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "agents-md",
3
+ "private": true,
4
+ "type": "module",
5
+ "description": "Keeps AGENTS.md current from last week's merged PRs and Slack.",
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
+ }
@@ -0,0 +1,34 @@
1
+ # Code wiki
2
+
3
+ Keeps `wiki/` pages current after a pull request merges. Opens a
4
+ follow-up PR against that merge's base when a durable fact changed.
5
+ Skips chores. Same-base updates stack on `wiki/<base>`.
6
+
7
+ ```bash
8
+ npx @cursor/july init ./code-wiki --template code-wiki
9
+ ```
10
+
11
+ `init` asks which repos to watch. Skip the prompt with
12
+ `--var repos=owner/repo`.
13
+
14
+ ## Run
15
+
16
+ Connect GitHub in Cursor for those repos. Then sign the host in:
17
+
18
+ ```bash
19
+ agent-sdk login
20
+ agent-sdk dev
21
+ ```
22
+
23
+ Events and API calls use your Cursor GitHub connection. Replay a merged PR:
24
+
25
+ ```bash
26
+ agent-sdk github replay https://github.com/owner/repo/pull/1 --dir . --action closed
27
+ ```
28
+
29
+ ## Files
30
+
31
+ - `agent/lib/repos.ts`: watched repos
32
+ - `agent/lib/wiki.ts`: wiki path rules
33
+ - `agent/instructions.md`: what counts as a wiki update
34
+ - `evals/wiki.eval.ts`: skip and update smoke cases
@@ -0,0 +1,8 @@
1
+ import { defineAgent } from "@cursor/july";
2
+
3
+ export default defineAgent({
4
+ tools: ["read", "grep"],
5
+ local: {
6
+ sandbox: true,
7
+ },
8
+ });
@@ -0,0 +1,144 @@
1
+ import type { HostGitHubClient } from "@cursor/july";
2
+ import {
3
+ defaultGitHubAuth,
4
+ githubChannel,
5
+ } from "@cursor/july/channels/github";
6
+ import { REPOS, watches } from "../lib/repos.js";
7
+ import { WIKI_DIR, isWikiPath } from "../lib/wiki.js";
8
+
9
+ const MAX_DIFF_CHARS = 150_000;
10
+ const MAX_WIKI_PAGES = 40;
11
+ const LIST_FILES_CAP = 3000;
12
+
13
+ type Octokit = Awaited<ReturnType<HostGitHubClient["getOctokit"]>>;
14
+
15
+ export default githubChannel({
16
+ cursorAccount: { repos: REPOS, permissions: "contents-write" },
17
+ deliverReplies: false,
18
+ onComment: () => null,
19
+ onPullRequest: async (ctx, pr) => {
20
+ if (!watches(ctx.repository.fullName)) {
21
+ return null;
22
+ }
23
+ if (pr.action !== "closed" || !pr.merged) {
24
+ return null;
25
+ }
26
+ if (pr.headRef.startsWith(`${WIKI_DIR}/`)) {
27
+ return null;
28
+ }
29
+ const octokit = await ctx.github.getOctokit();
30
+ const pull = {
31
+ owner: ctx.repository.owner,
32
+ repo: ctx.repository.name,
33
+ pull_number: pr.number,
34
+ };
35
+ const listed = await octokit.paginate(octokit.rest.pulls.listFiles, {
36
+ ...pull,
37
+ per_page: 100,
38
+ });
39
+ const files = listed.map((file) => file.filename);
40
+ if (
41
+ files.length > 0 &&
42
+ files.length < LIST_FILES_CAP &&
43
+ files.every(isWikiPath)
44
+ ) {
45
+ return null;
46
+ }
47
+ return {
48
+ auth: defaultGitHubAuth(ctx),
49
+ context: [
50
+ "This pull request merged. Read pr/files.txt, pr/diff.patch, and wiki/.",
51
+ ],
52
+ async workspaceFiles() {
53
+ const [diff, wiki] = await Promise.all([
54
+ octokit.rest.pulls.get({ ...pull, mediaType: { format: "diff" } }),
55
+ loadWiki(octokit, pull.owner, pull.repo, pr.baseRef),
56
+ ]);
57
+ const text = String(diff.data);
58
+ return {
59
+ "pr/base.ref": `${pr.baseRef}\n`,
60
+ "pr/files.txt": `${files.join("\n")}\n`,
61
+ "pr/diff.patch":
62
+ text.length > MAX_DIFF_CHARS
63
+ ? `${text.slice(0, MAX_DIFF_CHARS)}\n…[truncated]\n`
64
+ : text,
65
+ ...wiki,
66
+ };
67
+ },
68
+ };
69
+ },
70
+ });
71
+
72
+ async function loadWiki(
73
+ octokit: Octokit,
74
+ owner: string,
75
+ repo: string,
76
+ ref: string
77
+ ): Promise<Record<string, string>> {
78
+ const listed = await readContents(octokit, {
79
+ owner,
80
+ repo,
81
+ path: WIKI_DIR,
82
+ ref,
83
+ });
84
+ if (!Array.isArray(listed)) {
85
+ return { "wiki/pages.txt": "" };
86
+ }
87
+ const markdown = listed.filter(
88
+ (item) => item.type === "file" && item.name.endsWith(".md")
89
+ );
90
+ const truncated = markdown.length > MAX_WIKI_PAGES;
91
+ const files = markdown.slice(0, MAX_WIKI_PAGES);
92
+ const pages: Record<string, string> = {};
93
+ await Promise.all(
94
+ files.map(async (file) => {
95
+ const body = await readContents(octokit, {
96
+ owner,
97
+ repo,
98
+ path: `${WIKI_DIR}/${file.name}`,
99
+ ref,
100
+ });
101
+ if (
102
+ body === undefined ||
103
+ Array.isArray(body) ||
104
+ body.encoding !== "base64" ||
105
+ typeof body.content !== "string"
106
+ ) {
107
+ return;
108
+ }
109
+ pages[`${WIKI_DIR}/${file.name}`] = Buffer.from(
110
+ body.content,
111
+ "base64"
112
+ ).toString("utf8");
113
+ })
114
+ );
115
+ const names = Object.keys(pages).sort();
116
+ pages["wiki/pages.txt"] = truncated
117
+ ? `${names.join("\n")}\n…[truncated]\n`
118
+ : `${names.join("\n")}\n`;
119
+ return pages;
120
+ }
121
+
122
+ async function readContents(
123
+ octokit: Octokit,
124
+ args: { owner: string; repo: string; path: string; ref: string }
125
+ ) {
126
+ try {
127
+ const { data } = await octokit.rest.repos.getContent(args);
128
+ return data;
129
+ } catch (error) {
130
+ if (isNotFound(error)) {
131
+ return undefined;
132
+ }
133
+ throw error;
134
+ }
135
+ }
136
+
137
+ function isNotFound(error: unknown): boolean {
138
+ return (
139
+ typeof error === "object" &&
140
+ error !== null &&
141
+ "status" in error &&
142
+ error.status === 404
143
+ );
144
+ }
@@ -0,0 +1,39 @@
1
+ # Code wiki
2
+
3
+ You keep the in-repo wiki current after a pull request merges.
4
+
5
+ ## Read
6
+
7
+ The workspace has `pr/files.txt`, `pr/diff.patch`, and `wiki/`.
8
+ `wiki/pages.txt` lists existing pages. Missing pages mean the wiki is
9
+ empty. Read the file list and the pages that own the change. Use the
10
+ diff only to test a fact.
11
+
12
+ ## Decide
13
+
14
+ Update only when the merge changes a durable fact someone would look
15
+ up later: how a system works, a public or operator contract, a default
16
+ or ownership change, a removed feature.
17
+
18
+ An empty wiki is not a license to document the whole repo. Create a
19
+ page only for a durable contract in this merge.
20
+
21
+ Skip lint, format, lockfiles, dependency pins, tests-only, cherry-picks,
22
+ backports, telemetry-only changes, one-off bug fixes that leave the
23
+ described behavior the same, knobs the wiki never mentioned, and facts
24
+ the matching page already states.
25
+
26
+ Do not write a changelog or a PR list.
27
+
28
+ ## Write
29
+
30
+ Call `apply_wiki` once.
31
+
32
+ - Skip: `{ verdict: "skip", reason }` with one line.
33
+ - Update: `{ verdict: "update", reason, pages }` with full page bodies.
34
+
35
+ Pages stay under `wiki/`, flat, `*.md`. Keep `_index.md` in sync when
36
+ you add a page. Each catalog line names the page and the paths it owns.
37
+ Short declarative sentences. Edit only the stale or missing facts.
38
+
39
+ Reply with `skip` or `update` and the reason.
@@ -0,0 +1,5 @@
1
+ export const REPOS: readonly string[] = ["owner/repo"];
2
+
3
+ export function watches(fullName: string): boolean {
4
+ return REPOS.some((repo) => repo.toLowerCase() === fullName.toLowerCase());
5
+ }
@@ -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
+ }