@runcore-sh/runcore 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (351) hide show
  1. package/dictionary.json +2 -2
  2. package/dist/activity/log.js +2 -2
  3. package/dist/activity/log.js.map +1 -1
  4. package/dist/agents/governed-spawn.d.ts.map +1 -1
  5. package/dist/cli.js +101 -11
  6. package/dist/cli.js.map +1 -1
  7. package/dist/extensions/cache.d.ts +57 -0
  8. package/dist/extensions/cache.d.ts.map +1 -0
  9. package/dist/extensions/cache.js +173 -0
  10. package/dist/extensions/cache.js.map +1 -0
  11. package/dist/extensions/client.d.ts +55 -0
  12. package/dist/extensions/client.d.ts.map +1 -0
  13. package/dist/extensions/client.js +120 -0
  14. package/dist/extensions/client.js.map +1 -0
  15. package/dist/extensions/index.d.ts +13 -0
  16. package/dist/extensions/index.d.ts.map +1 -0
  17. package/dist/extensions/index.js +12 -0
  18. package/dist/extensions/index.js.map +1 -0
  19. package/dist/extensions/loader.d.ts +50 -0
  20. package/dist/extensions/loader.d.ts.map +1 -0
  21. package/dist/extensions/loader.js +166 -0
  22. package/dist/extensions/loader.js.map +1 -0
  23. package/dist/extensions/manifest.d.ts +38 -0
  24. package/dist/extensions/manifest.d.ts.map +1 -0
  25. package/dist/extensions/manifest.js +17 -0
  26. package/dist/extensions/manifest.js.map +1 -0
  27. package/dist/extensions/stubs.d.ts +27 -0
  28. package/dist/extensions/stubs.d.ts.map +1 -0
  29. package/dist/extensions/stubs.js +45 -0
  30. package/dist/extensions/stubs.js.map +1 -0
  31. package/dist/lib/audit.js +2 -2
  32. package/dist/lib/audit.js.map +1 -1
  33. package/dist/lib/brain-migrate.d.ts +21 -0
  34. package/dist/lib/brain-migrate.d.ts.map +1 -0
  35. package/dist/lib/brain-migrate.js +137 -0
  36. package/dist/lib/brain-migrate.js.map +1 -0
  37. package/dist/lib/paths.d.ts +27 -0
  38. package/dist/lib/paths.d.ts.map +1 -1
  39. package/dist/lib/paths.js +65 -0
  40. package/dist/lib/paths.js.map +1 -1
  41. package/dist/llm/call-log.d.ts +40 -0
  42. package/dist/llm/call-log.d.ts.map +1 -0
  43. package/dist/llm/call-log.js +35 -0
  44. package/dist/llm/call-log.js.map +1 -0
  45. package/dist/llm/complete.d.ts +6 -0
  46. package/dist/llm/complete.d.ts.map +1 -1
  47. package/dist/llm/complete.js +27 -0
  48. package/dist/llm/complete.js.map +1 -1
  49. package/dist/mcp-server.js +118 -2
  50. package/dist/mcp-server.js.map +1 -1
  51. package/dist/memory/file-backed.d.ts +4 -0
  52. package/dist/memory/file-backed.d.ts.map +1 -1
  53. package/dist/memory/file-backed.js +4 -0
  54. package/dist/memory/file-backed.js.map +1 -1
  55. package/dist/memory/vector-index.d.ts +4 -12
  56. package/dist/memory/vector-index.d.ts.map +1 -1
  57. package/dist/memory/vector-index.js +11 -93
  58. package/dist/memory/vector-index.js.map +1 -1
  59. package/dist/search/brain-docs.d.ts +17 -7
  60. package/dist/search/brain-docs.d.ts.map +1 -1
  61. package/dist/search/brain-docs.js +170 -52
  62. package/dist/search/brain-docs.js.map +1 -1
  63. package/dist/search/brain-rag.d.ts +45 -0
  64. package/dist/search/brain-rag.d.ts.map +1 -0
  65. package/dist/search/brain-rag.js +275 -0
  66. package/dist/search/brain-rag.js.map +1 -0
  67. package/dist/search/chunker.d.ts +24 -0
  68. package/dist/search/chunker.d.ts.map +1 -0
  69. package/dist/search/chunker.js +95 -0
  70. package/dist/search/chunker.js.map +1 -0
  71. package/dist/search/embedder.d.ts +16 -0
  72. package/dist/search/embedder.d.ts.map +1 -0
  73. package/dist/search/embedder.js +108 -0
  74. package/dist/search/embedder.js.map +1 -0
  75. package/dist/search/file-watcher.d.ts +11 -0
  76. package/dist/search/file-watcher.d.ts.map +1 -0
  77. package/dist/search/file-watcher.js +86 -0
  78. package/dist/search/file-watcher.js.map +1 -0
  79. package/dist/server.d.ts.map +1 -1
  80. package/dist/server.js +814 -472
  81. package/dist/server.js.map +1 -1
  82. package/dist/sessions/store.d.ts +9 -0
  83. package/dist/sessions/store.d.ts.map +1 -1
  84. package/dist/sessions/store.js.map +1 -1
  85. package/dist/settings.d.ts +26 -0
  86. package/dist/settings.d.ts.map +1 -1
  87. package/dist/settings.js +78 -2
  88. package/dist/settings.js.map +1 -1
  89. package/dist/tracing/init.d.ts +1 -1
  90. package/dist/tracing/init.d.ts.map +1 -1
  91. package/dist/utils/logger.js +2 -2
  92. package/dist/utils/logger.js.map +1 -1
  93. package/module-tiers.json +164 -0
  94. package/package.json +9 -13
  95. package/public/avatar/cache/1184385ec5522b57.mp4 +0 -0
  96. package/public/avatar/cache/1f15f6a1ebd7e439.mp4 +0 -0
  97. package/public/avatar/cache/2c7e47ff0bdeb8d1.mp4 +0 -0
  98. package/public/avatar/cache/5f308566f7abb8f2.mp4 +0 -0
  99. package/public/avatar/cache/62f9cfba848d724e.mp4 +0 -0
  100. package/public/avatar/cache/6d64e657e6bf2aab.mp4 +0 -0
  101. package/public/avatar/cache/763ad0349e0b6f26.mp4 +0 -0
  102. package/public/avatar/cache/81a516cfd461b2b9.mp4 +0 -0
  103. package/public/avatar/cache/9366de15fd6910ca.mp4 +0 -0
  104. package/public/avatar/cache/ade41a846b283895.mp4 +0 -0
  105. package/public/avatar/cache/b6066e5c65383eec.mp4 +0 -0
  106. package/public/avatar/cache/edadb75d37891fc7.mp4 +0 -0
  107. package/public/avatar/cache/f0ae159640621dd9.mp4 +0 -0
  108. package/public/avatar/cache/fc2e5419adf29d96.mp4 +0 -0
  109. package/public/index.html +379 -59
  110. package/dist/agents/autonomous.js +0 -749
  111. package/dist/agents/autonomous.js.map +0 -1
  112. package/dist/agents/commit.js +0 -113
  113. package/dist/agents/commit.js.map +0 -1
  114. package/dist/agents/continue.js +0 -158
  115. package/dist/agents/continue.js.map +0 -1
  116. package/dist/agents/cooldown.js +0 -397
  117. package/dist/agents/cooldown.js.map +0 -1
  118. package/dist/agents/dedup-guard.js +0 -131
  119. package/dist/agents/dedup-guard.js.map +0 -1
  120. package/dist/agents/feed.js +0 -176
  121. package/dist/agents/feed.js.map +0 -1
  122. package/dist/agents/governance.js +0 -292
  123. package/dist/agents/governance.js.map +0 -1
  124. package/dist/agents/governed-spawn.js +0 -192
  125. package/dist/agents/governed-spawn.js.map +0 -1
  126. package/dist/agents/heartbeat.js +0 -324
  127. package/dist/agents/heartbeat.js.map +0 -1
  128. package/dist/agents/instance-manager.js +0 -850
  129. package/dist/agents/instance-manager.js.map +0 -1
  130. package/dist/agents/issue-reporter.js +0 -123
  131. package/dist/agents/issue-reporter.js.map +0 -1
  132. package/dist/agents/issues.js +0 -141
  133. package/dist/agents/issues.js.map +0 -1
  134. package/dist/agents/locks.js +0 -234
  135. package/dist/agents/locks.js.map +0 -1
  136. package/dist/agents/memory.js +0 -93
  137. package/dist/agents/memory.js.map +0 -1
  138. package/dist/agents/monitor.js +0 -235
  139. package/dist/agents/monitor.js.map +0 -1
  140. package/dist/agents/orchestration.js +0 -715
  141. package/dist/agents/orchestration.js.map +0 -1
  142. package/dist/agents/recover.js +0 -166
  143. package/dist/agents/recover.js.map +0 -1
  144. package/dist/agents/reflection.js +0 -199
  145. package/dist/agents/reflection.js.map +0 -1
  146. package/dist/agents/runtime/bus.js +0 -174
  147. package/dist/agents/runtime/bus.js.map +0 -1
  148. package/dist/agents/runtime/config.js +0 -101
  149. package/dist/agents/runtime/config.js.map +0 -1
  150. package/dist/agents/runtime/driver.js +0 -214
  151. package/dist/agents/runtime/driver.js.map +0 -1
  152. package/dist/agents/runtime/errors.js +0 -40
  153. package/dist/agents/runtime/errors.js.map +0 -1
  154. package/dist/agents/runtime/index.js +0 -54
  155. package/dist/agents/runtime/index.js.map +0 -1
  156. package/dist/agents/runtime/lifecycle.js +0 -116
  157. package/dist/agents/runtime/lifecycle.js.map +0 -1
  158. package/dist/agents/runtime/manager.js +0 -948
  159. package/dist/agents/runtime/manager.js.map +0 -1
  160. package/dist/agents/runtime/registry.js +0 -195
  161. package/dist/agents/runtime/registry.js.map +0 -1
  162. package/dist/agents/runtime/resources.js +0 -146
  163. package/dist/agents/runtime/resources.js.map +0 -1
  164. package/dist/agents/runtime/types.js +0 -24
  165. package/dist/agents/runtime/types.js.map +0 -1
  166. package/dist/agents/spawn-policy.js +0 -202
  167. package/dist/agents/spawn-policy.js.map +0 -1
  168. package/dist/agents/spawn.js +0 -970
  169. package/dist/agents/spawn.js.map +0 -1
  170. package/dist/agents/triage.js +0 -81
  171. package/dist/agents/triage.js.map +0 -1
  172. package/dist/agents/workflow.js +0 -543
  173. package/dist/agents/workflow.js.map +0 -1
  174. package/dist/avatar/client.js +0 -172
  175. package/dist/avatar/client.js.map +0 -1
  176. package/dist/avatar/sidecar.js +0 -125
  177. package/dist/avatar/sidecar.js.map +0 -1
  178. package/dist/browser/sessions.js +0 -122
  179. package/dist/browser/sessions.js.map +0 -1
  180. package/dist/capabilities/definitions/browser.js +0 -242
  181. package/dist/capabilities/definitions/browser.js.map +0 -1
  182. package/dist/channels/whatsapp.js +0 -200
  183. package/dist/channels/whatsapp.js.map +0 -1
  184. package/dist/credentials/store.js +0 -189
  185. package/dist/credentials/store.js.map +0 -1
  186. package/dist/files/deep-index.js +0 -337
  187. package/dist/files/deep-index.js.map +0 -1
  188. package/dist/files/extract.js +0 -33
  189. package/dist/files/extract.js.map +0 -1
  190. package/dist/files/gdrive.js +0 -246
  191. package/dist/files/gdrive.js.map +0 -1
  192. package/dist/github/client.js +0 -408
  193. package/dist/github/client.js.map +0 -1
  194. package/dist/github/commit-analysis.js +0 -276
  195. package/dist/github/commit-analysis.js.map +0 -1
  196. package/dist/github/contributor-stats.js +0 -119
  197. package/dist/github/contributor-stats.js.map +0 -1
  198. package/dist/github/issue-sla.js +0 -220
  199. package/dist/github/issue-sla.js.map +0 -1
  200. package/dist/github/issue-triage.js +0 -286
  201. package/dist/github/issue-triage.js.map +0 -1
  202. package/dist/github/pr-readiness.js +0 -197
  203. package/dist/github/pr-readiness.js.map +0 -1
  204. package/dist/github/pr-review.js +0 -410
  205. package/dist/github/pr-review.js.map +0 -1
  206. package/dist/github/release-notes.js +0 -227
  207. package/dist/github/release-notes.js.map +0 -1
  208. package/dist/github/repo-health.js +0 -303
  209. package/dist/github/repo-health.js.map +0 -1
  210. package/dist/github/retry.js +0 -117
  211. package/dist/github/retry.js.map +0 -1
  212. package/dist/github/types.js +0 -8
  213. package/dist/github/types.js.map +0 -1
  214. package/dist/github/webhooks.js +0 -153
  215. package/dist/github/webhooks.js.map +0 -1
  216. package/dist/google/auth.js +0 -325
  217. package/dist/google/auth.js.map +0 -1
  218. package/dist/google/calendar-timer.js +0 -91
  219. package/dist/google/calendar-timer.js.map +0 -1
  220. package/dist/google/calendar.js +0 -270
  221. package/dist/google/calendar.js.map +0 -1
  222. package/dist/google/docs.js +0 -309
  223. package/dist/google/docs.js.map +0 -1
  224. package/dist/google/gmail-send.js +0 -219
  225. package/dist/google/gmail-send.js.map +0 -1
  226. package/dist/google/gmail-timer.js +0 -223
  227. package/dist/google/gmail-timer.js.map +0 -1
  228. package/dist/google/gmail.js +0 -470
  229. package/dist/google/gmail.js.map +0 -1
  230. package/dist/google/plugin.js +0 -169
  231. package/dist/google/plugin.js.map +0 -1
  232. package/dist/google/tasks-timer.js +0 -107
  233. package/dist/google/tasks-timer.js.map +0 -1
  234. package/dist/google/tasks.js +0 -331
  235. package/dist/google/tasks.js.map +0 -1
  236. package/dist/google/temporal.js +0 -176
  237. package/dist/google/temporal.js.map +0 -1
  238. package/dist/integrations/gate.js +0 -100
  239. package/dist/integrations/gate.js.map +0 -1
  240. package/dist/integrations/github.js +0 -331
  241. package/dist/integrations/github.js.map +0 -1
  242. package/dist/integrations/google-tasks.js +0 -432
  243. package/dist/integrations/google-tasks.js.map +0 -1
  244. package/dist/mdns.js +0 -110
  245. package/dist/mdns.js.map +0 -1
  246. package/dist/notifications/channel.js +0 -83
  247. package/dist/notifications/channel.js.map +0 -1
  248. package/dist/notifications/channels/adapter.js +0 -55
  249. package/dist/notifications/channels/adapter.js.map +0 -1
  250. package/dist/notifications/channels/index.js +0 -6
  251. package/dist/notifications/channels/index.js.map +0 -1
  252. package/dist/notifications/channels/log.js +0 -29
  253. package/dist/notifications/channels/log.js.map +0 -1
  254. package/dist/notifications/email.js +0 -72
  255. package/dist/notifications/email.js.map +0 -1
  256. package/dist/notifications/engine.js +0 -198
  257. package/dist/notifications/engine.js.map +0 -1
  258. package/dist/notifications/index.js +0 -24
  259. package/dist/notifications/index.js.map +0 -1
  260. package/dist/notifications/phone.js +0 -48
  261. package/dist/notifications/phone.js.map +0 -1
  262. package/dist/notifications/sms.js +0 -65
  263. package/dist/notifications/sms.js.map +0 -1
  264. package/dist/notifications/types.js +0 -14
  265. package/dist/notifications/types.js.map +0 -1
  266. package/dist/notifications/webhook.js +0 -65
  267. package/dist/notifications/webhook.js.map +0 -1
  268. package/dist/resend/inbox.js +0 -199
  269. package/dist/resend/inbox.js.map +0 -1
  270. package/dist/resend/webhooks.js +0 -244
  271. package/dist/resend/webhooks.js.map +0 -1
  272. package/dist/search/browse.js +0 -225
  273. package/dist/search/browse.js.map +0 -1
  274. package/dist/search/perplexity.js +0 -41
  275. package/dist/search/perplexity.js.map +0 -1
  276. package/dist/slack/channels.js +0 -277
  277. package/dist/slack/channels.js.map +0 -1
  278. package/dist/slack/client.js +0 -468
  279. package/dist/slack/client.js.map +0 -1
  280. package/dist/slack/retry.js +0 -100
  281. package/dist/slack/retry.js.map +0 -1
  282. package/dist/slack/types.js +0 -52
  283. package/dist/slack/types.js.map +0 -1
  284. package/dist/slack/webhooks.js +0 -285
  285. package/dist/slack/webhooks.js.map +0 -1
  286. package/dist/stt/client.js +0 -66
  287. package/dist/stt/client.js.map +0 -1
  288. package/dist/stt/sidecar.js +0 -115
  289. package/dist/stt/sidecar.js.map +0 -1
  290. package/dist/tracing/bridge.js +0 -70
  291. package/dist/tracing/bridge.js.map +0 -1
  292. package/dist/tracing/correlation.js +0 -49
  293. package/dist/tracing/correlation.js.map +0 -1
  294. package/dist/tracing/index.js +0 -18
  295. package/dist/tracing/index.js.map +0 -1
  296. package/dist/tracing/init.js +0 -81
  297. package/dist/tracing/init.js.map +0 -1
  298. package/dist/tracing/instrument.js +0 -145
  299. package/dist/tracing/instrument.js.map +0 -1
  300. package/dist/tracing/middleware.js +0 -69
  301. package/dist/tracing/middleware.js.map +0 -1
  302. package/dist/tracing/tracer.js +0 -327
  303. package/dist/tracing/tracer.js.map +0 -1
  304. package/dist/tts/client.js +0 -48
  305. package/dist/tts/client.js.map +0 -1
  306. package/dist/tts/sidecar.js +0 -148
  307. package/dist/tts/sidecar.js.map +0 -1
  308. package/dist/twilio/call.js +0 -79
  309. package/dist/twilio/call.js.map +0 -1
  310. package/dist/vault/matcher.js +0 -197
  311. package/dist/vault/matcher.js.map +0 -1
  312. package/dist/vault/personal.js +0 -163
  313. package/dist/vault/personal.js.map +0 -1
  314. package/dist/vault/policy.js +0 -159
  315. package/dist/vault/policy.js.map +0 -1
  316. package/dist/vault/store.js +0 -122
  317. package/dist/vault/store.js.map +0 -1
  318. package/dist/vault/transfer.js +0 -188
  319. package/dist/vault/transfer.js.map +0 -1
  320. package/dist/volumes/index.js +0 -2
  321. package/dist/volumes/index.js.map +0 -1
  322. package/dist/volumes/manager.js +0 -462
  323. package/dist/volumes/manager.js.map +0 -1
  324. package/dist/volumes/types.js +0 -8
  325. package/dist/volumes/types.js.map +0 -1
  326. package/dist/webhooks/config.js +0 -214
  327. package/dist/webhooks/config.js.map +0 -1
  328. package/dist/webhooks/event-log.js +0 -132
  329. package/dist/webhooks/event-log.js.map +0 -1
  330. package/dist/webhooks/handler.js +0 -103
  331. package/dist/webhooks/handler.js.map +0 -1
  332. package/dist/webhooks/handlers.js +0 -231
  333. package/dist/webhooks/handlers.js.map +0 -1
  334. package/dist/webhooks/index.js +0 -33
  335. package/dist/webhooks/index.js.map +0 -1
  336. package/dist/webhooks/mount.js +0 -400
  337. package/dist/webhooks/mount.js.map +0 -1
  338. package/dist/webhooks/registry.js +0 -143
  339. package/dist/webhooks/registry.js.map +0 -1
  340. package/dist/webhooks/relay.js +0 -53
  341. package/dist/webhooks/relay.js.map +0 -1
  342. package/dist/webhooks/retry.js +0 -270
  343. package/dist/webhooks/retry.js.map +0 -1
  344. package/dist/webhooks/router.js +0 -290
  345. package/dist/webhooks/router.js.map +0 -1
  346. package/dist/webhooks/twilio.js +0 -129
  347. package/dist/webhooks/twilio.js.map +0 -1
  348. package/dist/webhooks/types.js +0 -8
  349. package/dist/webhooks/types.js.map +0 -1
  350. package/dist/webhooks/verify.js +0 -154
  351. package/dist/webhooks/verify.js.map +0 -1
@@ -1,410 +0,0 @@
1
- /**
2
- * PR review automation — analyzes pull requests and provides feedback.
3
- *
4
- * Checks for: size, test coverage signals, doc changes, large/binary files,
5
- * naming conventions, security patterns, and breaking changes.
6
- * Does NOT use LLM — purely heuristic-based for speed and reliability.
7
- */
8
- import { createLogger } from "../utils/logger.js";
9
- import { logActivity } from "../activity/log.js";
10
- import * as client from "./client.js";
11
- const log = createLogger("github.pr-review");
12
- // ── Size thresholds ──────────────────────────────────────────────────────────
13
- const SIZE_THRESHOLDS = {
14
- small: 100,
15
- medium: 300,
16
- large: 500,
17
- huge: 1000,
18
- };
19
- const BINARY_EXTENSIONS = new Set([
20
- ".png", ".jpg", ".jpeg", ".gif", ".ico", ".svg",
21
- ".woff", ".woff2", ".ttf", ".eot",
22
- ".zip", ".tar", ".gz", ".exe", ".dll",
23
- ".mp3", ".mp4", ".wav", ".avi",
24
- ".pdf", ".doc", ".docx",
25
- ]);
26
- const TEST_PATTERNS = [
27
- /\.test\.[jt]sx?$/,
28
- /\.spec\.[jt]sx?$/,
29
- /__tests__\//,
30
- /test\//,
31
- /tests\//,
32
- ];
33
- const DOC_PATTERNS = [
34
- /\.md$/i,
35
- /docs?\//i,
36
- /readme/i,
37
- /changelog/i,
38
- ];
39
- const SECURITY_PATTERNS = [
40
- /password/i,
41
- /secret/i,
42
- /api[_-]?key/i,
43
- /token/i,
44
- /\.env/,
45
- /credentials/i,
46
- /auth[_-]?token/i,
47
- /private[_-]?key/i,
48
- ];
49
- const DEPENDENCY_FILES = new Set([
50
- "package.json",
51
- "package-lock.json",
52
- "yarn.lock",
53
- "pnpm-lock.yaml",
54
- "bun.lockb",
55
- "requirements.txt",
56
- "Pipfile.lock",
57
- "Gemfile.lock",
58
- "go.sum",
59
- "Cargo.lock",
60
- "composer.lock",
61
- ]);
62
- const LOCK_FILES = new Set([
63
- "package-lock.json",
64
- "yarn.lock",
65
- "pnpm-lock.yaml",
66
- "bun.lockb",
67
- "Pipfile.lock",
68
- "Gemfile.lock",
69
- "go.sum",
70
- "Cargo.lock",
71
- "composer.lock",
72
- ]);
73
- // ── Analysis functions ───────────────────────────────────────────────────────
74
- function getFileExtension(filename) {
75
- const dot = filename.lastIndexOf(".");
76
- return dot >= 0 ? filename.slice(dot).toLowerCase() : "";
77
- }
78
- function computeMetrics(pr, files) {
79
- const hasTests = files.some((f) => TEST_PATTERNS.some((p) => p.test(f.filename)));
80
- const hasDocChanges = files.some((f) => DOC_PATTERNS.some((p) => p.test(f.filename)));
81
- const largeFiles = files
82
- .filter((f) => f.changes > 300)
83
- .map((f) => f.filename);
84
- const binaryFiles = files
85
- .filter((f) => BINARY_EXTENSIONS.has(getFileExtension(f.filename)))
86
- .map((f) => f.filename);
87
- return {
88
- filesChanged: pr.changed_files,
89
- additions: pr.additions,
90
- deletions: pr.deletions,
91
- hasTests,
92
- hasDocChanges,
93
- largeFiles,
94
- binaryFiles,
95
- };
96
- }
97
- function analyzeSize(pr) {
98
- const findings = [];
99
- const total = pr.additions + pr.deletions;
100
- if (total > SIZE_THRESHOLDS.huge) {
101
- findings.push({
102
- severity: "error",
103
- category: "size",
104
- message: `Very large PR (${total} lines changed). Consider breaking into smaller PRs for easier review.`,
105
- });
106
- }
107
- else if (total > SIZE_THRESHOLDS.large) {
108
- findings.push({
109
- severity: "warning",
110
- category: "size",
111
- message: `Large PR (${total} lines changed). Smaller PRs are reviewed faster and more thoroughly.`,
112
- });
113
- }
114
- if (pr.changed_files > 20) {
115
- findings.push({
116
- severity: "warning",
117
- category: "size",
118
- message: `${pr.changed_files} files changed. Consider scoping this PR more narrowly.`,
119
- });
120
- }
121
- return findings;
122
- }
123
- function analyzeTestCoverage(files) {
124
- const findings = [];
125
- const srcFiles = files.filter((f) => f.status !== "removed" &&
126
- !TEST_PATTERNS.some((p) => p.test(f.filename)) &&
127
- !DOC_PATTERNS.some((p) => p.test(f.filename)) &&
128
- (f.filename.endsWith(".ts") || f.filename.endsWith(".tsx") || f.filename.endsWith(".js") || f.filename.endsWith(".jsx")));
129
- const testFiles = files.filter((f) => TEST_PATTERNS.some((p) => p.test(f.filename)));
130
- if (srcFiles.length > 0 && testFiles.length === 0) {
131
- findings.push({
132
- severity: "warning",
133
- category: "testing",
134
- message: `${srcFiles.length} source file(s) changed but no test files modified. Consider adding tests.`,
135
- });
136
- }
137
- return findings;
138
- }
139
- function analyzeSecurityPatterns(files) {
140
- const findings = [];
141
- for (const file of files) {
142
- if (!file.patch)
143
- continue;
144
- // Only check added lines (lines starting with +)
145
- const addedLines = file.patch.split("\n").filter((l) => l.startsWith("+") && !l.startsWith("+++"));
146
- for (const line of addedLines) {
147
- for (const pattern of SECURITY_PATTERNS) {
148
- if (pattern.test(line)) {
149
- // Skip if it's clearly a test or mock
150
- if (/mock|test|fake|dummy|example|placeholder/i.test(line))
151
- continue;
152
- findings.push({
153
- severity: "warning",
154
- category: "security",
155
- message: `Potential sensitive value in ${file.filename} — review for hardcoded credentials.`,
156
- file: file.filename,
157
- });
158
- break; // One finding per file per pattern check
159
- }
160
- }
161
- }
162
- }
163
- // Deduplicate by file
164
- const seen = new Set();
165
- return findings.filter((f) => {
166
- if (f.file && seen.has(f.file))
167
- return false;
168
- if (f.file)
169
- seen.add(f.file);
170
- return true;
171
- });
172
- }
173
- function analyzeDependencyChanges(files) {
174
- const findings = [];
175
- const depFiles = files.filter((f) => {
176
- const basename = f.filename.split("/").pop() ?? "";
177
- return DEPENDENCY_FILES.has(basename);
178
- });
179
- if (depFiles.length === 0)
180
- return findings;
181
- const manifestFiles = depFiles.filter((f) => {
182
- const basename = f.filename.split("/").pop() ?? "";
183
- return !LOCK_FILES.has(basename);
184
- });
185
- const lockFiles = depFiles.filter((f) => {
186
- const basename = f.filename.split("/").pop() ?? "";
187
- return LOCK_FILES.has(basename);
188
- });
189
- // Manifest changed but no lock file — might be missing install
190
- if (manifestFiles.length > 0 && lockFiles.length === 0) {
191
- findings.push({
192
- severity: "warning",
193
- category: "convention",
194
- message: `Dependency manifest changed (${manifestFiles.map((f) => f.filename).join(", ")}) but no lock file updated. Run install to update the lock file.`,
195
- });
196
- }
197
- // Lock file changed — flag for review
198
- if (lockFiles.length > 0) {
199
- findings.push({
200
- severity: "info",
201
- category: "security",
202
- message: `Lock file(s) changed: ${lockFiles.map((f) => f.filename).join(", ")}. Verify dependency updates are intentional.`,
203
- });
204
- }
205
- // Check for new dependency additions in patch
206
- for (const f of manifestFiles) {
207
- if (!f.patch)
208
- continue;
209
- const addedLines = f.patch.split("\n").filter((l) => l.startsWith("+") && !l.startsWith("+++"));
210
- if (addedLines.length > 10) {
211
- findings.push({
212
- severity: "info",
213
- category: "security",
214
- message: `Significant dependency changes in ${f.filename} (${addedLines.length} additions). Review new dependencies for supply chain risk.`,
215
- file: f.filename,
216
- });
217
- }
218
- }
219
- return findings;
220
- }
221
- function analyzeBreakingChanges(files) {
222
- const findings = [];
223
- const deletedFiles = files.filter((f) => f.status === "removed");
224
- const renamedFiles = files.filter((f) => f.status === "renamed");
225
- // Exported source files being deleted
226
- const deletedSrcFiles = deletedFiles.filter((f) => /\.(ts|js|tsx|jsx)$/.test(f.filename) &&
227
- !TEST_PATTERNS.some((p) => p.test(f.filename)));
228
- if (deletedSrcFiles.length > 0) {
229
- findings.push({
230
- severity: "warning",
231
- category: "breaking_change",
232
- message: `${deletedSrcFiles.length} source file(s) deleted: ${deletedSrcFiles.slice(0, 3).map((f) => f.filename).join(", ")}${deletedSrcFiles.length > 3 ? "..." : ""}. Verify no external consumers depend on these.`,
233
- });
234
- }
235
- // Renamed files may break imports
236
- if (renamedFiles.length > 0) {
237
- findings.push({
238
- severity: "info",
239
- category: "breaking_change",
240
- message: `${renamedFiles.length} file(s) renamed. Verify all import paths have been updated.`,
241
- });
242
- }
243
- // Check patches for removed exports
244
- for (const f of files) {
245
- if (!f.patch || f.status === "removed")
246
- continue;
247
- if (!/\.(ts|js|tsx|jsx)$/.test(f.filename))
248
- continue;
249
- const removedLines = f.patch.split("\n").filter((l) => l.startsWith("-") && !l.startsWith("---"));
250
- const removedExports = removedLines.filter((l) => /^\-\s*export\s/.test(l));
251
- if (removedExports.length > 0) {
252
- findings.push({
253
- severity: "warning",
254
- category: "breaking_change",
255
- message: `${removedExports.length} export(s) removed in ${f.filename}. This may break downstream consumers.`,
256
- file: f.filename,
257
- });
258
- }
259
- }
260
- return findings;
261
- }
262
- function analyzeReviewStaleness(pr) {
263
- const findings = [];
264
- const createdMs = new Date(pr.created_at).getTime();
265
- const nowMs = Date.now();
266
- const ageDays = (nowMs - createdMs) / (24 * 60 * 60 * 1000);
267
- if (ageDays > 14) {
268
- findings.push({
269
- severity: "warning",
270
- category: "convention",
271
- message: `PR has been open for ${Math.round(ageDays)} days. Consider merging, closing, or rebasing.`,
272
- });
273
- }
274
- else if (ageDays > 7) {
275
- findings.push({
276
- severity: "info",
277
- category: "convention",
278
- message: `PR has been open for ${Math.round(ageDays)} days. A prompt review keeps momentum.`,
279
- });
280
- }
281
- return findings;
282
- }
283
- function analyzeConventions(pr, files) {
284
- const findings = [];
285
- // Check PR title
286
- if (pr.title.length < 10) {
287
- findings.push({
288
- severity: "info",
289
- category: "convention",
290
- message: "PR title is very short. A descriptive title helps reviewers and shows in git history.",
291
- });
292
- }
293
- // Check for WIP / draft signals
294
- if (/\bwip\b/i.test(pr.title) && !pr.draft) {
295
- findings.push({
296
- severity: "info",
297
- category: "convention",
298
- message: "PR title contains 'WIP' but is not marked as draft.",
299
- });
300
- }
301
- // Check for empty body
302
- if (!pr.body || pr.body.trim().length < 20) {
303
- findings.push({
304
- severity: "info",
305
- category: "documentation",
306
- message: "PR description is empty or very short. Consider explaining the what and why of this change.",
307
- });
308
- }
309
- return findings;
310
- }
311
- function determineRecommendation(findings) {
312
- const hasErrors = findings.some((f) => f.severity === "error");
313
- if (hasErrors)
314
- return "request_changes";
315
- const warningCount = findings.filter((f) => f.severity === "warning").length;
316
- if (warningCount >= 3)
317
- return "request_changes";
318
- if (warningCount > 0)
319
- return "comment";
320
- return "approve";
321
- }
322
- // ── Public API ───────────────────────────────────────────────────────────────
323
- /**
324
- * Analyze a pull request and produce a review with findings and metrics.
325
- */
326
- export async function reviewPR(owner, repo, prNumber) {
327
- log.info(`Reviewing PR ${owner}/${repo}#${prNumber}`);
328
- const [pr, files] = await Promise.all([
329
- client.getPullRequest(owner, repo, prNumber),
330
- client.getPRFiles(owner, repo, prNumber),
331
- ]);
332
- if (!pr || !files) {
333
- log.warn(`Failed to fetch PR data for ${owner}/${repo}#${prNumber}`);
334
- return null;
335
- }
336
- const metrics = computeMetrics(pr, files);
337
- const findings = [
338
- ...analyzeSize(pr),
339
- ...analyzeTestCoverage(files),
340
- ...analyzeSecurityPatterns(files),
341
- ...analyzeDependencyChanges(files),
342
- ...analyzeBreakingChanges(files),
343
- ...analyzeReviewStaleness(pr),
344
- ...analyzeConventions(pr, files),
345
- ];
346
- // Binary file warnings
347
- if (metrics.binaryFiles.length > 0) {
348
- findings.push({
349
- severity: "info",
350
- category: "size",
351
- message: `${metrics.binaryFiles.length} binary file(s) included: ${metrics.binaryFiles.slice(0, 3).join(", ")}${metrics.binaryFiles.length > 3 ? "..." : ""}`,
352
- });
353
- }
354
- const recommendation = determineRecommendation(findings);
355
- const summary = buildSummary(pr, metrics, findings, recommendation);
356
- const result = {
357
- prNumber,
358
- repo: `${owner}/${repo}`,
359
- summary,
360
- findings,
361
- metrics,
362
- recommendation,
363
- reviewedAt: new Date().toISOString(),
364
- };
365
- logActivity({
366
- source: "board",
367
- summary: `PR review: ${owner}/${repo}#${prNumber} — ${recommendation} (${findings.length} findings)`,
368
- });
369
- return result;
370
- }
371
- /**
372
- * Review a PR and post the review as a GitHub comment.
373
- */
374
- export async function reviewAndComment(owner, repo, prNumber) {
375
- const result = await reviewPR(owner, repo, prNumber);
376
- if (!result)
377
- return null;
378
- // Post as PR comment (not a formal review, to avoid blocking)
379
- await client.addIssueComment(owner, repo, prNumber, result.summary);
380
- return result;
381
- }
382
- // ── Summary formatting ───────────────────────────────────────────────────────
383
- function buildSummary(pr, metrics, findings, recommendation) {
384
- const lines = [];
385
- lines.push(`## Automated PR Review`);
386
- lines.push("");
387
- lines.push(`**${pr.title}** (#${pr.number})`);
388
- lines.push("");
389
- lines.push(`| Metric | Value |`);
390
- lines.push(`|--------|-------|`);
391
- lines.push(`| Files changed | ${metrics.filesChanged} |`);
392
- lines.push(`| Additions | +${metrics.additions} |`);
393
- lines.push(`| Deletions | -${metrics.deletions} |`);
394
- lines.push(`| Tests included | ${metrics.hasTests ? "Yes" : "No"} |`);
395
- lines.push(`| Docs updated | ${metrics.hasDocChanges ? "Yes" : "No"} |`);
396
- lines.push("");
397
- if (findings.length > 0) {
398
- lines.push(`### Findings (${findings.length})`);
399
- lines.push("");
400
- for (const f of findings) {
401
- const icon = f.severity === "error" ? "🔴" : f.severity === "warning" ? "🟡" : "🔵";
402
- const loc = f.file ? ` (${f.file}${f.line ? `:${f.line}` : ""})` : "";
403
- lines.push(`- ${icon} **${f.category}**${loc}: ${f.message}`);
404
- }
405
- lines.push("");
406
- }
407
- lines.push(`**Recommendation:** ${recommendation.replace("_", " ")}`);
408
- return lines.join("\n");
409
- }
410
- //# sourceMappingURL=pr-review.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pr-review.js","sourceRoot":"","sources":["../../src/github/pr-review.ts"],"names":[],"mappings":"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"}
@@ -1,227 +0,0 @@
1
- /**
2
- * Release notes generator — produces structured release notes from commits.
3
- *
4
- * Groups commits by type (features, fixes, etc.) using conventional commit
5
- * parsing. Detects breaking changes and lists contributors.
6
- * Outputs structured data + formatted markdown.
7
- */
8
- import { createLogger } from "../utils/logger.js";
9
- import { logActivity } from "../activity/log.js";
10
- import * as client from "./client.js";
11
- const log = createLogger("github.release-notes");
12
- // ── Conventional commit parsing ──────────────────────────────────────────────
13
- const CONVENTIONAL_RE = /^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(?:\((.+?)\))?(!)?:\s(.+)/;
14
- function parseCommitMessage(sha, message, author) {
15
- const firstLine = message.split("\n")[0].trim();
16
- const match = firstLine.match(CONVENTIONAL_RE);
17
- if (match) {
18
- return {
19
- type: match[1],
20
- scope: match[2] || undefined,
21
- breaking: match[3] === "!" || /BREAKING.CHANGE/i.test(message),
22
- description: match[4],
23
- sha,
24
- author,
25
- raw: firstLine,
26
- };
27
- }
28
- // Non-conventional: try to categorize by keywords
29
- const lower = firstLine.toLowerCase();
30
- let type = "other";
31
- if (/^merge\s/i.test(lower))
32
- type = "merge";
33
- else if (/\b(fix|bug|patch|hotfix)\b/.test(lower))
34
- type = "fix";
35
- else if (/\b(add|feat|feature|implement|new)\b/.test(lower))
36
- type = "feat";
37
- else if (/\b(doc|readme)\b/.test(lower))
38
- type = "docs";
39
- else if (/\b(refactor|restructure|cleanup)\b/.test(lower))
40
- type = "refactor";
41
- else if (/\b(test|spec)\b/.test(lower))
42
- type = "test";
43
- else if (/\b(ci|pipeline|workflow)\b/.test(lower))
44
- type = "ci";
45
- else if (/\b(perf|optimize|speed)\b/.test(lower))
46
- type = "perf";
47
- return {
48
- type,
49
- breaking: /BREAKING.CHANGE/i.test(message),
50
- description: firstLine,
51
- sha,
52
- author,
53
- raw: firstLine,
54
- };
55
- }
56
- const SECTION_ORDER = [
57
- { title: "Breaking Changes", icon: "💥", types: [] }, // Special: populated from breaking flag
58
- { title: "Features", icon: "✨", types: ["feat"] },
59
- { title: "Bug Fixes", icon: "🐛", types: ["fix"] },
60
- { title: "Performance", icon: "⚡", types: ["perf"] },
61
- { title: "Documentation", icon: "📝", types: ["docs"] },
62
- { title: "Refactoring", icon: "♻️", types: ["refactor"] },
63
- { title: "Tests", icon: "🧪", types: ["test"] },
64
- { title: "CI/CD", icon: "🔧", types: ["ci", "build"] },
65
- { title: "Chores", icon: "🧹", types: ["chore"] },
66
- { title: "Other", icon: "📦", types: ["other", "revert", "style"] },
67
- ];
68
- // ── Public API ───────────────────────────────────────────────────────────────
69
- /**
70
- * Generate release notes from commits between two refs (tags, SHAs, or branches).
71
- */
72
- export async function generateReleaseNotes(owner, repo, opts) {
73
- const to = opts.to ?? "HEAD";
74
- log.info(`Generating release notes for ${owner}/${repo}: ${opts.from}..${to}`);
75
- const comparison = await client.compareBranches(owner, repo, opts.from, to);
76
- if (!comparison) {
77
- log.warn(`Failed to compare ${opts.from}..${to}`);
78
- return null;
79
- }
80
- if (comparison.commits.length === 0) {
81
- log.info("No commits found between the two refs.");
82
- return {
83
- repo: `${owner}/${repo}`,
84
- version: opts.version ?? to,
85
- from: opts.from,
86
- to,
87
- generatedAt: new Date().toISOString(),
88
- sections: [],
89
- breakingChanges: [],
90
- contributors: [],
91
- markdown: `## ${opts.version ?? to}\n\nNo changes.`,
92
- };
93
- }
94
- // Parse all commits
95
- const parsed = comparison.commits
96
- .filter((c) => !c.commit.message.startsWith("Merge ")) // Skip merge commits
97
- .map((c) => parseCommitMessage(c.sha, c.commit.message, c.commit.author?.name ?? "Unknown"));
98
- // Collect breaking changes
99
- const breakingChanges = parsed
100
- .filter((c) => c.breaking)
101
- .map((c) => c.scope ? `**${c.scope}:** ${c.description}` : c.description);
102
- // Collect unique contributors
103
- const contributors = [...new Set(parsed.map((c) => c.author))].sort();
104
- // Build sections
105
- const sections = [];
106
- for (const def of SECTION_ORDER) {
107
- // Skip the "Breaking Changes" section (handled separately in markdown)
108
- if (def.types.length === 0)
109
- continue;
110
- const entries = parsed
111
- .filter((c) => def.types.includes(c.type))
112
- .map((c) => ({
113
- sha: c.sha.slice(0, 7),
114
- message: c.description,
115
- author: c.author,
116
- scope: c.scope,
117
- }));
118
- if (entries.length > 0) {
119
- sections.push({ title: def.title, icon: def.icon, commits: entries });
120
- }
121
- }
122
- const version = opts.version ?? to;
123
- const markdown = formatReleaseNotes(version, sections, breakingChanges, contributors);
124
- const result = {
125
- repo: `${owner}/${repo}`,
126
- version,
127
- from: opts.from,
128
- to,
129
- generatedAt: new Date().toISOString(),
130
- sections,
131
- breakingChanges,
132
- contributors,
133
- markdown,
134
- };
135
- logActivity({
136
- source: "board",
137
- summary: `Release notes: ${owner}/${repo} ${version} — ${parsed.length} commits, ${contributors.length} contributors`,
138
- });
139
- return result;
140
- }
141
- /**
142
- * Generate release notes from the latest tag to HEAD.
143
- */
144
- export async function generateReleaseNotesFromLatestTag(owner, repo, opts) {
145
- const tags = await client.listTags(owner, repo, { per_page: 1 });
146
- if (!tags || tags.length === 0) {
147
- log.warn(`No tags found for ${owner}/${repo}`);
148
- return null;
149
- }
150
- return generateReleaseNotes(owner, repo, {
151
- from: tags[0].name,
152
- to: "HEAD",
153
- version: opts?.version,
154
- });
155
- }
156
- // ── Formatting ───────────────────────────────────────────────────────────────
157
- function formatReleaseNotes(version, sections, breakingChanges, contributors) {
158
- const lines = [];
159
- lines.push(`## ${version}`);
160
- lines.push("");
161
- if (breakingChanges.length > 0) {
162
- lines.push("### 💥 Breaking Changes");
163
- lines.push("");
164
- for (const bc of breakingChanges) {
165
- lines.push(`- ${bc}`);
166
- }
167
- lines.push("");
168
- }
169
- for (const section of sections) {
170
- lines.push(`### ${section.icon} ${section.title}`);
171
- lines.push("");
172
- for (const entry of section.commits) {
173
- const scope = entry.scope ? `**${entry.scope}:** ` : "";
174
- lines.push(`- ${scope}${entry.message} (${entry.sha})`);
175
- }
176
- lines.push("");
177
- }
178
- if (contributors.length > 0) {
179
- lines.push("### Contributors");
180
- lines.push("");
181
- lines.push(contributors.map((c) => `@${c}`).join(", "));
182
- lines.push("");
183
- }
184
- return lines.join("\n").trimEnd();
185
- }
186
- /**
187
- * Generate release notes purely from commit data (no API calls).
188
- * Useful for testing or when commit data is already available.
189
- */
190
- export function generateReleaseNotesFromCommits(repo, version, commits) {
191
- const parsed = commits
192
- .filter((c) => !c.message.startsWith("Merge "))
193
- .map((c) => parseCommitMessage(c.sha, c.message, c.author));
194
- const breakingChanges = parsed
195
- .filter((c) => c.breaking)
196
- .map((c) => c.scope ? `**${c.scope}:** ${c.description}` : c.description);
197
- const contributors = [...new Set(parsed.map((c) => c.author))].sort();
198
- const sections = [];
199
- for (const def of SECTION_ORDER) {
200
- if (def.types.length === 0)
201
- continue;
202
- const entries = parsed
203
- .filter((c) => def.types.includes(c.type))
204
- .map((c) => ({
205
- sha: c.sha.slice(0, 7),
206
- message: c.description,
207
- author: c.author,
208
- scope: c.scope,
209
- }));
210
- if (entries.length > 0) {
211
- sections.push({ title: def.title, icon: def.icon, commits: entries });
212
- }
213
- }
214
- const markdown = formatReleaseNotes(version, sections, breakingChanges, contributors);
215
- return {
216
- repo,
217
- version,
218
- from: "",
219
- to: "",
220
- generatedAt: new Date().toISOString(),
221
- sections,
222
- breakingChanges,
223
- contributors,
224
- markdown,
225
- };
226
- }
227
- //# sourceMappingURL=release-notes.js.map