limn-review 0.1.123

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 (474) hide show
  1. package/LICENSE +110 -0
  2. package/README.md +133 -0
  3. package/dist/ai/runtime.js +535 -0
  4. package/dist/api/plugins/auth.js +169 -0
  5. package/dist/api/plugins/error-handler.js +114 -0
  6. package/dist/api/plugins/rate-limit.js +855 -0
  7. package/dist/api/plugins/security.js +321 -0
  8. package/dist/api/routes/activity.js +103 -0
  9. package/dist/api/routes/ai-runtime.js +67 -0
  10. package/dist/api/routes/auth.js +194 -0
  11. package/dist/api/routes/billing.js +209 -0
  12. package/dist/api/routes/bot-triage.js +1289 -0
  13. package/dist/api/routes/conflicts.js +730 -0
  14. package/dist/api/routes/contact.js +318 -0
  15. package/dist/api/routes/daily-brief.js +58 -0
  16. package/dist/api/routes/flow.js +71 -0
  17. package/dist/api/routes/health.js +7 -0
  18. package/dist/api/routes/insights.js +200 -0
  19. package/dist/api/routes/me.js +458 -0
  20. package/dist/api/routes/mentions.js +22 -0
  21. package/dist/api/routes/mergers.js +8 -0
  22. package/dist/api/routes/ml-labels.js +109 -0
  23. package/dist/api/routes/open-prs.js +35 -0
  24. package/dist/api/routes/prs.js +1633 -0
  25. package/dist/api/routes/reactions.js +217 -0
  26. package/dist/api/routes/repos.js +563 -0
  27. package/dist/api/routes/search.js +41 -0
  28. package/dist/api/routes/threads.js +118 -0
  29. package/dist/api/routes/timeline.js +150 -0
  30. package/dist/api/routes/users.js +67 -0
  31. package/dist/api/routes/webhooks.js +181 -0
  32. package/dist/api/routes/workspaces.js +322 -0
  33. package/dist/app.js +274 -0
  34. package/dist/ascii.js +19 -0
  35. package/dist/auth/account.js +482 -0
  36. package/dist/auth/crypto.js +46 -0
  37. package/dist/bot-triage/resolve.js +59 -0
  38. package/dist/cli.js +388 -0
  39. package/dist/coding/activity.js +80 -0
  40. package/dist/coding/agent.js +288 -0
  41. package/dist/coding/ai-fix/auto-fix.js +212 -0
  42. package/dist/coding/ai-fix/manager.js +370 -0
  43. package/dist/coding/ai-fix/persist.js +213 -0
  44. package/dist/coding/ai-fix/pr-context.js +58 -0
  45. package/dist/coding/ai-fix/prompts.js +138 -0
  46. package/dist/coding/ai-fix/review-seed.js +357 -0
  47. package/dist/coding/ai-fix/routes.js +425 -0
  48. package/dist/coding/git-ops.js +321 -0
  49. package/dist/coding/git.js +184 -0
  50. package/dist/coding/merge.js +262 -0
  51. package/dist/coding/safe-path.js +75 -0
  52. package/dist/coding/schema.js +43 -0
  53. package/dist/config.js +648 -0
  54. package/dist/conflict/diff.js +304 -0
  55. package/dist/conflict/git.js +118 -0
  56. package/dist/conflict/hash.js +73 -0
  57. package/dist/conflict/janitor.js +218 -0
  58. package/dist/conflict/land.js +675 -0
  59. package/dist/conflict/model-types.js +2 -0
  60. package/dist/conflict/model.js +1081 -0
  61. package/dist/conflict/parse.js +142 -0
  62. package/dist/conflict/seam.js +136 -0
  63. package/dist/conflict/session.js +532 -0
  64. package/dist/conflict/suggestion.js +398 -0
  65. package/dist/conflict/tokens.js +72 -0
  66. package/dist/data-dir.js +112 -0
  67. package/dist/db/actor-lanes.js +213 -0
  68. package/dist/db/automation-ids.js +97 -0
  69. package/dist/db/automation-output.js +349 -0
  70. package/dist/db/blast-radius-query.js +36 -0
  71. package/dist/db/blast-radius.js +226 -0
  72. package/dist/db/bot-dormancy.js +115 -0
  73. package/dist/db/bot-overlap.js +579 -0
  74. package/dist/db/bot-volume.js +722 -0
  75. package/dist/db/bot-window.js +35 -0
  76. package/dist/db/branch-queries.js +310 -0
  77. package/dist/db/change-shape.js +243 -0
  78. package/dist/db/changepoint.js +75 -0
  79. package/dist/db/cleanup.js +36 -0
  80. package/dist/db/client.js +102 -0
  81. package/dist/db/code-loc.js +388 -0
  82. package/dist/db/credits.js +79 -0
  83. package/dist/db/daily-brief.js +406 -0
  84. package/dist/db/dependency-cards.js +145 -0
  85. package/dist/db/erase-account.js +255 -0
  86. package/dist/db/export-account.js +189 -0
  87. package/dist/db/failing-checks.js +124 -0
  88. package/dist/db/file-coupling.js +197 -0
  89. package/dist/db/flow-detail.js +661 -0
  90. package/dist/db/flow-pointers.js +197 -0
  91. package/dist/db/flow-settings.js +67 -0
  92. package/dist/db/forecast.js +114 -0
  93. package/dist/db/line-overlap.js +81 -0
  94. package/dist/db/merge-queue.js +189 -0
  95. package/dist/db/migrate.js +17 -0
  96. package/dist/db/migrations/0000_purple_ben_grimm.sql +155 -0
  97. package/dist/db/migrations/0001_colorful_ozymandias.sql +31 -0
  98. package/dist/db/migrations/0002_famous_sersi.sql +9 -0
  99. package/dist/db/migrations/0003_clever_shinobi_shaw.sql +3 -0
  100. package/dist/db/migrations/0004_pale_scalphunter.sql +1 -0
  101. package/dist/db/migrations/0005_daffy_guardian.sql +2 -0
  102. package/dist/db/migrations/0006_cute_violations.sql +45 -0
  103. package/dist/db/migrations/0007_dark_anthem.sql +2 -0
  104. package/dist/db/migrations/0008_multitenant_accounts.sql +44 -0
  105. package/dist/db/migrations/0009_lean_bodies.sql +13 -0
  106. package/dist/db/migrations/0010_lean_bodies_nullable.sql +56 -0
  107. package/dist/db/migrations/0011_pr_diff_size.sql +10 -0
  108. package/dist/db/migrations/0012_findings_included_default.sql +7 -0
  109. package/dist/db/migrations/0013_review_routing.sql +9 -0
  110. package/dist/db/migrations/0014_account_last_active.sql +6 -0
  111. package/dist/db/migrations/0015_repos_inbox_watch.sql +9 -0
  112. package/dist/db/migrations/0016_repo_viewer_permission.sql +7 -0
  113. package/dist/db/migrations/0017_account_display_name.sql +7 -0
  114. package/dist/db/migrations/0018_finding_comment_kind.sql +7 -0
  115. package/dist/db/migrations/0019_finding_file_in_diff.sql +7 -0
  116. package/dist/db/migrations/0020_claude_review_cost_telemetry.sql +11 -0
  117. package/dist/db/migrations/0021_account_feed_last_seen.sql +7 -0
  118. package/dist/db/migrations/0022_ci_status_events.sql +21 -0
  119. package/dist/db/migrations/0023_ai_usage.sql +21 -0
  120. package/dist/db/migrations/0024_pr_head_ref_name.sql +6 -0
  121. package/dist/db/migrations/0025_account_billing.sql +7 -0
  122. package/dist/db/migrations/0026_ai_credit_allowance.sql +5 -0
  123. package/dist/db/migrations/0027_user_github_type.sql +6 -0
  124. package/dist/db/migrations/0028_bot_review_classification.sql +21 -0
  125. package/dist/db/migrations/0029_bot_mute_rules.sql +19 -0
  126. package/dist/db/migrations/0030_teams.sql +32 -0
  127. package/dist/db/migrations/0031_events_pr_idx.sql +7 -0
  128. package/dist/db/migrations/0032_benchmark_contributions.sql +29 -0
  129. package/dist/db/migrations/0033_thread_addressed_confidence.sql +9 -0
  130. package/dist/db/migrations/0034_thread_resolved_at.sql +6 -0
  131. package/dist/db/migrations/0035_pr_first_review_requested_at.sql +5 -0
  132. package/dist/db/migrations/0036_search_index.sql +25 -0
  133. package/dist/db/migrations/0037_author_indexes.sql +15 -0
  134. package/dist/db/migrations/0038_auto_merge_requests.sql +37 -0
  135. package/dist/db/migrations/0039_branch_status.sql +44 -0
  136. package/dist/db/migrations/0040_pr_review_decision.sql +10 -0
  137. package/dist/db/migrations/0041_branch_commit_detail.sql +38 -0
  138. package/dist/db/migrations/0042_repo_reviewers.sql +176 -0
  139. package/dist/db/migrations/0043_account_reviewers.sql +131 -0
  140. package/dist/db/migrations/0044_workspaces.sql +138 -0
  141. package/dist/db/migrations/0045_workspace_reviewers.sql +180 -0
  142. package/dist/db/migrations/0046_drop_inbox_watch.sql +25 -0
  143. package/dist/db/migrations/0047_ml_comment_labels.sql +40 -0
  144. package/dist/db/migrations/0048_ml_vendor_severity.sql +31 -0
  145. package/dist/db/migrations/0049_seat_pricing_repo_description.sql +21 -0
  146. package/dist/db/migrations/0050_users_app_slug.sql +12 -0
  147. package/dist/db/migrations/0051_auto_merge_queue.sql +17 -0
  148. package/dist/db/migrations/0052_trunk_ci_status_events.sql +43 -0
  149. package/dist/db/migrations/0053_automation_roles.sql +79 -0
  150. package/dist/db/migrations/0054_automation_vendor_kinds.sql +514 -0
  151. package/dist/db/migrations/0055_auto_merge_phase.sql +12 -0
  152. package/dist/db/migrations/0056_pr_mentions.sql +22 -0
  153. package/dist/db/migrations/0057_large_pr_threshold.sql +14 -0
  154. package/dist/db/migrations/0058_pending_mute.sql +53 -0
  155. package/dist/db/migrations/0059_merge_queue_state.sql +33 -0
  156. package/dist/db/migrations/0060_drop_my_turn_dismissals.sql +33 -0
  157. package/dist/db/migrations/0061_auto_merge_durable_anchors.sql +27 -0
  158. package/dist/db/migrations/0062_blast_radius_config.sql +21 -0
  159. package/dist/db/migrations/0063_repo_file_coupling.sql +33 -0
  160. package/dist/db/migrations/0064_pr_content_kind.sql +21 -0
  161. package/dist/db/migrations/0065_workspace_flow_settings.sql +13 -0
  162. package/dist/db/migrations/0066_review_request_events.sql +31 -0
  163. package/dist/db/migrations/0067_pr_security_signals.sql +86 -0
  164. package/dist/db/migrations/0068_my_turn_settings.sql +18 -0
  165. package/dist/db/migrations/0069_my_turn_dismissals.sql +41 -0
  166. package/dist/db/migrations/0070_claude_review_follow_up_ticket.sql +22 -0
  167. package/dist/db/migrations/0071_claude_review_trigger.sql +11 -0
  168. package/dist/db/migrations/0072_commit_message_headline.sql +13 -0
  169. package/dist/db/migrations/0073_claude_review_chat.sql +31 -0
  170. package/dist/db/migrations/0074_adopt_agentic_tables.sql +98 -0
  171. package/dist/db/migrations/0075_review_lens_drop_learnings.sql +15 -0
  172. package/dist/db/migrations/0076_claude_review_threads.sql +17 -0
  173. package/dist/db/migrations/0077_claude_review_ci_failures.sql +10 -0
  174. package/dist/db/migrations/0078_ai_fix_change_report.sql +17 -0
  175. package/dist/db/migrations/0079_claude_finding_story.sql +16 -0
  176. package/dist/db/migrations/meta/0000_snapshot.json +1116 -0
  177. package/dist/db/migrations/meta/0001_snapshot.json +1321 -0
  178. package/dist/db/migrations/meta/0002_snapshot.json +1375 -0
  179. package/dist/db/migrations/meta/0003_snapshot.json +1396 -0
  180. package/dist/db/migrations/meta/0004_snapshot.json +1416 -0
  181. package/dist/db/migrations/meta/0005_snapshot.json +1430 -0
  182. package/dist/db/migrations/meta/0006_snapshot.json +1745 -0
  183. package/dist/db/migrations/meta/0007_snapshot.json +1759 -0
  184. package/dist/db/migrations/meta/_journal.json +566 -0
  185. package/dist/db/migrations-pg/0000_tired_alex_power.sql +268 -0
  186. package/dist/db/migrations-pg/0001_dizzy_mockingbird.sql +3 -0
  187. package/dist/db/migrations-pg/0002_glorious_ikaris.sql +4 -0
  188. package/dist/db/migrations-pg/0003_melted_secret_warriors.sql +2 -0
  189. package/dist/db/migrations-pg/0004_numerous_triton.sql +1 -0
  190. package/dist/db/migrations-pg/0005_thick_blockbuster.sql +2 -0
  191. package/dist/db/migrations-pg/0006_majestic_dracula.sql +1 -0
  192. package/dist/db/migrations-pg/0007_same_human_torch.sql +2 -0
  193. package/dist/db/migrations-pg/0008_slimy_toxin.sql +1 -0
  194. package/dist/db/migrations-pg/0009_fuzzy_jubilee.sql +4 -0
  195. package/dist/db/migrations-pg/0010_late_hammerhead.sql +1 -0
  196. package/dist/db/migrations-pg/0011_happy_leech.sql +16 -0
  197. package/dist/db/migrations-pg/0012_woozy_captain_midlands.sql +16 -0
  198. package/dist/db/migrations-pg/0013_yielding_nicolaos.sql +1 -0
  199. package/dist/db/migrations-pg/0014_wakeful_bill_hollister.sql +2 -0
  200. package/dist/db/migrations-pg/0015_aspiring_black_tom.sql +1 -0
  201. package/dist/db/migrations-pg/0016_cute_ghost_rider.sql +30 -0
  202. package/dist/db/migrations-pg/0017_far_changeling.sql +24 -0
  203. package/dist/db/migrations-pg/0018_fancy_miss_america.sql +1 -0
  204. package/dist/db/migrations-pg/0019_benchmark_contributions.sql +22 -0
  205. package/dist/db/migrations-pg/0020_majestic_edwin_jarvis.sql +3 -0
  206. package/dist/db/migrations-pg/0021_green_salo.sql +1 -0
  207. package/dist/db/migrations-pg/0022_wise_baron_strucker.sql +1 -0
  208. package/dist/db/migrations-pg/0023_search_index.sql +19 -0
  209. package/dist/db/migrations-pg/0024_author_indexes.sql +9 -0
  210. package/dist/db/migrations-pg/0025_auto_merge_requests.sql +26 -0
  211. package/dist/db/migrations-pg/0026_branch_status.sql +32 -0
  212. package/dist/db/migrations-pg/0027_pr_review_decision.sql +5 -0
  213. package/dist/db/migrations-pg/0028_branch_commit_detail.sql +9 -0
  214. package/dist/db/migrations-pg/0029_repo_reviewers.sql +127 -0
  215. package/dist/db/migrations-pg/0030_account_reviewers.sql +77 -0
  216. package/dist/db/migrations-pg/0031_workspaces.sql +131 -0
  217. package/dist/db/migrations-pg/0032_workspace_reviewers.sql +165 -0
  218. package/dist/db/migrations-pg/0033_drop_inbox_watch.sql +14 -0
  219. package/dist/db/migrations-pg/0034_ml_comment_labels.sql +33 -0
  220. package/dist/db/migrations-pg/0035_ml_vendor_severity.sql +16 -0
  221. package/dist/db/migrations-pg/0036_seat_pricing_repo_description.sql +12 -0
  222. package/dist/db/migrations-pg/0037_users_app_slug.sql +9 -0
  223. package/dist/db/migrations-pg/0038_auto_merge_queue.sql +10 -0
  224. package/dist/db/migrations-pg/0039_trunk_ci_status_events.sql +27 -0
  225. package/dist/db/migrations-pg/0040_automation_roles.sql +63 -0
  226. package/dist/db/migrations-pg/0041_automation_vendor_kinds.sql +488 -0
  227. package/dist/db/migrations-pg/0042_auto_merge_phase.sql +8 -0
  228. package/dist/db/migrations-pg/0043_pr_mentions.sql +19 -0
  229. package/dist/db/migrations-pg/0044_large_pr_threshold.sql +6 -0
  230. package/dist/db/migrations-pg/0045_pending_mute.sql +26 -0
  231. package/dist/db/migrations-pg/0046_merge_queue_state.sql +18 -0
  232. package/dist/db/migrations-pg/0047_drop_my_turn_dismissals.sql +21 -0
  233. package/dist/db/migrations-pg/0048_auto_merge_durable_anchors.sql +27 -0
  234. package/dist/db/migrations-pg/0049_blast_radius_config.sql +8 -0
  235. package/dist/db/migrations-pg/0050_repo_file_coupling.sql +13 -0
  236. package/dist/db/migrations-pg/0051_pr_content_kind.sql +6 -0
  237. package/dist/db/migrations-pg/0052_workspace_flow_settings.sql +4 -0
  238. package/dist/db/migrations-pg/0053_review_request_events.sql +18 -0
  239. package/dist/db/migrations-pg/0054_pr_security_signals.sql +59 -0
  240. package/dist/db/migrations-pg/0055_my_turn_settings.sql +6 -0
  241. package/dist/db/migrations-pg/0056_my_turn_dismissals.sql +21 -0
  242. package/dist/db/migrations-pg/0057_claude_review_follow_up_ticket.sql +8 -0
  243. package/dist/db/migrations-pg/0058_claude_review_trigger.sql +4 -0
  244. package/dist/db/migrations-pg/0059_commit_message_headline.sql +3 -0
  245. package/dist/db/migrations-pg/0060_claude_review_chat.sql +24 -0
  246. package/dist/db/migrations-pg/0061_adopt_agentic_tables.sql +79 -0
  247. package/dist/db/migrations-pg/0062_review_lens_drop_learnings.sql +5 -0
  248. package/dist/db/migrations-pg/0063_claude_review_threads.sql +7 -0
  249. package/dist/db/migrations-pg/0064_claude_review_ci_failures.sql +4 -0
  250. package/dist/db/migrations-pg/0065_ai_fix_change_report.sql +9 -0
  251. package/dist/db/migrations-pg/0066_claude_finding_story.sql +7 -0
  252. package/dist/db/migrations-pg/meta/0000_snapshot.json +2137 -0
  253. package/dist/db/migrations-pg/meta/0001_snapshot.json +2143 -0
  254. package/dist/db/migrations-pg/meta/0002_snapshot.json +2170 -0
  255. package/dist/db/migrations-pg/meta/0003_snapshot.json +2182 -0
  256. package/dist/db/migrations-pg/meta/0004_snapshot.json +2188 -0
  257. package/dist/db/migrations-pg/meta/0005_snapshot.json +2201 -0
  258. package/dist/db/migrations-pg/meta/0006_snapshot.json +2207 -0
  259. package/dist/db/migrations-pg/meta/0007_snapshot.json +2219 -0
  260. package/dist/db/migrations-pg/meta/0008_snapshot.json +2226 -0
  261. package/dist/db/migrations-pg/meta/0009_snapshot.json +2250 -0
  262. package/dist/db/migrations-pg/meta/0010_snapshot.json +2256 -0
  263. package/dist/db/migrations-pg/meta/0011_snapshot.json +2412 -0
  264. package/dist/db/migrations-pg/meta/0012_snapshot.json +2528 -0
  265. package/dist/db/migrations-pg/meta/0013_snapshot.json +2534 -0
  266. package/dist/db/migrations-pg/meta/0014_snapshot.json +2547 -0
  267. package/dist/db/migrations-pg/meta/0015_snapshot.json +2553 -0
  268. package/dist/db/migrations-pg/meta/0016_snapshot.json +2774 -0
  269. package/dist/db/migrations-pg/meta/0017_snapshot.json +2999 -0
  270. package/dist/db/migrations-pg/meta/0018_snapshot.json +3020 -0
  271. package/dist/db/migrations-pg/meta/0020_snapshot.json +3228 -0
  272. package/dist/db/migrations-pg/meta/0021_snapshot.json +3234 -0
  273. package/dist/db/migrations-pg/meta/0022_snapshot.json +3240 -0
  274. package/dist/db/migrations-pg/meta/_journal.json +475 -0
  275. package/dist/db/ml-labels.js +1666 -0
  276. package/dist/db/my-turn-dismissals.js +343 -0
  277. package/dist/db/my-turn-settings.js +34 -0
  278. package/dist/db/pending-classify.js +46 -0
  279. package/dist/db/pending-mute.js +171 -0
  280. package/dist/db/pending-tabs.js +238 -0
  281. package/dist/db/period-metrics.js +820 -0
  282. package/dist/db/person-period.js +763 -0
  283. package/dist/db/pr-intervals.js +930 -0
  284. package/dist/db/pr-liveness.js +240 -0
  285. package/dist/db/pr-mentions.js +279 -0
  286. package/dist/db/pr-merge-queue-stamp.js +91 -0
  287. package/dist/db/queries.js +14631 -0
  288. package/dist/db/reaction-targets.js +94 -0
  289. package/dist/db/repo-activity.js +171 -0
  290. package/dist/db/retention.js +138 -0
  291. package/dist/db/review-threads-for-review.js +240 -0
  292. package/dist/db/run-migrations.js +24 -0
  293. package/dist/db/schema.pg.js +1220 -0
  294. package/dist/db/schema.sqlite.js +1801 -0
  295. package/dist/db/search.js +317 -0
  296. package/dist/db/security-alerts.js +218 -0
  297. package/dist/db/synthesis-input.js +565 -0
  298. package/dist/db/triage.js +320 -0
  299. package/dist/db/usage.js +63 -0
  300. package/dist/db/work-plan.js +1086 -0
  301. package/dist/db/working-hours.js +161 -0
  302. package/dist/feed/my-turn.js +122 -0
  303. package/dist/github/actions-logs.js +397 -0
  304. package/dist/github/auth.js +86 -0
  305. package/dist/github/branch-queries.js +229 -0
  306. package/dist/github/client.js +454 -0
  307. package/dist/github/codeowners.js +221 -0
  308. package/dist/github/commit-checks.js +105 -0
  309. package/dist/github/compare.js +110 -0
  310. package/dist/github/diff-anchor.js +227 -0
  311. package/dist/github/mutations.js +706 -0
  312. package/dist/github/pr-file-content.js +254 -0
  313. package/dist/github/pr-liveness.js +161 -0
  314. package/dist/github/queries.js +875 -0
  315. package/dist/github/rate-budget.js +129 -0
  316. package/dist/github/reactions.js +161 -0
  317. package/dist/github/reviewer-suggest.js +104 -0
  318. package/dist/github/team-reviewers.js +96 -0
  319. package/dist/index.js +184 -0
  320. package/dist/merge/auto-merge-runner.js +960 -0
  321. package/dist/ml/severity-client.js +218 -0
  322. package/dist/pr/detail-enricher.js +26 -0
  323. package/dist/pro/bind.js +302 -0
  324. package/dist/pro/contract.js +37 -0
  325. package/dist/pro/migrate.js +64 -0
  326. package/dist/review/agent-context.js +127 -0
  327. package/dist/review/agent.js +385 -0
  328. package/dist/review/agentic.js +59 -0
  329. package/dist/review/auth.js +94 -0
  330. package/dist/review/chat-agent.js +179 -0
  331. package/dist/review/claude-review/ai-ready.js +16 -0
  332. package/dist/review/claude-review/auto-settings.js +139 -0
  333. package/dist/review/claude-review/auto.js +244 -0
  334. package/dist/review/claude-review/chat.js +489 -0
  335. package/dist/review/claude-review/ci-failures.js +350 -0
  336. package/dist/review/claude-review/follow-up.js +310 -0
  337. package/dist/review/claude-review/manager.js +686 -0
  338. package/dist/review/claude-review/persist.js +996 -0
  339. package/dist/review/claude-review/prompts.js +357 -0
  340. package/dist/review/claude-review/routes.js +518 -0
  341. package/dist/review/claude-review/routing.js +61 -0
  342. package/dist/review/claude-review/specialists.js +190 -0
  343. package/dist/review/claude-review/threads.js +265 -0
  344. package/dist/review/claude-review/ticket.js +282 -0
  345. package/dist/review/clone-hygiene.js +380 -0
  346. package/dist/review/clone-manager.js +367 -0
  347. package/dist/review/llm.js +113 -0
  348. package/dist/review/model-options.js +48 -0
  349. package/dist/review/plugin-providers.js +12 -0
  350. package/dist/review/post-review.js +216 -0
  351. package/dist/review/post-seam.js +161 -0
  352. package/dist/review/prepare.js +168 -0
  353. package/dist/review/pricing.js +17 -0
  354. package/dist/review/schema.js +156 -0
  355. package/dist/review/submit-map.js +41 -0
  356. package/dist/review/usage.js +90 -0
  357. package/dist/shared/claude-review.js +335 -0
  358. package/dist/shared/conflict-fold.js +151 -0
  359. package/dist/shared/conflicts.js +30 -0
  360. package/dist/shared/flow-settings.js +191 -0
  361. package/dist/shared/index.js +8 -0
  362. package/dist/shared/my-turn-settings.js +238 -0
  363. package/dist/shared/pending-rules.js +281 -0
  364. package/dist/shared/product.js +54 -0
  365. package/dist/shared/types.js +896 -0
  366. package/dist/status.js +386 -0
  367. package/dist/sync/adaptive.js +185 -0
  368. package/dist/sync/app-attribution.js +66 -0
  369. package/dist/sync/auth-notices.js +36 -0
  370. package/dist/sync/backfill-ci-history.js +315 -0
  371. package/dist/sync/backfill-commit-headlines.js +136 -0
  372. package/dist/sync/backfill-pr-security.js +175 -0
  373. package/dist/sync/backfill-review-requests.js +97 -0
  374. package/dist/sync/benchmark-rollup.js +50 -0
  375. package/dist/sync/bot-detection.js +309 -0
  376. package/dist/sync/bot-resolution-markers.js +30 -0
  377. package/dist/sync/branch-status.js +634 -0
  378. package/dist/sync/classify-change-shape.js +150 -0
  379. package/dist/sync/commit-files.js +74 -0
  380. package/dist/sync/derive-thread-state.js +99 -0
  381. package/dist/sync/drain-review-threads.js +212 -0
  382. package/dist/sync/hydrate-detail.js +482 -0
  383. package/dist/sync/mention-scan.js +89 -0
  384. package/dist/sync/ml-enrichment.js +478 -0
  385. package/dist/sync/pr-change-signal.js +96 -0
  386. package/dist/sync/pr-liveness-sweep.js +139 -0
  387. package/dist/sync/pr-settle.js +381 -0
  388. package/dist/sync/refresh-pr.js +163 -0
  389. package/dist/sync/reparse-vendor-badges.js +495 -0
  390. package/dist/sync/resync-after-write.js +280 -0
  391. package/dist/sync/review-fingerprint.js +117 -0
  392. package/dist/sync/reviewer-behavior.js +103 -0
  393. package/dist/sync/reviewer-classify.js +503 -0
  394. package/dist/sync/routing-files.js +97 -0
  395. package/dist/sync/scheduled-jobs.js +12 -0
  396. package/dist/sync/scheduler.js +159 -0
  397. package/dist/sync/security-detect.js +521 -0
  398. package/dist/sync/sync-manager.js +750 -0
  399. package/dist/sync/sync-one-pr.js +205 -0
  400. package/dist/sync/sync-repo.js +400 -0
  401. package/dist/sync/unsettled-prs.js +506 -0
  402. package/dist/sync/upsert.js +1190 -0
  403. package/package.json +56 -0
  404. package/public/apple-touch-icon.png +0 -0
  405. package/public/assets/AiFixTab-CQP6PT5u.js +2 -0
  406. package/public/assets/ClaudeReviewTab-DQJ-58ZA.js +8 -0
  407. package/public/assets/PrBotBehaviourTab-CCnFrWbC.js +1 -0
  408. package/public/assets/archivo-latin-600-BN-JkNrl.woff2 +0 -0
  409. package/public/assets/highlight-BEHUn5zE.css +10 -0
  410. package/public/assets/highlight-CIIZLa6Z.js +12 -0
  411. package/public/assets/index-BDnYs6zg.js +73 -0
  412. package/public/assets/index-mCuI--RC.css +1 -0
  413. package/public/assets/markdown-I_JLLVAZ.js +32 -0
  414. package/public/assets/perfProbe-Da13EhTE.js +1 -0
  415. package/public/assets/tanstack-5qsxxaLe.js +17 -0
  416. package/public/assets/vis-C3BCkP5U.js +1280 -0
  417. package/public/assets/vis-ziCVehMy.css +1 -0
  418. package/public/favicon-16.png +0 -0
  419. package/public/favicon-32.png +0 -0
  420. package/public/favicon-48.png +0 -0
  421. package/public/favicon.svg +5 -0
  422. package/public/index.html +41 -0
  423. package/public-landing/apple-touch-icon.png +0 -0
  424. package/public-landing/assets/archivo-latin-500-BWmvx2Mg.woff2 +0 -0
  425. package/public-landing/assets/archivo-latin-600-BN-JkNrl.woff2 +0 -0
  426. package/public-landing/assets/index-CA3eEGXO.js +40 -0
  427. package/public-landing/assets/index-naQrQ6Fe.css +1 -0
  428. package/public-landing/assets/jetbrains-mono-latin-400-RruCX7RW.woff2 +0 -0
  429. package/public-landing/assets/newsreader-latin-400-DExrRRrN.woff2 +0 -0
  430. package/public-landing/assets/newsreader-latin-400-italic-b0I-AwbV.woff2 +0 -0
  431. package/public-landing/bots/index.html +156 -0
  432. package/public-landing/contact/index.html +156 -0
  433. package/public-landing/cookies/index.html +156 -0
  434. package/public-landing/demo/limn-walkthrough-poster.jpg +0 -0
  435. package/public-landing/demo/limn-walkthrough.cues.json +44 -0
  436. package/public-landing/demo/limn-walkthrough.mp4 +0 -0
  437. package/public-landing/favicon-16.png +0 -0
  438. package/public-landing/favicon-32.png +0 -0
  439. package/public-landing/favicon-48.png +0 -0
  440. package/public-landing/favicon.svg +5 -0
  441. package/public-landing/features/index.html +156 -0
  442. package/public-landing/for-developers/index.html +156 -0
  443. package/public-landing/for-managers/index.html +156 -0
  444. package/public-landing/how-it-works/index.html +156 -0
  445. package/public-landing/how-we-measure/index.html +156 -0
  446. package/public-landing/icon-192.png +0 -0
  447. package/public-landing/icon-512.png +0 -0
  448. package/public-landing/index.html +156 -0
  449. package/public-landing/insights/index.html +156 -0
  450. package/public-landing/og-image.png +0 -0
  451. package/public-landing/pricing/index.html +156 -0
  452. package/public-landing/privacy/index.html +156 -0
  453. package/public-landing/pro/index.html +156 -0
  454. package/public-landing/reviews/index.html +156 -0
  455. package/public-landing/robots.txt +8 -0
  456. package/public-landing/shots/benchmark.png +0 -0
  457. package/public-landing/shots/bot-roi.png +0 -0
  458. package/public-landing/shots/bot-settings.png +0 -0
  459. package/public-landing/shots/chronology.png +0 -0
  460. package/public-landing/shots/feed.png +0 -0
  461. package/public-landing/shots/flow-metrics.png +0 -0
  462. package/public-landing/shots/free-reports.png +0 -0
  463. package/public-landing/shots/pending-board.png +0 -0
  464. package/public-landing/shots/pending-card.png +0 -0
  465. package/public-landing/shots/period-report.png +0 -0
  466. package/public-landing/shots/pr-detail.png +0 -0
  467. package/public-landing/shots/pr-threads.png +0 -0
  468. package/public-landing/shots/reach.png +0 -0
  469. package/public-landing/shots/repo-rows.png +0 -0
  470. package/public-landing/shots/severity-findings.png +0 -0
  471. package/public-landing/shots/severity-strip.png +0 -0
  472. package/public-landing/site.webmanifest +14 -0
  473. package/public-landing/sitemap.xml +51 -0
  474. package/public-landing/terms/index.html +156 -0
@@ -0,0 +1,262 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { existsSync } from 'node:fs';
3
+ import { isAbsolute, join } from 'node:path';
4
+ import { promisify } from 'node:util';
5
+ import { config } from '../config.js';
6
+ import { getAccessToken, getAccountById } from '../auth/account.js';
7
+ import { cleanupCloneCache, prepWorktree, removeWorktreeLocked, } from '../review/clone-manager.js';
8
+ import { fetchPrHeadInfo } from '../github/mutations.js';
9
+ import { codedError, pushForceWithLease, pushRef } from './git.js';
10
+ import { protectedRefsFor } from './git-ops.js';
11
+ const execFileAsync = promisify(execFile);
12
+ // CORE (free tier): "Update branch from trunk" — rebase or merge the trunk into a PR's own
13
+ // head branch and push — plus `hasConflictMarkers`, which the in-app conflict resolver
14
+ // (src/conflict/) imports. Same discipline as git.ts / clone-manager.ts: args are ALWAYS arrays
15
+ // (no shell), a tokenized URL is passed per-op and never persisted, and there is no agent here
16
+ // at all. ANY conflict aborts the rebase/merge and throws CONFLICTS_UNRESOLVED — nothing is
17
+ // ever resolved on this path, so a tree with conflicts is never pushed.
18
+ //
19
+ // (This file used to also hold AI Fix's trunk reconciliation — merge preview, rebase-resolve,
20
+ // merge-resolve-and-push, push-resolved, and the agentic conflict resolver they called. All of
21
+ // it was removed: an AI Fix now pushes as-is through git-ops.ts `applyAndPush`.)
22
+ // Non-interactive git env: no credential prompt, no editor, no merge-message editor.
23
+ const GIT_ENV = {
24
+ ...process.env,
25
+ GIT_TERMINAL_PROMPT: '0',
26
+ GIT_EDITOR: 'true',
27
+ GIT_SEQUENCE_EDITOR: 'true',
28
+ GIT_MERGE_AUTOEDIT: 'no',
29
+ };
30
+ /** Run git, throwing on a non-zero exit (for ops that MUST succeed). */
31
+ async function git(args, cwd) {
32
+ const { stdout, stderr } = await execFileAsync('git', args, {
33
+ cwd,
34
+ env: GIT_ENV,
35
+ timeout: 120_000,
36
+ maxBuffer: 128 * 1024 * 1024,
37
+ });
38
+ return { ok: true, code: 0, stdout, stderr };
39
+ }
40
+ /** Run git WITHOUT throwing; returns the exit code + output (for merge/rebase). */
41
+ async function gitTry(args, cwd) {
42
+ try {
43
+ const { stdout, stderr } = await execFileAsync('git', args, {
44
+ cwd,
45
+ env: GIT_ENV,
46
+ timeout: 120_000,
47
+ maxBuffer: 128 * 1024 * 1024,
48
+ });
49
+ return { ok: true, code: 0, stdout, stderr };
50
+ }
51
+ catch (err) {
52
+ const e = err;
53
+ return {
54
+ ok: false,
55
+ code: typeof e.code === 'number' ? e.code : 1,
56
+ stdout: e.stdout ?? '',
57
+ stderr: e.stderr ?? (err instanceof Error ? err.message : String(err)),
58
+ };
59
+ }
60
+ }
61
+ function tokenizedUrl(owner, name, token) {
62
+ return `https://x-access-token:${token}@github.com/${owner}/${name}.git`;
63
+ }
64
+ function lines(s) {
65
+ return s
66
+ .split('\n')
67
+ .map((l) => l.trim())
68
+ .filter(Boolean);
69
+ }
70
+ async function identFor(accountId) {
71
+ const account = await getAccountById(accountId);
72
+ const name = account?.displayName || account?.githubLogin || 'pierre-review';
73
+ const email = account?.githubLogin
74
+ ? `${account.githubLogin}@users.noreply.github.com`
75
+ : 'pierre-review@users.noreply.github.com';
76
+ return { name, email };
77
+ }
78
+ function identArgs(ident) {
79
+ return ['-c', `user.name=${ident.name}`, '-c', `user.email=${ident.email}`];
80
+ }
81
+ async function scheduleCleanup(repoCloneDir) {
82
+ if (!repoCloneDir)
83
+ return;
84
+ setImmediate(() => {
85
+ try {
86
+ cleanupCloneCache();
87
+ }
88
+ catch {
89
+ /* advisory */
90
+ }
91
+ });
92
+ }
93
+ async function teardown(owner, name, repoCloneDir, worktreePath) {
94
+ if (repoCloneDir && worktreePath) {
95
+ await removeWorktreeLocked(owner, name, repoCloneDir, worktreePath).catch(() => { });
96
+ }
97
+ void scheduleCleanup(repoCloneDir);
98
+ }
99
+ /** Fetch a branch into the worktree's object store and return its tip sha. */
100
+ async function fetchTrunk(worktree, owner, name, token, trunk) {
101
+ const res = await gitTry(['fetch', '--no-tags', '--force', tokenizedUrl(owner, name, token), trunk], worktree);
102
+ if (!res.ok) {
103
+ throw codedError('TRUNK_FETCH_FAILED', `couldn't fetch trunk '${trunk}': ${res.stderr || res.stdout}`);
104
+ }
105
+ const { stdout } = await git(['rev-parse', 'FETCH_HEAD'], worktree);
106
+ return stdout.trim();
107
+ }
108
+ /** True if `ancestor` is an ancestor of `descendant` (i.e. already contained). */
109
+ async function isAncestor(worktree, ancestor, descendant) {
110
+ const res = await gitTry(['merge-base', '--is-ancestor', ancestor, descendant], worktree);
111
+ return res.ok;
112
+ }
113
+ /** The currently-unmerged (conflicted) paths. */
114
+ async function conflictedFiles(worktree) {
115
+ const { stdout } = await git(['diff', '--name-only', '--diff-filter=U'], worktree);
116
+ return lines(stdout);
117
+ }
118
+ // A leftover conflict marker: `<<<<<<< `, `>>>>>>> ` or diff3's `||||||| ` (the
119
+ // `=======` divider alone is ambiguous — real files contain it — so we rely on the
120
+ // unambiguous open/close markers plus git's own unmerged-index check).
121
+ const MARKER_RE = /^(<{7}|>{7}|\|{7})[ \t]/m;
122
+ /** True if `text` still contains an (unambiguous) unresolved conflict marker. */
123
+ export function hasConflictMarkers(text) {
124
+ return MARKER_RE.test(text);
125
+ }
126
+ /** True if a rebase or merge is currently in progress in this worktree. */
127
+ async function opInProgress(worktree, kind) {
128
+ const probes = kind === 'rebase' ? ['rebase-merge', 'rebase-apply'] : ['MERGE_HEAD'];
129
+ for (const p of probes) {
130
+ try {
131
+ const { stdout } = await git(['rev-parse', '--git-path', p], worktree);
132
+ const rel = stdout.trim();
133
+ const abs = isAbsolute(rel) ? rel : join(worktree, rel);
134
+ if (existsSync(abs))
135
+ return true;
136
+ }
137
+ catch {
138
+ /* ignore */
139
+ }
140
+ }
141
+ return false;
142
+ }
143
+ // ---- rebase the checked-out branch onto the trunk (aborts on the first conflict) ----
144
+ async function runRebase(worktree, trunkSha, ident) {
145
+ const gc = identArgs(ident);
146
+ let res = await gitTry([...gc, 'rebase', trunkSha], worktree);
147
+ let step = 0;
148
+ while (!res.ok) {
149
+ if (!(await opInProgress(worktree, 'rebase'))) {
150
+ // The rebase never started / hard-failed (not a conflict stop).
151
+ throw codedError('REBASE_FAILED', res.stderr || res.stdout || 'rebase failed');
152
+ }
153
+ const files = await conflictedFiles(worktree);
154
+ if (files.length > 0) {
155
+ await gitTry(['rebase', '--abort'], worktree);
156
+ throw codedError('CONFLICTS_UNRESOLVED', `rebase conflicts in ${files.join(', ')}`);
157
+ }
158
+ // A stop with no conflicted file (e.g. a commit that became empty): continue or skip it,
159
+ // capped so a pathological history can't spin.
160
+ if (++step > config.aiFixRebaseMaxSteps) {
161
+ await gitTry(['rebase', '--abort'], worktree);
162
+ throw codedError('REBASE_FAILED', `rebase exceeded ${config.aiFixRebaseMaxSteps} conflict steps`);
163
+ }
164
+ res = await continueOrSkip(worktree, gc);
165
+ }
166
+ }
167
+ // `git rebase --continue`, falling back to `--skip` when a commit became empty (its
168
+ // changes are already on the trunk).
169
+ async function continueOrSkip(worktree, gc) {
170
+ const cont = await gitTry([...gc, 'rebase', '--continue'], worktree);
171
+ if (cont.ok)
172
+ return cont;
173
+ const blob = `${cont.stderr}\n${cont.stdout}`.toLowerCase();
174
+ if (blob.includes('no changes') ||
175
+ blob.includes('nothing to commit') ||
176
+ blob.includes('did you forget') ||
177
+ blob.includes('patch is empty')) {
178
+ return gitTry([...gc, 'rebase', '--skip'], worktree);
179
+ }
180
+ return cont;
181
+ }
182
+ // ---- merge the trunk into the checked-out branch (aborts on any conflict) ----
183
+ async function runMerge(worktree, trunkSha, trunk, branchLabel, ident) {
184
+ const gc = identArgs(ident);
185
+ if (await isAncestor(worktree, trunkSha, 'HEAD')) {
186
+ return; // already contains the trunk
187
+ }
188
+ const res = await gitTry([...gc, 'merge', '--no-ff', '--no-edit', '-m', `Merge ${trunk} into ${branchLabel}`, trunkSha], worktree);
189
+ if (res.ok)
190
+ return;
191
+ const files = await conflictedFiles(worktree);
192
+ if (files.length === 0) {
193
+ await gitTry(['merge', '--abort'], worktree);
194
+ throw codedError('MERGE_FAILED', res.stderr || res.stdout || 'merge failed');
195
+ }
196
+ await gitTry(['merge', '--abort'], worktree);
197
+ throw codedError('CONFLICTS_UNRESOLVED', `merge conflicts in ${files.join(', ')}`);
198
+ }
199
+ // ---- CORE (free tier): update a PR's OWN branch from its base/trunk ----
200
+ // Rebase (default) or merge the trunk into the PR's head branch and push. This is the local,
201
+ // clone-based path for the free-tier "Update branch from trunk": on ANY conflict runRebase /
202
+ // runMerge abort the op and throw CONFLICTS_UNRESOLVED (nothing here resolves a conflict — the
203
+ // in-app resolver in src/conflict/ is a separate, reader-driven flow). No stored patch is
204
+ // involved: we check the PR head out as-is and reconcile it.
205
+ export async function updatePrBranchFromTrunk(args) {
206
+ const { accountId, owner, name, prNumber, headRef, headSha, trunk, strategy } = args;
207
+ const token = await getAccessToken(accountId);
208
+ const ident = await identFor(accountId);
209
+ // The head must not have moved out from under us, and a fork head must be pushable.
210
+ const info = await fetchPrHeadInfo(token, owner, name, prNumber);
211
+ if (info.headSha !== headSha) {
212
+ throw codedError('HEAD_MOVED', `the PR head advanced (now ${info.headSha.slice(0, 7)}, expected ${headSha.slice(0, 7)})`);
213
+ }
214
+ if (info.isFork && !info.maintainerCanModify) {
215
+ throw codedError('PUSH_DENIED', 'the PR head is a fork this account cannot push to — update it on GitHub instead');
216
+ }
217
+ // The PR head branch lives in the HEAD repo, which for a fork PR is NOT the base (watched)
218
+ // repo — push there, or a merge would create a stray branch on the base and a rebase's lease
219
+ // would target the wrong ref. The clone/fetch still uses the base repo below (pull/N/head
220
+ // resolves there); only the PUSH target is the head repo. full_name is always `owner/name`.
221
+ const slash = info.headRepoFullName.indexOf('/');
222
+ const headOwner = slash > 0 ? info.headRepoFullName.slice(0, slash) : owner;
223
+ const headName = slash > 0 ? info.headRepoFullName.slice(slash + 1) : name;
224
+ // The push lands in the HEAD repo, which for a fork PR is not the watched one — then there
225
+ // is nothing of ours to protect there (see protectedRefsFor).
226
+ const push = {
227
+ worktree: '',
228
+ owner: headOwner,
229
+ name: headName,
230
+ token,
231
+ committish: 'HEAD',
232
+ remoteBranch: headRef,
233
+ protect: await protectedRefsFor(accountId, owner, name, prNumber, headOwner, headName),
234
+ };
235
+ let repoCloneDir = null;
236
+ let worktreePath = null;
237
+ try {
238
+ // Check out the PR head branch (prepWorktree checks out at the given sha).
239
+ ({ repoCloneDir, worktreePath } = await prepWorktree(owner, name, prNumber, headSha, token));
240
+ const trunkSha = await fetchTrunk(worktreePath, owner, name, token, trunk);
241
+ if (strategy === 'rebase') {
242
+ await runRebase(worktreePath, trunkSha, ident); // throws CONFLICTS_UNRESOLVED on conflict
243
+ const newSha = (await git(['rev-parse', 'HEAD'], worktreePath)).stdout.trim();
244
+ // Rewriting history requires a force push; the lease pins to the sha we cloned so a
245
+ // concurrent push aborts it (never blows away someone else's work).
246
+ await pushForceWithLease({ ...push, worktree: worktreePath, leaseSha: headSha });
247
+ return { headSha: newSha, strategy };
248
+ }
249
+ await runMerge(worktreePath, trunkSha, trunk, headRef, ident); // throws on conflict
250
+ const newSha = (await git(['rev-parse', 'HEAD'], worktreePath)).stdout.trim();
251
+ // A merge only adds a commit (the old head is its ancestor) → a plain push. Already
252
+ // up-to-date (runMerge no-op) leaves HEAD unchanged → nothing to push.
253
+ if (newSha !== headSha) {
254
+ await pushRef({ ...push, worktree: worktreePath });
255
+ }
256
+ return { headSha: newSha, strategy };
257
+ }
258
+ finally {
259
+ await teardown(owner, name, repoCloneDir, worktreePath);
260
+ }
261
+ }
262
+ //# sourceMappingURL=merge.js.map
@@ -0,0 +1,75 @@
1
+ import { lstatSync, realpathSync } from 'node:fs';
2
+ import { join, sep } from 'node:path';
3
+ import { codedError } from './git.js';
4
+ // Where a write is allowed to land inside a checked-out worktree.
5
+ //
6
+ // File paths reach the coding seams from adapter plans whose locations can be influenced by
7
+ // REPO CONTENT (a T3 manifest proposes a configPath), i.e. attacker-suppliable in cloud. Two
8
+ // guards, and NEITHER is sufficient alone:
9
+ // - assertSafeTargetPath is LEXICAL and runs before any side effect;
10
+ // - resolveContainedTargetPath is FILESYSTEM and runs after checkout, immediately before
11
+ // the write, because a committed symlink is a real directory entry and no amount of
12
+ // string inspection can see it.
13
+ /**
14
+ * Lexical: repo-relative, no traversal, no drive letter, no `.git` segment at ANY depth,
15
+ * case-folded. Throws a coded 'APPLY_FAILED'.
16
+ * ⚠ `.git` is checked per SEGMENT and case-INSENSITIVELY: the predecessor anchored it at the
17
+ * root (`norm === '.git' || norm.startsWith('.git/')`), so `a/.git/hooks/pre-commit` — a hook
18
+ * git runs on the next commit — sailed through, and `.GIT/config` did too on macOS.
19
+ */
20
+ export function assertSafeTargetPath(path) {
21
+ const norm = path.replace(/\\/g, '/');
22
+ const segments = norm.split('/');
23
+ if (!norm ||
24
+ norm.startsWith('/') ||
25
+ /^[A-Za-z]:/.test(norm) ||
26
+ segments.some((s) => s === '' || s === '.' || s === '..' || s.toLowerCase() === '.git')) {
27
+ throw codedError('APPLY_FAILED', `invalid target path: ${path}`);
28
+ }
29
+ }
30
+ /**
31
+ * Containment: resolve every EXISTING component of `<root>/<path>` and assert the result
32
+ * stays inside `<root>`. Returns the absolute path to write to.
33
+ *
34
+ * ⚠ A COMMITTED SYMLINK IS A REAL DIRECTORY ENTRY, so `link/evil.txt` is traversal-free text
35
+ * that writes wherever `link` points — outside the worktree, with no `..` anywhere in it. An
36
+ * in-tree symlink is REFUSED outright rather than followed: git records the LINK, not the
37
+ * target, so a repo can ship one and nothing about writing through it is ever intended.
38
+ * ⚠ realpath the ROOT too — /tmp is a symlink to /private/tmp on macOS, and comparing an
39
+ * unresolved root against a resolved child refuses every legitimate write.
40
+ *
41
+ * Call AFTER checkout, IMMEDIATELY before the mkdir/write.
42
+ */
43
+ export function resolveContainedTargetPath(root, path) {
44
+ assertSafeTargetPath(path);
45
+ let realRoot;
46
+ try {
47
+ realRoot = realpathSync(root);
48
+ }
49
+ catch {
50
+ throw codedError('APPLY_FAILED', `worktree root is not readable: ${root}`);
51
+ }
52
+ let current = realRoot;
53
+ for (const segment of path.replace(/\\/g, '/').split('/')) {
54
+ const next = join(current, segment);
55
+ let entry;
56
+ try {
57
+ entry = lstatSync(next);
58
+ }
59
+ catch {
60
+ // Nothing there yet — this segment and everything after it is ours to create, and a
61
+ // path that does not exist cannot redirect us anywhere.
62
+ current = next;
63
+ continue;
64
+ }
65
+ if (entry.isSymbolicLink()) {
66
+ throw codedError('APPLY_FAILED', `refusing to write through the symlink ${segment} in ${path}`);
67
+ }
68
+ current = next;
69
+ }
70
+ if (current !== realRoot && !current.startsWith(realRoot + sep)) {
71
+ throw codedError('APPLY_FAILED', `target path escapes the worktree: ${path}`);
72
+ }
73
+ return current;
74
+ }
75
+ //# sourceMappingURL=safe-path.js.map
@@ -0,0 +1,43 @@
1
+ import { loadZod } from "../ai/runtime.js";
2
+ // The structured-output contract for the in-process `submit_fix` MCP tool. The agent
3
+ // EDITS files in the worktree and calls this ONCE at the end to report what it did.
4
+ // We deliberately capture ONLY a prose summary + a commit message here — the actual
5
+ // changeset (patch + file list) is derived from `git` after the run, never from the
6
+ // agent's self-report (which miscounts / omits files). Exported as a raw zod shape
7
+ // (what `tool()` wants) plus an assembled object schema for validation.
8
+ export function buildSubmitFixShape(z) {
9
+ return {
10
+ // A concise, user-facing description of the fix that was applied.
11
+ summary: z.string(),
12
+ // A conventional-commit-style message for the commit the host will create.
13
+ commitMessage: z.string(),
14
+ // The per-change report: ONE entry per file the agent changed — what changed and why, and the
15
+ // refs of the task items (F3, T1, S1-AC2, C1, P2 …) that change addresses. Optional at the
16
+ // schema level so a run that changed nothing is not made to invent one; the prompt asks for it.
17
+ // As with `summary`, this is a SELF-REPORT stored as commentary: the authoritative changeset
18
+ // still comes from git, and the manager drops any ref the run was not shown.
19
+ changes: z
20
+ .array(z.object({
21
+ path: z.string(),
22
+ // 1–3 sentences: what changed and why.
23
+ summary: z.string(),
24
+ refs: z.array(z.string()).optional(),
25
+ }))
26
+ .optional(),
27
+ // Items the agent deliberately did NOT fix, each with the reason (wrong, out of scope, needs
28
+ // a person, already done …).
29
+ unaddressed: z
30
+ .array(z.object({ ref: z.string(), reason: z.string() }))
31
+ .optional(),
32
+ };
33
+ }
34
+ /** The raw shape `tool()` wants, built from the runtime's zod. */
35
+ export async function submitFixShape() {
36
+ return buildSubmitFixShape(await loadZod());
37
+ }
38
+ /** The assembled object schema, for validation. */
39
+ export async function submitFixSchema() {
40
+ const z = await loadZod();
41
+ return z.object(buildSubmitFixShape(z));
42
+ }
43
+ //# sourceMappingURL=schema.js.map