@nanonets/graft 0.15.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. package/README.md +17 -5
  2. package/dist/ai/crux.d.ts +14 -1
  3. package/dist/ai/crux.d.ts.map +1 -1
  4. package/dist/ai/crux.js +31 -1
  5. package/dist/ai/crux.js.map +1 -1
  6. package/dist/ai/failure.d.ts +13 -2
  7. package/dist/ai/failure.d.ts.map +1 -1
  8. package/dist/ai/failure.js +16 -4
  9. package/dist/ai/failure.js.map +1 -1
  10. package/dist/ai/llm/factory.d.ts +6 -1
  11. package/dist/ai/llm/factory.d.ts.map +1 -1
  12. package/dist/ai/llm/factory.js +8 -0
  13. package/dist/ai/llm/factory.js.map +1 -1
  14. package/dist/ai/llm/orcarouter.d.ts +34 -0
  15. package/dist/ai/llm/orcarouter.d.ts.map +1 -0
  16. package/dist/ai/llm/orcarouter.js +45 -0
  17. package/dist/ai/llm/orcarouter.js.map +1 -0
  18. package/dist/ai/providers.d.ts.map +1 -1
  19. package/dist/ai/providers.js +13 -3
  20. package/dist/ai/providers.js.map +1 -1
  21. package/dist/app/brain-build.d.ts +66 -0
  22. package/dist/app/brain-build.d.ts.map +1 -0
  23. package/dist/app/brain-build.js +169 -0
  24. package/dist/app/brain-build.js.map +1 -0
  25. package/dist/app/checkout.d.ts +53 -3
  26. package/dist/app/checkout.d.ts.map +1 -1
  27. package/dist/app/checkout.js +195 -27
  28. package/dist/app/checkout.js.map +1 -1
  29. package/dist/app/events.d.ts +7 -0
  30. package/dist/app/events.d.ts.map +1 -1
  31. package/dist/app/events.js +7 -2
  32. package/dist/app/events.js.map +1 -1
  33. package/dist/app/history.d.ts +128 -0
  34. package/dist/app/history.d.ts.map +1 -0
  35. package/dist/app/history.js +269 -0
  36. package/dist/app/history.js.map +1 -0
  37. package/dist/app/identity.d.ts +33 -0
  38. package/dist/app/identity.d.ts.map +1 -1
  39. package/dist/app/identity.js +72 -0
  40. package/dist/app/identity.js.map +1 -1
  41. package/dist/app/main.js +12 -0
  42. package/dist/app/main.js.map +1 -1
  43. package/dist/app/pages.d.ts +17 -0
  44. package/dist/app/pages.d.ts.map +1 -1
  45. package/dist/app/pages.js +112 -5
  46. package/dist/app/pages.js.map +1 -1
  47. package/dist/app/review-process.d.ts +66 -0
  48. package/dist/app/review-process.d.ts.map +1 -0
  49. package/dist/app/review-process.js +199 -0
  50. package/dist/app/review-process.js.map +1 -0
  51. package/dist/app/review-worker.d.ts +2 -0
  52. package/dist/app/review-worker.d.ts.map +1 -0
  53. package/dist/app/review-worker.js +108 -0
  54. package/dist/app/review-worker.js.map +1 -0
  55. package/dist/app/review.d.ts.map +1 -1
  56. package/dist/app/review.js +14 -1
  57. package/dist/app/review.js.map +1 -1
  58. package/dist/app/server.d.ts +22 -2
  59. package/dist/app/server.d.ts.map +1 -1
  60. package/dist/app/server.js +77 -3
  61. package/dist/app/server.js.map +1 -1
  62. package/dist/app/sources.d.ts +68 -0
  63. package/dist/app/sources.d.ts.map +1 -0
  64. package/dist/app/sources.js +341 -0
  65. package/dist/app/sources.js.map +1 -0
  66. package/dist/ask/ask.d.ts +6 -0
  67. package/dist/ask/ask.d.ts.map +1 -1
  68. package/dist/ask/ask.js +30 -2
  69. package/dist/ask/ask.js.map +1 -1
  70. package/dist/blast/blast-cli.d.ts.map +1 -1
  71. package/dist/blast/blast-cli.js +6 -30
  72. package/dist/blast/blast-cli.js.map +1 -1
  73. package/dist/blast/name.d.ts +13 -0
  74. package/dist/blast/name.d.ts.map +1 -1
  75. package/dist/blast/name.js +36 -0
  76. package/dist/blast/name.js.map +1 -1
  77. package/dist/brain/attach.d.ts +44 -0
  78. package/dist/brain/attach.d.ts.map +1 -0
  79. package/dist/brain/attach.js +63 -0
  80. package/dist/brain/attach.js.map +1 -0
  81. package/dist/brain/connect.d.ts +59 -0
  82. package/dist/brain/connect.d.ts.map +1 -0
  83. package/dist/brain/connect.js +80 -0
  84. package/dist/brain/connect.js.map +1 -0
  85. package/dist/brain/link.d.ts +82 -0
  86. package/dist/brain/link.d.ts.map +1 -0
  87. package/dist/brain/link.js +136 -0
  88. package/dist/brain/link.js.map +1 -0
  89. package/dist/brain/push.d.ts +72 -0
  90. package/dist/brain/push.d.ts.map +1 -0
  91. package/dist/brain/push.js +191 -0
  92. package/dist/brain/push.js.map +1 -0
  93. package/dist/brain/wire.d.ts +38 -0
  94. package/dist/brain/wire.d.ts.map +1 -0
  95. package/dist/brain/wire.js +133 -0
  96. package/dist/brain/wire.js.map +1 -0
  97. package/dist/claude/format.d.ts.map +1 -1
  98. package/dist/claude/format.js +10 -3
  99. package/dist/claude/format.js.map +1 -1
  100. package/dist/claude/hooks.d.ts.map +1 -1
  101. package/dist/claude/hooks.js +125 -24
  102. package/dist/claude/hooks.js.map +1 -1
  103. package/dist/claude/init.d.ts +6 -0
  104. package/dist/claude/init.d.ts.map +1 -1
  105. package/dist/claude/init.js +10 -2
  106. package/dist/claude/init.js.map +1 -1
  107. package/dist/claude/session-metrics.d.ts +73 -0
  108. package/dist/claude/session-metrics.d.ts.map +1 -0
  109. package/dist/claude/session-metrics.js +206 -0
  110. package/dist/claude/session-metrics.js.map +1 -0
  111. package/dist/claude/settings-merge.d.ts +25 -1
  112. package/dist/claude/settings-merge.d.ts.map +1 -1
  113. package/dist/claude/settings-merge.js +88 -25
  114. package/dist/claude/settings-merge.js.map +1 -1
  115. package/dist/claude/skill-template.d.ts.map +1 -1
  116. package/dist/claude/skill-template.js +6 -0
  117. package/dist/claude/skill-template.js.map +1 -1
  118. package/dist/claude/state.d.ts +26 -0
  119. package/dist/claude/state.d.ts.map +1 -1
  120. package/dist/claude/state.js +14 -1
  121. package/dist/claude/state.js.map +1 -1
  122. package/dist/claude/tally.d.ts +27 -0
  123. package/dist/claude/tally.d.ts.map +1 -1
  124. package/dist/claude/tally.js +74 -1
  125. package/dist/claude/tally.js.map +1 -1
  126. package/dist/cli.js +237 -4
  127. package/dist/cli.js.map +1 -1
  128. package/dist/context/build.d.ts +11 -0
  129. package/dist/context/build.d.ts.map +1 -1
  130. package/dist/context/build.js +27 -6
  131. package/dist/context/build.js.map +1 -1
  132. package/dist/context/check.d.ts.map +1 -1
  133. package/dist/context/check.js +5 -13
  134. package/dist/context/check.js.map +1 -1
  135. package/dist/context/node-file.d.ts +1 -1
  136. package/dist/context/node-file.d.ts.map +1 -1
  137. package/dist/context/node-file.js +38 -6
  138. package/dist/context/node-file.js.map +1 -1
  139. package/dist/context/price.d.ts +49 -0
  140. package/dist/context/price.d.ts.map +1 -0
  141. package/dist/context/price.js +83 -0
  142. package/dist/context/price.js.map +1 -0
  143. package/dist/context/savings.d.ts +20 -2
  144. package/dist/context/savings.d.ts.map +1 -1
  145. package/dist/context/savings.js +57 -4
  146. package/dist/context/savings.js.map +1 -1
  147. package/dist/engine.d.ts +2 -0
  148. package/dist/engine.d.ts.map +1 -1
  149. package/dist/engine.js +1 -0
  150. package/dist/engine.js.map +1 -1
  151. package/dist/graph/cards.d.ts +4 -3
  152. package/dist/graph/cards.d.ts.map +1 -1
  153. package/dist/graph/cards.js +34 -6
  154. package/dist/graph/cards.js.map +1 -1
  155. package/dist/graph/enrich.d.ts +4 -4
  156. package/dist/graph/enrich.d.ts.map +1 -1
  157. package/dist/graph/enrich.js +32 -6
  158. package/dist/graph/enrich.js.map +1 -1
  159. package/dist/graph/generic.d.ts +10 -0
  160. package/dist/graph/generic.d.ts.map +1 -1
  161. package/dist/graph/generic.js +20 -2
  162. package/dist/graph/generic.js.map +1 -1
  163. package/dist/graph/workspace.d.ts +2 -0
  164. package/dist/graph/workspace.d.ts.map +1 -1
  165. package/dist/graph/workspace.js +173 -6
  166. package/dist/graph/workspace.js.map +1 -1
  167. package/dist/hosts/antigravity.d.ts +2 -2
  168. package/dist/hosts/antigravity.d.ts.map +1 -1
  169. package/dist/hosts/claude-global.d.ts +33 -0
  170. package/dist/hosts/claude-global.d.ts.map +1 -0
  171. package/dist/hosts/claude-global.js +118 -0
  172. package/dist/hosts/claude-global.js.map +1 -0
  173. package/dist/hosts/codex-hooks.d.ts +2 -6
  174. package/dist/hosts/codex-hooks.d.ts.map +1 -1
  175. package/dist/hosts/codex-hooks.js +7 -30
  176. package/dist/hosts/codex-hooks.js.map +1 -1
  177. package/dist/hosts/config-write.d.ts +36 -0
  178. package/dist/hosts/config-write.d.ts.map +1 -0
  179. package/dist/hosts/config-write.js +63 -0
  180. package/dist/hosts/config-write.js.map +1 -0
  181. package/dist/hosts/cursor-hooks.d.ts +18 -0
  182. package/dist/hosts/cursor-hooks.d.ts.map +1 -0
  183. package/dist/hosts/cursor-hooks.js +100 -0
  184. package/dist/hosts/cursor-hooks.js.map +1 -0
  185. package/dist/hosts/init.d.ts +2 -2
  186. package/dist/hosts/init.d.ts.map +1 -1
  187. package/dist/hosts/init.js +8 -2
  188. package/dist/hosts/init.js.map +1 -1
  189. package/dist/hosts/mcp-config.d.ts +3 -5
  190. package/dist/hosts/mcp-config.d.ts.map +1 -1
  191. package/dist/hosts/mcp-config.js +5 -10
  192. package/dist/hosts/mcp-config.js.map +1 -1
  193. package/dist/hosts/plan.d.ts.map +1 -1
  194. package/dist/hosts/plan.js +7 -1
  195. package/dist/hosts/plan.js.map +1 -1
  196. package/dist/hosts/retract.d.ts.map +1 -1
  197. package/dist/hosts/retract.js +33 -13
  198. package/dist/hosts/retract.js.map +1 -1
  199. package/dist/hosts/sections.d.ts +23 -2
  200. package/dist/hosts/sections.d.ts.map +1 -1
  201. package/dist/hosts/sections.js +25 -9
  202. package/dist/hosts/sections.js.map +1 -1
  203. package/dist/index.d.ts +2 -0
  204. package/dist/index.d.ts.map +1 -1
  205. package/dist/index.js +2 -0
  206. package/dist/index.js.map +1 -1
  207. package/dist/ingest/fs.d.ts +20 -0
  208. package/dist/ingest/fs.d.ts.map +1 -1
  209. package/dist/ingest/fs.js +76 -3
  210. package/dist/ingest/fs.js.map +1 -1
  211. package/dist/mcp/server.d.ts.map +1 -1
  212. package/dist/mcp/server.js +33 -4
  213. package/dist/mcp/server.js.map +1 -1
  214. package/dist/mcp/tool-names.d.ts +20 -0
  215. package/dist/mcp/tool-names.d.ts.map +1 -0
  216. package/dist/mcp/tool-names.js +36 -0
  217. package/dist/mcp/tool-names.js.map +1 -0
  218. package/dist/mcp/tools.d.ts +11 -2
  219. package/dist/mcp/tools.d.ts.map +1 -1
  220. package/dist/mcp/tools.js +14 -22
  221. package/dist/mcp/tools.js.map +1 -1
  222. package/dist/telemetry/contract.d.ts.map +1 -1
  223. package/dist/telemetry/contract.js +10 -1
  224. package/dist/telemetry/contract.js.map +1 -1
  225. package/dist/telemetry/flush.d.ts.map +1 -1
  226. package/dist/telemetry/flush.js +1 -0
  227. package/dist/telemetry/flush.js.map +1 -1
  228. package/dist/telemetry/gate.d.ts +14 -0
  229. package/dist/telemetry/gate.d.ts.map +1 -1
  230. package/dist/telemetry/gate.js +18 -2
  231. package/dist/telemetry/gate.js.map +1 -1
  232. package/dist/telemetry/identity.d.ts +7 -0
  233. package/dist/telemetry/identity.d.ts.map +1 -1
  234. package/dist/telemetry/identity.js.map +1 -1
  235. package/dist/telemetry/index.d.ts +2 -2
  236. package/dist/telemetry/index.d.ts.map +1 -1
  237. package/dist/telemetry/index.js +2 -2
  238. package/dist/telemetry/index.js.map +1 -1
  239. package/dist/telemetry/sessions.d.ts +19 -2
  240. package/dist/telemetry/sessions.d.ts.map +1 -1
  241. package/dist/telemetry/sessions.js +57 -40
  242. package/dist/telemetry/sessions.js.map +1 -1
  243. package/dist/telemetry/track.d.ts +22 -3
  244. package/dist/telemetry/track.d.ts.map +1 -1
  245. package/dist/telemetry/track.js +34 -5
  246. package/dist/telemetry/track.js.map +1 -1
  247. package/dist/upkeep-run.d.ts.map +1 -1
  248. package/dist/upkeep-run.js +12 -2
  249. package/dist/upkeep-run.js.map +1 -1
  250. package/dist/upkeep.d.ts +25 -4
  251. package/dist/upkeep.d.ts.map +1 -1
  252. package/dist/upkeep.js +40 -1
  253. package/dist/upkeep.js.map +1 -1
  254. package/dist/util/state.d.ts +9 -0
  255. package/dist/util/state.d.ts.map +1 -1
  256. package/dist/util/state.js.map +1 -1
  257. package/package.json +2 -2
  258. package/scripts/postinstall.mjs +42 -3
  259. package/scripts/run-tests.mjs +14 -0
@@ -1 +1 @@
1
- {"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/app/review.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/app/review.ts"],"names":[],"mappings":"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"}
@@ -9,24 +9,44 @@
9
9
  * GitHub retries a delivery it considers failed and gives up after ten seconds,
10
10
  * while a review takes tens of them — so the handler validates, queues, and
11
11
  * answers 202. Everything real happens on the queue.
12
+ *
13
+ * "On the queue" used to mean "on this event loop", and that was the whole of a
14
+ * multi-minute outage: a review is synchronous end to end, so one in flight left
15
+ * this server unable to answer /healthz or serve a page it had already produced.
16
+ * The queue now runs each review in its own process (`./review-process.ts`) and
17
+ * everything in here is I/O again.
12
18
  */
13
19
  import { type Server } from "node:http";
14
20
  import { type ReviewJob } from "./events.js";
15
21
  import { type AppCredentials, type Fetch } from "./identity.js";
22
+ import { buildRepoIntoBrain } from "./brain-build.js";
16
23
  import { PageStore } from "./pages.js";
17
24
  import { WorkQueue } from "./queue.js";
18
- import { reviewPullRequest } from "./review.js";
25
+ import type { reviewPullRequest } from "./review.js";
19
26
  /** Seams for tests: nothing here has a default that touches the network. */
20
27
  export interface AppSeams {
21
28
  fetch?: Fetch;
22
- /** Swapped out to assert what the queue was handed, without a clone. */
29
+ /** Swapped out so a test can assert what the route handed the builder without
30
+ * cloning a repository or reaching GitHub. */
31
+ brainBuild?: typeof buildRepoIntoBrain;
32
+ /** Swapped out to assert what the queue was handed, without a clone — and, being
33
+ * called in-process, without the fork the default reviewer does. */
23
34
  review?: typeof reviewPullRequest;
24
35
  now?: () => number;
25
36
  }
26
37
  export interface AppConfig extends AppCredentials {
27
38
  webhookSecret: string;
39
+ /** Shared secret for `POST /brain/build`. That route is called by the
40
+ * platform, not by GitHub, so it cannot use the webhook's payload signature —
41
+ * it takes a bearer token instead. Unset disables the route entirely, which
42
+ * is the right default for a deployment that only reviews pull requests. */
43
+ brainBuildSecret?: string;
44
+ /** Platform base URL the digest is posted to. Defaults to production. */
45
+ brainBaseUrl?: string;
28
46
  /** Public origin, for the links put in comments, e.g. https://graft.example.com */
29
47
  publicUrl: string;
48
+ /** Where pages are kept, so a restart does not strand the links already posted. */
49
+ pageDir?: string;
30
50
  port?: number;
31
51
  concurrency?: number;
32
52
  api?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/app/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAC;AACjG,OAAO,EAAwB,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAuC,KAAK,cAAc,EAAE,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC;AACrG,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAKhD,4EAA4E;AAC5E,MAAM,WAAW,QAAQ;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,wEAAwE;IACxE,MAAM,CAAC,EAAE,OAAO,iBAAiB,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAU,SAAQ,cAAc;IAC/C,aAAa,EAAE,MAAM,CAAC;IACtB,mFAAmF;IACnF,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED,wBAAgB,SAAS,CACvB,MAAM,EAAE,SAAS,EACjB,KAAK,GAAE,QAAa,GACnB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,CAkFnE"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/app/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAC;AAEjG,OAAO,EAAwB,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAuC,KAAK,cAAc,EAAE,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC;AACrG,OAAO,EAAE,kBAAkB,EAA8C,MAAM,kBAAkB,CAAC;AAClG,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAKrD,4EAA4E;AAC5E,MAAM,WAAW,QAAQ;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd;kDAC8C;IAC9C,UAAU,CAAC,EAAE,OAAO,kBAAkB,CAAC;IACvC;wEACoE;IACpE,MAAM,CAAC,EAAE,OAAO,iBAAiB,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAU,SAAQ,cAAc;IAC/C,aAAa,EAAE,MAAM,CAAC;IACtB;;;gFAG4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mFAAmF;IACnF,SAAS,EAAE,MAAM,CAAC;IAClB,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED,wBAAgB,SAAS,CACvB,MAAM,EAAE,SAAS,EACjB,KAAK,GAAE,QAAa,GACnB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,CAoInE"}
@@ -9,21 +9,29 @@
9
9
  * GitHub retries a delivery it considers failed and gives up after ten seconds,
10
10
  * while a review takes tens of them — so the handler validates, queues, and
11
11
  * answers 202. Everything real happens on the queue.
12
+ *
13
+ * "On the queue" used to mean "on this event loop", and that was the whole of a
14
+ * multi-minute outage: a review is synchronous end to end, so one in flight left
15
+ * this server unable to answer /healthz or serve a page it had already produced.
16
+ * The queue now runs each review in its own process (`./review-process.ts`) and
17
+ * everything in here is I/O again.
12
18
  */
13
19
  import { createServer } from "node:http";
20
+ import { timingSafeEqual } from "node:crypto";
14
21
  import { jobKey, reviewJobFor } from "./events.js";
15
22
  import { InstallationTokens, verifySignature } from "./identity.js";
23
+ import { buildRepoIntoBrain, RepoNotAccessibleError } from "./brain-build.js";
16
24
  import { PageStore } from "./pages.js";
17
25
  import { WorkQueue } from "./queue.js";
18
- import { reviewPullRequest } from "./review.js";
26
+ import { reviewInChildProcess } from "./review-process.js";
19
27
  /** A webhook body larger than this is not a pull_request event we can use. */
20
28
  const MAX_BODY_BYTES = 2 * 1024 * 1024;
21
29
  export function createApp(config, seams = {}) {
22
30
  const log = config.log ?? ((msg) => console.log(msg));
23
31
  const fetchImpl = seams.fetch ?? globalThis.fetch;
24
- const review = seams.review ?? reviewPullRequest;
32
+ const review = seams.review ?? reviewInChildProcess;
25
33
  const tokens = new InstallationTokens(config, fetchImpl, seams.now ?? Date.now, config.api);
26
- const pages = new PageStore({ secret: config.webhookSecret });
34
+ const pages = new PageStore({ secret: config.webhookSecret, dir: config.pageDir });
27
35
  const origin = config.publicUrl.replace(/\/$/, "");
28
36
  const queue = new WorkQueue(async (job) => {
29
37
  const started = Date.now();
@@ -88,6 +96,60 @@ export function createApp(config, seams = {}) {
88
96
  log(`${jobKey(decided.job)}: queued${decided.job.fromFork ? " (fork)" : ""}`);
89
97
  return send(res, 202, "application/json", JSON.stringify({ queued: true }));
90
98
  }
99
+ // Build one repository into a brain, on demand. Called by the platform when
100
+ // someone pastes a repository URL during onboarding — there is no webhook
101
+ // behind it, so it authenticates with a bearer token rather than a payload
102
+ // signature.
103
+ if (req.method === "POST" && url.pathname === "/brain/build") {
104
+ if (!config.brainBuildSecret)
105
+ return send(res, 404, "text/plain", "not found");
106
+ // Compared in constant time for the same reason verifySignature is: this
107
+ // is a long-lived shared secret, and a timing oracle on it is worth more
108
+ // to an attacker than one on a per-payload signature.
109
+ if (!bearerMatches(header(req, "authorization"), config.brainBuildSecret)) {
110
+ return send(res, 401, "text/plain", "unauthorized");
111
+ }
112
+ const body = await readBody(req);
113
+ if (body === null)
114
+ return send(res, 413, "text/plain", "payload too large");
115
+ let job;
116
+ try {
117
+ job = JSON.parse(body);
118
+ }
119
+ catch {
120
+ return send(res, 400, "text/plain", "bad json");
121
+ }
122
+ // brainId/brainToken are optional: without them the digest comes back in
123
+ // the response for the caller to ingest itself. See BrainBuildJob.
124
+ if (!job.owner || !job.repo) {
125
+ return send(res, 400, "application/json", JSON.stringify({ error: "owner and repo are required" }));
126
+ }
127
+ // Synchronous on purpose: the caller is a person waiting on a screen, and
128
+ // the platform's own import job is what makes the SLOW half (extraction and
129
+ // placement) asynchronous. This half is a shallow clone and a graph build.
130
+ try {
131
+ // The deployment's platform URL wins over anything a caller sends, so a
132
+ // request cannot redirect a repository's history to another host.
133
+ if (config.brainBaseUrl)
134
+ job.brainBaseUrl = config.brainBaseUrl;
135
+ const built = await (seams.brainBuild ?? buildRepoIntoBrain)(job, {
136
+ creds: config,
137
+ fetch: fetchImpl,
138
+ api: config.api,
139
+ log,
140
+ now: seams.now,
141
+ });
142
+ return send(res, 202, "application/json", JSON.stringify(built));
143
+ }
144
+ catch (e) {
145
+ if (e instanceof RepoNotAccessibleError) {
146
+ return send(res, 404, "application/json", JSON.stringify({ error: e.message, ...e.gap }));
147
+ }
148
+ const msg = e instanceof Error ? e.message : String(e);
149
+ log(`brain build ${job.owner}/${job.repo} failed: ${msg}`);
150
+ return send(res, 502, "application/json", JSON.stringify({ error: msg }));
151
+ }
152
+ }
91
153
  return send(res, 404, "text/plain", "not found");
92
154
  }
93
155
  if (config.port !== undefined)
@@ -98,6 +160,18 @@ const header = (req, name) => {
98
160
  const v = req.headers[name];
99
161
  return Array.isArray(v) ? v[0] : v;
100
162
  };
163
+ /** Constant-time `Authorization: Bearer <secret>` check. */
164
+ function bearerMatches(headerValue, secret) {
165
+ const prefix = "Bearer ";
166
+ if (!headerValue || !headerValue.startsWith(prefix))
167
+ return false;
168
+ const given = Buffer.from(headerValue.slice(prefix.length));
169
+ const want = Buffer.from(secret);
170
+ // timingSafeEqual throws on a length mismatch, which is itself a leak of the
171
+ // secret's length — but one byte of length is not worth a branch that skips
172
+ // the comparison, and the lengths here are fixed by deployment config.
173
+ return given.length === want.length && timingSafeEqual(given, want);
174
+ }
101
175
  function send(res, status, type, body, extra = {}) {
102
176
  res.writeHead(status, { "content-type": type, ...extra });
103
177
  res.end(body);
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/app/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/app/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import type { Fetch } from "./identity.js";
2
+ /** What kind of thing a source is, so extraction can weigh it. */
3
+ export type SourceKind = "agent_instructions" | "decision_doc" | "lint_config" | "ci_config" | "codeowners" | "branch_protection" | "revert" | "test_name" | "declined_issue";
4
+ /** One rule-bearing artefact. */
5
+ export interface HistorySource {
6
+ kind: SourceKind;
7
+ /** Repo-relative path, or an API-ish label like "branch protection: main". */
8
+ path: string;
9
+ text: string;
10
+ /** Deep link, where one exists (an issue, a reverted commit). */
11
+ url?: string;
12
+ }
13
+ /**
14
+ * Instruction files the team already wrote for coding agents.
15
+ *
16
+ * The single highest-precision source in a repository: someone sat down and
17
+ * wrote imperative rules for a machine to follow. Nothing has to be inferred.
18
+ *
19
+ * Graft's own managed blocks are stripped first. Without that the brain reads
20
+ * back graft's instructions about using graft, and then graft carries them into
21
+ * the same file — a loop that fills the rulebook with itself.
22
+ */
23
+ export declare function readAgentInstructions(root: string): HistorySource[];
24
+ /** Architecture decision records and the docs that read like them. */
25
+ export declare function readDecisionDocs(root: string): HistorySource[];
26
+ /**
27
+ * Rules the team already encoded for a machine: linters, formatters, and the
28
+ * checks CI insists on. Nothing to infer — extraction only has to phrase them.
29
+ */
30
+ export declare function readCodifiedRules(root: string): HistorySource[];
31
+ /** Who must approve what. A hard constraint, stated as a file. */
32
+ export declare function readCodeowners(root: string): HistorySource[];
33
+ /**
34
+ * Commits that undid another commit.
35
+ *
36
+ * "We tried this and took it back" is a rule available from nowhere else, and
37
+ * it is the one kind of history that says what NOT to do. The body of a revert
38
+ * usually names the commit it undoes and, when the author bothered, why.
39
+ */
40
+ export declare function readReverts(root: string, max?: number): HistorySource[];
41
+ /**
42
+ * Test names, which are invariants someone wrote deliberately.
43
+ *
44
+ * `never retries on a card decline` is a rule stated as an assertion. Read from
45
+ * the graph's own symbols rather than by re-parsing, so this costs nothing:
46
+ * a test function is already a node.
47
+ *
48
+ * Only names that read like a sentence are kept. `TestFoo` is a label;
49
+ * `rejects an expired token` is a claim about how the system must behave.
50
+ */
51
+ export declare function readTestNames(symbolNames: Array<{
52
+ name: string;
53
+ path: string;
54
+ }>, max?: number): HistorySource[];
55
+ /**
56
+ * Issues closed as not planned.
57
+ *
58
+ * A decision NOT to build something, which is half of what a codebase's rules
59
+ * are and is invisible everywhere else — nothing was committed, so no commit
60
+ * message records it.
61
+ */
62
+ export declare function readDeclinedIssues(owner: string, repo: string, token: string, fetchImpl: Fetch, api?: string, max?: number): Promise<HistorySource[]>;
63
+ /** Required checks and reviewers on the default branch. */
64
+ export declare function readBranchProtection(owner: string, repo: string, branch: string, token: string, fetchImpl: Fetch, api?: string): Promise<HistorySource[]>;
65
+ export declare function budgetSources(sources: HistorySource[], maxChars?: number, maxCount?: number): HistorySource[];
66
+ /** Repo-relative path, for readers handed an absolute one. */
67
+ export declare function relPath(root: string, abs: string): string;
68
+ //# sourceMappingURL=sources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../../src/app/sources.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAE3C,kEAAkE;AAClE,MAAM,MAAM,UAAU,GAClB,oBAAoB,GACpB,cAAc,GACd,aAAa,GACb,WAAW,GACX,YAAY,GACZ,mBAAmB,GACnB,QAAQ,GACR,WAAW,GACX,gBAAgB,CAAC;AAErB,iCAAiC;AACjC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,UAAU,CAAC;IACjB,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAkCD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAenE;AASD,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAiB9D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CA0B/D;AAED,kEAAkE;AAClE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAM5D;AAiBD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAc,GAAG,aAAa,EAAE,CAe5E;AAKD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,GAAG,SAAiB,GAAG,aAAa,EAAE,CAUvH;AAqBD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,KAAK,EAChB,GAAG,SAA2B,EAC9B,GAAG,SAAe,GACjB,OAAO,CAAC,aAAa,EAAE,CAAC,CAkC1B;AAED,2DAA2D;AAC3D,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,KAAK,EAChB,GAAG,SAA2B,GAC7B,OAAO,CAAC,aAAa,EAAE,CAAC,CA2B1B;AAsBD,wBAAgB,aAAa,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,QAAQ,SAAkB,EAAE,QAAQ,SAAc,GAAG,aAAa,EAAE,CAW3H;AAED,8DAA8D;AAC9D,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEzD"}
@@ -0,0 +1,341 @@
1
+ /**
2
+ * Everything in a repository that is already a rule, or nearly one.
3
+ *
4
+ * Commit messages and pull-request discussion say what a team decided in
5
+ * passing. These are the places where they wrote it down on purpose: the
6
+ * instruction files they hand their own agents, the decision records, the linter
7
+ * config, the ownership rules. Higher precision per byte than any amount of
8
+ * history, and most of it is a file read.
9
+ *
10
+ * Every reader returns text, never source code, and every one is best-effort:
11
+ * a repo with none of these still builds a brain from its history.
12
+ */
13
+ import { readFileSync, existsSync, readdirSync, statSync } from "node:fs";
14
+ import { join, relative } from "node:path";
15
+ import { spawnSync } from "node:child_process";
16
+ /** Per-file and total caps, so one enormous doc cannot crowd out everything. */
17
+ const MAX_FILE_CHARS = 24_000;
18
+ const MAX_TOTAL_CHARS = 300_000;
19
+ const MAX_SOURCES = 120;
20
+ function readText(root, rel) {
21
+ try {
22
+ const p = join(root, rel);
23
+ if (!existsSync(p) || !statSync(p).isFile())
24
+ return null;
25
+ const raw = readFileSync(p, "utf8");
26
+ const trimmed = raw.trim();
27
+ if (!trimmed)
28
+ return null;
29
+ return trimmed.length > MAX_FILE_CHARS ? `${trimmed.slice(0, MAX_FILE_CHARS)}\n[…truncated]` : trimmed;
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ }
35
+ /** Files directly under `rel`, one level deep, matching `test`. */
36
+ function filesIn(root, rel, test) {
37
+ try {
38
+ const dir = join(root, rel);
39
+ if (!existsSync(dir) || !statSync(dir).isDirectory())
40
+ return [];
41
+ return readdirSync(dir)
42
+ .filter(test)
43
+ .map((n) => join(rel, n))
44
+ .sort();
45
+ }
46
+ catch {
47
+ return [];
48
+ }
49
+ }
50
+ /**
51
+ * Instruction files the team already wrote for coding agents.
52
+ *
53
+ * The single highest-precision source in a repository: someone sat down and
54
+ * wrote imperative rules for a machine to follow. Nothing has to be inferred.
55
+ *
56
+ * Graft's own managed blocks are stripped first. Without that the brain reads
57
+ * back graft's instructions about using graft, and then graft carries them into
58
+ * the same file — a loop that fills the rulebook with itself.
59
+ */
60
+ export function readAgentInstructions(root) {
61
+ const candidates = [
62
+ "CLAUDE.md",
63
+ "AGENTS.md",
64
+ "GEMINI.md",
65
+ ".github/copilot-instructions.md",
66
+ ".windsurf/rules/graft.md",
67
+ ...filesIn(root, ".cursor/rules", (n) => n.endsWith(".mdc") || n.endsWith(".md")),
68
+ ];
69
+ const out = [];
70
+ for (const rel of candidates) {
71
+ const text = stripManagedBlocks(readText(root, rel) ?? "");
72
+ if (text.trim())
73
+ out.push({ kind: "agent_instructions", path: rel, text });
74
+ }
75
+ return out;
76
+ }
77
+ /** Remove graft's own fenced regions, so the brain never learns graft from graft. */
78
+ function stripManagedBlocks(text) {
79
+ return text
80
+ .replace(/<!--\s*graft:(brain:)?start\s*-->[\s\S]*?<!--\s*graft:(brain:)?end\s*-->/g, "")
81
+ .trim();
82
+ }
83
+ /** Architecture decision records and the docs that read like them. */
84
+ export function readDecisionDocs(root) {
85
+ const mdIn = (dir) => filesIn(root, dir, (n) => n.endsWith(".md"));
86
+ const candidates = [
87
+ "ARCHITECTURE.md",
88
+ "CONTRIBUTING.md",
89
+ "docs/ARCHITECTURE.md",
90
+ "docs/CONTRIBUTING.md",
91
+ ...mdIn("docs/adr"),
92
+ ...mdIn("docs/decisions"),
93
+ ...mdIn("adr"),
94
+ ];
95
+ const out = [];
96
+ for (const rel of candidates) {
97
+ const text = readText(root, rel);
98
+ if (text)
99
+ out.push({ kind: "decision_doc", path: rel, text });
100
+ }
101
+ return out;
102
+ }
103
+ /**
104
+ * Rules the team already encoded for a machine: linters, formatters, and the
105
+ * checks CI insists on. Nothing to infer — extraction only has to phrase them.
106
+ */
107
+ export function readCodifiedRules(root) {
108
+ const lint = [
109
+ ".golangci.yml",
110
+ ".golangci.yaml",
111
+ ".eslintrc.json",
112
+ ".eslintrc.js",
113
+ "eslint.config.js",
114
+ "eslint.config.mjs",
115
+ "ruff.toml",
116
+ ".ruff.toml",
117
+ ".prettierrc",
118
+ ".prettierrc.json",
119
+ "commitlint.config.cjs",
120
+ "commitlint.config.js",
121
+ ".editorconfig",
122
+ ];
123
+ const out = [];
124
+ for (const rel of lint) {
125
+ const text = readText(root, rel);
126
+ if (text)
127
+ out.push({ kind: "lint_config", path: rel, text });
128
+ }
129
+ for (const rel of filesIn(root, ".github/workflows", (n) => n.endsWith(".yml") || n.endsWith(".yaml"))) {
130
+ const text = readText(root, rel);
131
+ if (text)
132
+ out.push({ kind: "ci_config", path: rel, text });
133
+ }
134
+ return out;
135
+ }
136
+ /** Who must approve what. A hard constraint, stated as a file. */
137
+ export function readCodeowners(root) {
138
+ for (const rel of [".github/CODEOWNERS", "CODEOWNERS", "docs/CODEOWNERS"]) {
139
+ const text = readText(root, rel);
140
+ if (text)
141
+ return [{ kind: "codeowners", path: rel, text }];
142
+ }
143
+ return [];
144
+ }
145
+ /** Run git in `root`, or null when it fails. */
146
+ function git(root, args) {
147
+ const res = spawnSync("git", ["-c", "core.quotePath=false", ...args], {
148
+ cwd: root,
149
+ encoding: "utf8",
150
+ stdio: ["ignore", "pipe", "pipe"],
151
+ maxBuffer: 64 * 1024 * 1024,
152
+ });
153
+ if (res.error || res.status !== 0 || typeof res.stdout !== "string")
154
+ return null;
155
+ return res.stdout;
156
+ }
157
+ /** How many reverts to carry. */
158
+ const MAX_REVERTS = 40;
159
+ /**
160
+ * Commits that undid another commit.
161
+ *
162
+ * "We tried this and took it back" is a rule available from nowhere else, and
163
+ * it is the one kind of history that says what NOT to do. The body of a revert
164
+ * usually names the commit it undoes and, when the author bothered, why.
165
+ */
166
+ export function readReverts(root, max = MAX_REVERTS) {
167
+ const out = git(root, ["log", "--grep=^Revert", "-n", String(max), "--format=%H%x02%s%x02%b%x01"]);
168
+ if (!out)
169
+ return [];
170
+ const sources = [];
171
+ for (const record of out.split("\x01")) {
172
+ if (!record.trim())
173
+ continue;
174
+ const [sha = "", subject = "", body = ""] = record.split("\x02");
175
+ if (!sha.trim() || !subject.trim())
176
+ continue;
177
+ sources.push({
178
+ kind: "revert",
179
+ path: `revert ${sha.trim().slice(0, 12)}`,
180
+ text: [subject.trim(), body.trim()].filter(Boolean).join("\n"),
181
+ });
182
+ }
183
+ return sources;
184
+ }
185
+ /** How many test names to carry. */
186
+ const MAX_TEST_NAMES = 300;
187
+ /**
188
+ * Test names, which are invariants someone wrote deliberately.
189
+ *
190
+ * `never retries on a card decline` is a rule stated as an assertion. Read from
191
+ * the graph's own symbols rather than by re-parsing, so this costs nothing:
192
+ * a test function is already a node.
193
+ *
194
+ * Only names that read like a sentence are kept. `TestFoo` is a label;
195
+ * `rejects an expired token` is a claim about how the system must behave.
196
+ */
197
+ export function readTestNames(symbolNames, max = MAX_TEST_NAMES) {
198
+ const out = [];
199
+ for (const s of symbolNames) {
200
+ if (!/(^|[/.])(test|spec)[s]?[/.]|_test\.|\.test\.|\.spec\./i.test(s.path))
201
+ continue;
202
+ const sentence = humanizeTestName(s.name);
203
+ if (!sentence)
204
+ continue;
205
+ out.push({ kind: "test_name", path: s.path, text: sentence });
206
+ if (out.length === max)
207
+ break;
208
+ }
209
+ return out;
210
+ }
211
+ /**
212
+ * A test's name as a claim, or null when it is only a label.
213
+ *
214
+ * Requires three words after the prefix is stripped: fewer than that
215
+ * ("TestParse", "handles errors") states no invariant worth a rule, and letting
216
+ * those through fills the brain with noise that reads like content.
217
+ */
218
+ function humanizeTestName(name) {
219
+ let s = name.replace(/^(Test|it|test|should|describe)[_\s]*/i, "");
220
+ // TestRetriesThreeTimes → Retries Three Times
221
+ if (/^[A-Za-z]+$/.test(s) && /[a-z][A-Z]/.test(s))
222
+ s = s.replace(/([a-z0-9])([A-Z])/g, "$1 $2");
223
+ s = s.replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
224
+ if (s.split(" ").length < 3)
225
+ return null;
226
+ return s.toLowerCase();
227
+ }
228
+ /** How many declined issues to carry. */
229
+ const MAX_DECLINED = 40;
230
+ /**
231
+ * Issues closed as not planned.
232
+ *
233
+ * A decision NOT to build something, which is half of what a codebase's rules
234
+ * are and is invisible everywhere else — nothing was committed, so no commit
235
+ * message records it.
236
+ */
237
+ export async function readDeclinedIssues(owner, repo, token, fetchImpl, api = "https://api.github.com", max = MAX_DECLINED) {
238
+ try {
239
+ const res = await fetchImpl(`${api}/repos/${owner}/${repo}/issues?state=closed&per_page=100&sort=updated`, {
240
+ headers: { authorization: `Bearer ${token}`, accept: "application/vnd.github+json", "user-agent": "graft-app" },
241
+ });
242
+ if (!res.ok)
243
+ return [];
244
+ const items = JSON.parse(await res.text());
245
+ if (!Array.isArray(items))
246
+ return [];
247
+ const out = [];
248
+ for (const i of items) {
249
+ // The issues endpoint returns pull requests too; they are already mined as
250
+ // threads and would be counted twice.
251
+ if (i.pull_request)
252
+ continue;
253
+ if (i.state_reason !== "not_planned")
254
+ continue;
255
+ if (!i.title?.trim())
256
+ continue;
257
+ out.push({
258
+ kind: "declined_issue",
259
+ path: `issue #${i.number}`,
260
+ text: [i.title.trim(), (i.body ?? "").trim()].filter(Boolean).join("\n").slice(0, MAX_FILE_CHARS),
261
+ url: i.html_url,
262
+ });
263
+ if (out.length === max)
264
+ break;
265
+ }
266
+ return out;
267
+ }
268
+ catch {
269
+ return [];
270
+ }
271
+ }
272
+ /** Required checks and reviewers on the default branch. */
273
+ export async function readBranchProtection(owner, repo, branch, token, fetchImpl, api = "https://api.github.com") {
274
+ if (!branch)
275
+ return [];
276
+ try {
277
+ const res = await fetchImpl(`${api}/repos/${owner}/${repo}/branches/${encodeURIComponent(branch)}/protection`, {
278
+ headers: { authorization: `Bearer ${token}`, accept: "application/vnd.github+json", "user-agent": "graft-app" },
279
+ });
280
+ // 404 simply means the branch is not protected, which is not a failure.
281
+ if (!res.ok)
282
+ return [];
283
+ const p = JSON.parse(await res.text());
284
+ const lines = [];
285
+ const checks = p.required_status_checks?.contexts ?? [];
286
+ if (checks.length)
287
+ lines.push(`Checks that must pass before merging to ${branch}: ${checks.join(", ")}.`);
288
+ const reviews = p.required_pull_request_reviews;
289
+ if (reviews?.required_approving_review_count) {
290
+ lines.push(`${reviews.required_approving_review_count} approving review(s) required to merge to ${branch}.`);
291
+ }
292
+ if (reviews?.require_code_owner_reviews)
293
+ lines.push(`A code owner must approve changes to ${branch}.`);
294
+ if (p.allow_force_pushes?.enabled === false)
295
+ lines.push(`Force pushes to ${branch} are not allowed.`);
296
+ if (!lines.length)
297
+ return [];
298
+ return [{ kind: "branch_protection", path: `branch protection: ${branch}`, text: lines.join("\n") }];
299
+ }
300
+ catch {
301
+ return [];
302
+ }
303
+ }
304
+ /**
305
+ * Trim the collected sources to a budget, best kinds first.
306
+ *
307
+ * The order is the argument of this whole module: a file the team wrote to
308
+ * instruct an agent outranks a decision doc, which outranks a config, which
309
+ * outranks anything inferred. When the budget runs out it should run out on the
310
+ * weakest evidence.
311
+ */
312
+ const KIND_RANK = [
313
+ "agent_instructions",
314
+ "decision_doc",
315
+ "codeowners",
316
+ "branch_protection",
317
+ "lint_config",
318
+ "ci_config",
319
+ "revert",
320
+ "declined_issue",
321
+ "test_name",
322
+ ];
323
+ export function budgetSources(sources, maxChars = MAX_TOTAL_CHARS, maxCount = MAX_SOURCES) {
324
+ const ranked = [...sources].sort((a, b) => KIND_RANK.indexOf(a.kind) - KIND_RANK.indexOf(b.kind));
325
+ const out = [];
326
+ let spent = 0;
327
+ for (const s of ranked) {
328
+ if (out.length >= maxCount)
329
+ break;
330
+ if (spent + s.text.length > maxChars)
331
+ continue;
332
+ out.push(s);
333
+ spent += s.text.length;
334
+ }
335
+ return out;
336
+ }
337
+ /** Repo-relative path, for readers handed an absolute one. */
338
+ export function relPath(root, abs) {
339
+ return relative(root, abs) || abs;
340
+ }
341
+ //# sourceMappingURL=sources.js.map