@openhands/extensions 0.1.0 → 0.2.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 (347) hide show
  1. package/.agents/skills/custom-codereview-guide.md +25 -0
  2. package/.github/pull_request_template.md +38 -0
  3. package/.github/release.yml +14 -0
  4. package/.github/workflows/check-extensions.yml +72 -0
  5. package/.github/workflows/npm-publish.yml +89 -0
  6. package/.github/workflows/pr.yml +30 -0
  7. package/.github/workflows/release.yml +24 -0
  8. package/.github/workflows/tests.yml +25 -0
  9. package/.github/workflows/vulnerability-scan.yml +87 -0
  10. package/.release-please-manifest.json +3 -0
  11. package/AGENTS.md +132 -0
  12. package/README.md +10 -0
  13. package/analysis_results.md +162 -0
  14. package/marketplaces/large-codebase.json +66 -0
  15. package/marketplaces/openhands-extensions.json +682 -0
  16. package/package.json +4 -10
  17. package/plugins/README.md +30 -0
  18. package/plugins/city-weather/.plugin/plugin.json +13 -0
  19. package/plugins/city-weather/README.md +145 -0
  20. package/plugins/city-weather/commands/now.md +56 -0
  21. package/plugins/cobol-modernization/.plugin/plugin.json +19 -0
  22. package/plugins/cobol-modernization/README.md +201 -0
  23. package/plugins/cobol-modernization/references/troubleshooting.md +18 -0
  24. package/plugins/cobol-modernization/skills/build-setup/SKILL.md +78 -0
  25. package/plugins/cobol-modernization/skills/build-setup/scripts/install-gnucobol.sh +32 -0
  26. package/plugins/cobol-modernization/skills/cobol-modernization-overview/SKILL.md +113 -0
  27. package/plugins/cobol-modernization/skills/mainfraime-removal/SKILL.md +62 -0
  28. package/plugins/cobol-modernization/skills/mainfraime-removal/references/cics-transformation-examples.md +45 -0
  29. package/plugins/cobol-modernization/skills/mainframe-planning/SKILL.md +78 -0
  30. package/plugins/cobol-modernization/skills/to-java-migration/SKILL.md +59 -0
  31. package/plugins/cobol-modernization/skills/to-java-migration/references/cobol-to-java-example.md +58 -0
  32. package/plugins/cobol-modernization/skills/to-java-migration/references/datatype-mappings.md +19 -0
  33. package/plugins/issue-duplicate-checker/.plugin/plugin.json +13 -0
  34. package/plugins/issue-duplicate-checker/README.md +51 -0
  35. package/plugins/issue-duplicate-checker/action.yml +349 -0
  36. package/plugins/issue-duplicate-checker/scripts/auto_close_duplicate_issues.py +569 -0
  37. package/plugins/issue-duplicate-checker/scripts/issue_duplicate_check_openhands.py +681 -0
  38. package/plugins/issue-duplicate-checker/scripts/post_duplicate_notice.js +220 -0
  39. package/plugins/issue-duplicate-checker/scripts/remove_duplicate_candidate_label.js +27 -0
  40. package/plugins/magic-test/.plugin/plugin.json +13 -0
  41. package/plugins/magic-test/skills/magic-word/SKILL.md +33 -0
  42. package/plugins/migration-scoring/.plugin/plugin.json +19 -0
  43. package/plugins/migration-scoring/README.md +244 -0
  44. package/plugins/migration-scoring/skills/migration-mapping/SKILL.md +72 -0
  45. package/plugins/migration-scoring/skills/migration-report/SKILL.md +118 -0
  46. package/plugins/migration-scoring/skills/migration-scoring-overview/SKILL.md +126 -0
  47. package/plugins/migration-scoring/skills/score-quality/SKILL.md +54 -0
  48. package/plugins/migration-scoring/skills/score-quality/references/scoring-criteria.md +30 -0
  49. package/plugins/migration-scoring/skills/score-style/SKILL.md +106 -0
  50. package/plugins/onboarding/.plugin/plugin.json +20 -0
  51. package/plugins/onboarding/README.md +30 -0
  52. package/plugins/onboarding/references/criteria.md +144 -0
  53. package/plugins/onboarding/skills/agent-readiness-report/README.md +23 -0
  54. package/plugins/onboarding/skills/agent-readiness-report/SKILL.md +122 -0
  55. package/plugins/onboarding/skills/agent-readiness-report/scripts/scan_agent_instructions.sh +88 -0
  56. package/plugins/onboarding/skills/agent-readiness-report/scripts/scan_build_env.sh +114 -0
  57. package/plugins/onboarding/skills/agent-readiness-report/scripts/scan_feedback_loops.sh +133 -0
  58. package/plugins/onboarding/skills/agent-readiness-report/scripts/scan_policy.sh +113 -0
  59. package/plugins/onboarding/skills/agent-readiness-report/scripts/scan_workflows.sh +127 -0
  60. package/plugins/onboarding/skills/improve-agent-readiness/README.md +19 -0
  61. package/plugins/onboarding/skills/improve-agent-readiness/SKILL.md +167 -0
  62. package/plugins/onboarding/skills/setup-agents-md/README.md +15 -0
  63. package/plugins/onboarding/skills/setup-agents-md/SKILL.md +150 -0
  64. package/plugins/onboarding/skills/setup-openhands/README.md +20 -0
  65. package/plugins/onboarding/skills/setup-openhands/SKILL.md +56 -0
  66. package/plugins/onboarding/skills/setup-pr-review/README.md +23 -0
  67. package/plugins/onboarding/skills/setup-pr-review/SKILL.md +72 -0
  68. package/plugins/openhands/.plugin/plugin.json +13 -0
  69. package/plugins/openhands/README.md +52 -0
  70. package/plugins/openhands/SKILL.md +61 -0
  71. package/plugins/openhands/commands/create.md +55 -0
  72. package/plugins/openhands/commands/openhands-cloud.md +8 -0
  73. package/plugins/openhands/scripts/run.sh +69 -0
  74. package/plugins/pr-review/.plugin/plugin.json +13 -0
  75. package/plugins/pr-review/README.md +393 -0
  76. package/plugins/pr-review/action.yml +298 -0
  77. package/plugins/pr-review/scripts/agent_script.py +1282 -0
  78. package/plugins/pr-review/scripts/evaluate_review.py +655 -0
  79. package/plugins/pr-review/scripts/prompt.py +260 -0
  80. package/plugins/pr-review/workflows/pr-review-by-openhands.yml +51 -0
  81. package/plugins/pr-review/workflows/pr-review-evaluation.yml +85 -0
  82. package/plugins/qa-changes/.plugin/plugin.json +11 -0
  83. package/plugins/qa-changes/README.md +185 -0
  84. package/plugins/qa-changes/action.yml +181 -0
  85. package/plugins/qa-changes/scripts/agent_script.py +406 -0
  86. package/plugins/qa-changes/scripts/evaluate_qa_changes.py +385 -0
  87. package/plugins/qa-changes/scripts/prompt.py +174 -0
  88. package/plugins/qa-changes/workflows/qa-changes-by-openhands.yml +50 -0
  89. package/plugins/qa-changes/workflows/qa-changes-evaluation.yml +85 -0
  90. package/plugins/release-notes/.plugin/plugin.json +19 -0
  91. package/plugins/release-notes/README.md +283 -0
  92. package/plugins/release-notes/SKILL.md +83 -0
  93. package/plugins/release-notes/action.yml +117 -0
  94. package/plugins/release-notes/commands/release-notes.md +8 -0
  95. package/plugins/release-notes/scripts/agent_script.py +292 -0
  96. package/plugins/release-notes/scripts/generate_release_notes.py +733 -0
  97. package/plugins/release-notes/scripts/prompt.py +90 -0
  98. package/plugins/release-notes/scripts/validate_release_notes.py +328 -0
  99. package/plugins/release-notes/workflows/release-notes.yml +76 -0
  100. package/plugins/vulnerability-remediation/.plugin/plugin.json +19 -0
  101. package/plugins/vulnerability-remediation/README.md +217 -0
  102. package/plugins/vulnerability-remediation/action.yml +187 -0
  103. package/plugins/vulnerability-remediation/scripts/scan_and_remediate.py +561 -0
  104. package/plugins/vulnerability-remediation/workflows/vulnerability-scan.yml +87 -0
  105. package/pyproject.toml +12 -0
  106. package/release-please-config.json +16 -0
  107. package/scripts/sync_extensions.py +494 -0
  108. package/scripts/sync_openhands_sdk_skill.py +264 -0
  109. package/skills/README.md +159 -0
  110. package/skills/add-javadoc/.plugin/plugin.json +18 -0
  111. package/skills/add-javadoc/README.md +40 -0
  112. package/skills/add-javadoc/SKILL.md +35 -0
  113. package/skills/add-javadoc/references/example.md +32 -0
  114. package/skills/add-skill/.plugin/plugin.json +18 -0
  115. package/skills/add-skill/README.md +67 -0
  116. package/skills/add-skill/SKILL.md +47 -0
  117. package/skills/add-skill/scripts/fetch_skill.py +259 -0
  118. package/skills/agent-creator/.plugin/plugin.json +20 -0
  119. package/skills/agent-creator/README.md +104 -0
  120. package/skills/agent-creator/SKILL.md +190 -0
  121. package/skills/agent-creator/commands/agent-creator.md +8 -0
  122. package/skills/agent-creator/references/fallback.md +117 -0
  123. package/skills/agent-memory/.plugin/plugin.json +18 -0
  124. package/skills/agent-memory/README.md +35 -0
  125. package/skills/agent-memory/SKILL.md +30 -0
  126. package/skills/agent-memory/commands/remember.md +8 -0
  127. package/skills/agent-sdk-builder/.plugin/plugin.json +18 -0
  128. package/skills/agent-sdk-builder/README.md +40 -0
  129. package/skills/agent-sdk-builder/SKILL.md +37 -0
  130. package/skills/agent-sdk-builder/commands/agent-builder.md +8 -0
  131. package/skills/azure-devops/.plugin/plugin.json +18 -0
  132. package/skills/azure-devops/README.md +55 -0
  133. package/skills/azure-devops/SKILL.md +50 -0
  134. package/skills/bitbucket/.plugin/plugin.json +17 -0
  135. package/skills/bitbucket/README.md +50 -0
  136. package/skills/bitbucket/SKILL.md +45 -0
  137. package/skills/code-review/.plugin/plugin.json +19 -0
  138. package/skills/code-review/README.md +18 -0
  139. package/skills/code-review/SKILL.md +208 -0
  140. package/skills/code-review/commands/codereview-roasted.md +8 -0
  141. package/skills/code-review/commands/codereview.md +8 -0
  142. package/skills/code-review/references/risk-evaluation.md +41 -0
  143. package/skills/code-review/references/supply-chain-security.md +31 -0
  144. package/skills/code-simplifier/.plugin/plugin.json +21 -0
  145. package/skills/code-simplifier/README.md +30 -0
  146. package/skills/code-simplifier/SKILL.md +91 -0
  147. package/skills/code-simplifier/commands/simplify.md +8 -0
  148. package/skills/code-simplifier/references/code-quality-review.md +86 -0
  149. package/skills/code-simplifier/references/code-reuse-review.md +63 -0
  150. package/skills/code-simplifier/references/efficiency-review.md +81 -0
  151. package/skills/datadog/.plugin/plugin.json +19 -0
  152. package/skills/datadog/README.md +100 -0
  153. package/skills/datadog/SKILL.md +95 -0
  154. package/skills/deno/.plugin/plugin.json +18 -0
  155. package/skills/deno/README.md +5 -0
  156. package/skills/deno/SKILL.md +99 -0
  157. package/skills/deno/references/README.md +6 -0
  158. package/skills/discord/.plugin/plugin.json +18 -0
  159. package/skills/discord/README.md +31 -0
  160. package/skills/discord/SKILL.md +109 -0
  161. package/skills/discord/__init__.py +0 -0
  162. package/skills/discord/references/REFERENCE.md +78 -0
  163. package/skills/discord/scripts/__init__.py +0 -0
  164. package/skills/discord/scripts/_http.py +127 -0
  165. package/skills/discord/scripts/post_webhook.py +106 -0
  166. package/skills/discord/scripts/send_message.py +102 -0
  167. package/skills/docker/.plugin/plugin.json +17 -0
  168. package/skills/docker/README.md +34 -0
  169. package/skills/docker/SKILL.md +29 -0
  170. package/skills/evidence-based-citations/.plugin/plugin.json +20 -0
  171. package/skills/evidence-based-citations/README.md +31 -0
  172. package/skills/evidence-based-citations/SKILL.md +59 -0
  173. package/skills/flarglebargle/.plugin/plugin.json +16 -0
  174. package/skills/flarglebargle/README.md +14 -0
  175. package/skills/flarglebargle/SKILL.md +9 -0
  176. package/skills/frontend-design/.plugin/plugin.json +21 -0
  177. package/skills/frontend-design/LICENSE.txt +177 -0
  178. package/skills/frontend-design/README.md +42 -0
  179. package/skills/frontend-design/SKILL.md +42 -0
  180. package/skills/github/.plugin/plugin.json +19 -0
  181. package/skills/github/README.md +42 -0
  182. package/skills/github/SKILL.md +106 -0
  183. package/skills/github-pr-review/.plugin/plugin.json +18 -0
  184. package/skills/github-pr-review/README.md +145 -0
  185. package/skills/github-pr-review/SKILL.md +148 -0
  186. package/skills/github-pr-review/commands/github-pr-review.md +8 -0
  187. package/skills/github-pr-reviewer/.plugin/plugin.json +20 -0
  188. package/skills/github-pr-reviewer/README.md +34 -0
  189. package/skills/github-pr-reviewer/SKILL.md +89 -0
  190. package/skills/github-pr-reviewer/commands/pr-reviewer:setup.md +8 -0
  191. package/skills/github-repo-monitor/.plugin/plugin.json +22 -0
  192. package/skills/github-repo-monitor/README.md +70 -0
  193. package/skills/github-repo-monitor/SKILL.md +316 -0
  194. package/skills/github-repo-monitor/commands/github-monitor:poll.md +8 -0
  195. package/skills/github-repo-monitor/references/github-api.md +241 -0
  196. package/skills/github-repo-monitor/references/state-schema.md +160 -0
  197. package/skills/github-repo-monitor/scripts/main.py +915 -0
  198. package/skills/github-repo-monitor/tests/test_main.py +400 -0
  199. package/skills/gitlab/.plugin/plugin.json +17 -0
  200. package/skills/gitlab/README.md +37 -0
  201. package/skills/gitlab/SKILL.md +32 -0
  202. package/skills/incident-retrospective/.plugin/plugin.json +21 -0
  203. package/skills/incident-retrospective/README.md +34 -0
  204. package/skills/incident-retrospective/SKILL.md +98 -0
  205. package/skills/incident-retrospective/commands/incident-retro:setup.md +8 -0
  206. package/skills/iterate/.plugin/plugin.json +13 -0
  207. package/skills/iterate/README.md +25 -0
  208. package/skills/iterate/SKILL.md +399 -0
  209. package/skills/iterate/commands/babysit.md +8 -0
  210. package/skills/iterate/commands/iterate.md +8 -0
  211. package/skills/iterate/commands/verify.md +8 -0
  212. package/skills/iterate/references/heuristics.md +58 -0
  213. package/skills/iterate/references/verification.md +96 -0
  214. package/skills/jupyter/.plugin/plugin.json +18 -0
  215. package/skills/jupyter/README.md +55 -0
  216. package/skills/jupyter/SKILL.md +50 -0
  217. package/skills/kubernetes/.plugin/plugin.json +18 -0
  218. package/skills/kubernetes/README.md +53 -0
  219. package/skills/kubernetes/SKILL.md +48 -0
  220. package/skills/learn-from-code-review/.plugin/plugin.json +19 -0
  221. package/skills/learn-from-code-review/README.md +64 -0
  222. package/skills/learn-from-code-review/SKILL.md +186 -0
  223. package/skills/learn-from-code-review/commands/learn-from-reviews.md +8 -0
  224. package/skills/linear/.plugin/plugin.json +19 -0
  225. package/skills/linear/README.md +58 -0
  226. package/skills/linear/SKILL.md +213 -0
  227. package/skills/linear-triage/.plugin/plugin.json +21 -0
  228. package/skills/linear-triage/README.md +34 -0
  229. package/skills/linear-triage/SKILL.md +91 -0
  230. package/skills/linear-triage/commands/linear-triage:setup.md +8 -0
  231. package/skills/notion/.plugin/plugin.json +17 -0
  232. package/skills/notion/README.md +114 -0
  233. package/skills/notion/SKILL.md +109 -0
  234. package/skills/npm/.plugin/plugin.json +17 -0
  235. package/skills/npm/README.md +14 -0
  236. package/skills/npm/SKILL.md +9 -0
  237. package/skills/openhands-api/.plugin/plugin.json +22 -0
  238. package/skills/openhands-api/README.md +48 -0
  239. package/skills/openhands-api/SKILL.md +399 -0
  240. package/skills/openhands-api/references/README.md +33 -0
  241. package/skills/openhands-api/references/TROUBLESHOOTING.md +81 -0
  242. package/skills/openhands-api/references/example_prompt.md +12 -0
  243. package/skills/openhands-api/scripts/openhands_api.py +606 -0
  244. package/skills/openhands-api/scripts/openhands_api.ts +252 -0
  245. package/skills/openhands-automation/.plugin/plugin.json +19 -0
  246. package/skills/openhands-automation/README.md +89 -0
  247. package/skills/openhands-automation/SKILL.md +875 -0
  248. package/skills/openhands-automation/commands/automation:create.md +8 -0
  249. package/skills/openhands-automation/references/ab-testing.md +185 -0
  250. package/skills/openhands-automation/references/custom-automation.md +644 -0
  251. package/skills/openhands-sdk/.plugin/plugin.json +20 -0
  252. package/skills/openhands-sdk/README.md +22 -0
  253. package/skills/openhands-sdk/SKILL.md +229 -0
  254. package/skills/openhands-sdk/commands/sdk.md +8 -0
  255. package/skills/pdflatex/.plugin/plugin.json +18 -0
  256. package/skills/pdflatex/README.md +39 -0
  257. package/skills/pdflatex/SKILL.md +34 -0
  258. package/skills/prd/.plugin/plugin.json +19 -0
  259. package/skills/prd/README.md +28 -0
  260. package/skills/prd/SKILL.md +237 -0
  261. package/skills/prd/commands/prd.md +8 -0
  262. package/skills/qa-changes/README.md +18 -0
  263. package/skills/qa-changes/SKILL.md +229 -0
  264. package/skills/qa-changes/commands/qa-changes.md +8 -0
  265. package/skills/release-notes/README.md +24 -0
  266. package/skills/release-notes/SKILL.md +19 -0
  267. package/skills/release-notes/commands/release-notes.md +8 -0
  268. package/skills/research-brief/.plugin/plugin.json +20 -0
  269. package/skills/research-brief/README.md +34 -0
  270. package/skills/research-brief/SKILL.md +99 -0
  271. package/skills/research-brief/commands/research-brief:setup.md +8 -0
  272. package/skills/security/.plugin/plugin.json +18 -0
  273. package/skills/security/README.md +38 -0
  274. package/skills/security/SKILL.md +33 -0
  275. package/skills/skill-creator/.plugin/plugin.json +17 -0
  276. package/skills/skill-creator/LICENSE.txt +202 -0
  277. package/skills/skill-creator/README.md +182 -0
  278. package/skills/skill-creator/SKILL.md +545 -0
  279. package/skills/skill-creator/references/output-patterns.md +82 -0
  280. package/skills/skill-creator/references/workflows.md +28 -0
  281. package/skills/skill-creator/scripts/init_skill.py +303 -0
  282. package/skills/skill-creator/scripts/quick_validate.py +95 -0
  283. package/skills/slack-channel-monitor/.plugin/plugin.json +21 -0
  284. package/skills/slack-channel-monitor/README.md +91 -0
  285. package/skills/slack-channel-monitor/SKILL.md +276 -0
  286. package/skills/slack-channel-monitor/commands/slack-monitor:poll.md +8 -0
  287. package/skills/slack-channel-monitor/references/slack-api.md +207 -0
  288. package/skills/slack-channel-monitor/references/state-schema.md +180 -0
  289. package/skills/slack-channel-monitor/scripts/main.py +962 -0
  290. package/skills/slack-standup-digest/.plugin/plugin.json +21 -0
  291. package/skills/slack-standup-digest/README.md +34 -0
  292. package/skills/slack-standup-digest/SKILL.md +92 -0
  293. package/skills/slack-standup-digest/commands/standup-digest:setup.md +8 -0
  294. package/skills/spark-version-upgrade/.plugin/plugin.json +20 -0
  295. package/skills/spark-version-upgrade/README.md +54 -0
  296. package/skills/spark-version-upgrade/SKILL.md +233 -0
  297. package/skills/ssh/.plugin/plugin.json +18 -0
  298. package/skills/ssh/README.md +140 -0
  299. package/skills/ssh/SKILL.md +135 -0
  300. package/skills/swift-linux/.plugin/plugin.json +17 -0
  301. package/skills/swift-linux/README.md +86 -0
  302. package/skills/swift-linux/SKILL.md +81 -0
  303. package/skills/theme-factory/.plugin/plugin.json +19 -0
  304. package/skills/theme-factory/LICENSE.txt +202 -0
  305. package/skills/theme-factory/README.md +58 -0
  306. package/skills/theme-factory/SKILL.md +59 -0
  307. package/skills/theme-factory/theme-showcase.pdf +0 -0
  308. package/skills/theme-factory/themes/arctic-frost.md +19 -0
  309. package/skills/theme-factory/themes/botanical-garden.md +19 -0
  310. package/skills/theme-factory/themes/desert-rose.md +19 -0
  311. package/skills/theme-factory/themes/forest-canopy.md +19 -0
  312. package/skills/theme-factory/themes/golden-hour.md +19 -0
  313. package/skills/theme-factory/themes/midnight-galaxy.md +19 -0
  314. package/skills/theme-factory/themes/modern-minimalist.md +19 -0
  315. package/skills/theme-factory/themes/ocean-depths.md +19 -0
  316. package/skills/theme-factory/themes/sunset-boulevard.md +19 -0
  317. package/skills/theme-factory/themes/tech-innovation.md +19 -0
  318. package/skills/uv/.plugin/plugin.json +18 -0
  319. package/skills/uv/README.md +5 -0
  320. package/skills/uv/SKILL.md +95 -0
  321. package/skills/uv/references/README.md +5 -0
  322. package/skills/vercel/.plugin/plugin.json +18 -0
  323. package/skills/vercel/README.md +108 -0
  324. package/skills/vercel/SKILL.md +103 -0
  325. package/tests/test_add_skill_installs_to_agents_dir.py +42 -0
  326. package/tests/test_catalogs.py +109 -0
  327. package/tests/test_code_review_risk_evaluation.py +94 -0
  328. package/tests/test_issue_duplicate_checker.py +240 -0
  329. package/tests/test_openhands_api_python.py +152 -0
  330. package/tests/test_plugin_manifest.py +83 -0
  331. package/tests/test_pr_review_diff_payload.py +202 -0
  332. package/tests/test_pr_review_feedback.py +263 -0
  333. package/tests/test_pr_review_prompt.py +152 -0
  334. package/tests/test_pr_review_review_context.py +253 -0
  335. package/tests/test_qa_changes.py +232 -0
  336. package/tests/test_qa_changes_evaluation.py +259 -0
  337. package/tests/test_release_notes_generator.py +990 -0
  338. package/tests/test_sdk_loading.py +150 -0
  339. package/tests/test_skill_plugin_loading.py +149 -0
  340. package/tests/test_skills_have_readme.py +66 -0
  341. package/tests/test_sync_extensions.py +292 -0
  342. package/tests/test_workflow_sync.py +46 -0
  343. package/utils/analysis/README.md +7 -0
  344. package/utils/analysis/laminar_signals/README.md +211 -0
  345. package/utils/analysis/laminar_signals/analyze.py +780 -0
  346. package/utils/analysis/laminar_signals/templates/default.j2 +49 -0
  347. package/utils/analysis/laminar_signals/templates/pr_review.j2 +61 -0
@@ -0,0 +1,260 @@
1
+ """
2
+ PR Review Prompt Template
3
+
4
+ This module contains the prompt template used by the OpenHands agent
5
+ for conducting pull request reviews. The template uses skill triggers:
6
+ - {skill_trigger} will be replaced with '/codereview'
7
+ - /github-pr-review provides instructions for posting review comments via GitHub API
8
+
9
+ The template includes:
10
+ - {diff} - The complete git diff for the PR (may be truncated for large files)
11
+ - {pr_number} - The PR number
12
+ - {commit_id} - The HEAD commit SHA
13
+ - {review_context} - Previous review comments and thread resolution status
14
+
15
+ When sub-agent delegation is enabled (``use_sub_agents=True``), a short
16
+ delegation suffix is appended to the base prompt giving the agent the
17
+ option to delegate file-level reviews via the TaskToolSet.
18
+ """
19
+
20
+ # Template for when there is review context available
21
+ _REVIEW_CONTEXT_SECTION = """
22
+ ## Previous Review History
23
+
24
+ The following shows previous reviews and review threads on this PR.
25
+ Pay attention to:
26
+ - **Unresolved threads**: These issues may still need to be addressed
27
+ - **Resolved threads**: These provide context on what was already discussed
28
+ - **Previous review decisions**: See what other reviewers have said
29
+
30
+ {review_context}
31
+
32
+ When reviewing, consider:
33
+ 1. Don't repeat comments that have already been made and are still relevant
34
+ 2. If an issue is still unresolved in the code, you may reference it
35
+ 3. If resolved, don't bring it up unless the fix introduced new problems
36
+ 4. Focus on NEW issues in the current diff that haven't been discussed yet
37
+ """
38
+
39
+ _EVIDENCE_REQUIREMENT_SECTION = """
40
+ ## PR Description Evidence Requirement
41
+
42
+ Require the PR description to include an `Evidence` section (or similarly labeled section) showing that the code actually works.
43
+
44
+ When checking the PR description:
45
+ - For frontend or UI changes, require a screenshot or video that demonstrates the implemented behavior in the actual product.
46
+ - For backend, API, CLI, or script changes, require the command(s) used to run or exercise the real code path end-to-end and the resulting output.
47
+ - Unit tests alone do **not** count as evidence. Do not accept `pytest`, unit test output, or similar test runs as the only proof that the change works.
48
+ - If the change appears to come from an agent conversation or AI-assisted workflow, prefer a conversation link such as `https://app.all-hands.dev/conversations/{conversation_id}` so reviewers can trace the work.
49
+ - Do not accept vague claims like "tested locally" without concrete runtime artifacts, commands, or output.
50
+
51
+ If the change is substantive and this evidence is missing or weak, call it out as a must-fix issue in your review. Do not invent evidence that is not present in the PR description.
52
+ """
53
+
54
+ FEEDBACK_COMMENT_MARKER = "<!-- openhands-pr-review-feedback -->"
55
+
56
+ _FEEDBACK_FOOTER_SECTION = """
57
+ ## Review Feedback Footer
58
+
59
+ When you submit the top-level GitHub review body, append this exact footer at the end of that same review body so maintainers can react without creating a separate PR comment:
60
+
61
+ ```md
62
+ ---
63
+ Was this automated review useful? React with 👍 or 👎 to this review to help us measure review quality.
64
+ Workflow run: {review_run_url}
65
+ {feedback_comment_marker}
66
+ ```
67
+
68
+ Requirements:
69
+ - Put this footer in the main review body, not in a separate issue comment.
70
+ - Keep the rest of the review body concise.
71
+ - If you would otherwise post only inline comments, still include a short top-level review body so this footer has somewhere to live.
72
+ """
73
+
74
+ PROMPT = """{skill_trigger}
75
+ /github-pr-review
76
+
77
+ When posting a review, keep the review body brief unless your active review instructions require a longer structured format.
78
+
79
+ For dependency update PRs, do **NOT** approve a target version that was published less than 7 days ago.
80
+
81
+ Review the PR changes below and identify issues that need to be addressed.
82
+
83
+ ## Pull Request Information
84
+
85
+ - **Title**: {title}
86
+ - **Description**: {body}
87
+ - **Repository**: {repo_name}
88
+ - **Base Branch**: {base_branch}
89
+ - **Head Branch**: {head_branch}
90
+ - **PR Number**: {pr_number}
91
+ - **Commit ID**: {commit_id}
92
+
93
+ {review_context_section}{evidence_requirements_section}{feedback_footer_section}
94
+ {files_manifest}
95
+ ## Patches
96
+
97
+ The fenced block below contains the per-file patches. Individual patches may be **abbreviated** (look for `[patch abbreviated: ...]`) or **omitted** (look for `[patch omitted: ...]`) when they exceed the per-file or total budget. Files that appear in the manifest above but whose patch is missing or short here are still present in the PR — read the file from the workspace to inspect them. Do not flag them as missing from the PR.
98
+
99
+ ```diff
100
+ {diff}
101
+ ```
102
+
103
+ Analyze the changes and post your review using the GitHub API.
104
+ """
105
+
106
+ # Appended to PROMPT when use_sub_agents=True. Gives the main agent the
107
+ # option to delegate via the TaskToolSet without duplicating the base prompt.
108
+ _DELEGATION_SUFFIX = """
109
+ ## Sub-agent Delegation
110
+
111
+ You have access to the **task** tool for delegating file-level reviews to
112
+ `file_reviewer` sub-agents. Use it when the diff is large — roughly 4+ files
113
+ or 500+ changed lines. For smaller diffs, just review directly.
114
+
115
+ When delegating, split the diff by file (or small group of related files) and
116
+ call the task tool with `subagent_type: "file_reviewer"`. Each sub-agent will
117
+ return a JSON array of findings. Merge them, de-duplicate, drop noise, and
118
+ post a single consolidated review via the GitHub API.
119
+ """
120
+
121
+ # Skill content injected into each file_reviewer sub-agent.
122
+ # Defines the review persona, available tools, and — most importantly — the
123
+ # exact JSON schema the sub-agent must return.
124
+ FILE_REVIEWER_SKILL = """\
125
+ You are a **file-level code reviewer** sub-agent.
126
+
127
+ ## Your Task
128
+
129
+ You will receive a diff for one or more files from a pull request.
130
+ Review the changes and return structured findings.
131
+
132
+ ## Tools
133
+
134
+ You have `terminal` and `file_editor` so you can inspect the full source
135
+ files for surrounding context — use `cat`, `grep`, or `file_editor view`
136
+ when the diff alone is not enough to judge an issue.
137
+
138
+ ## Review Style
139
+
140
+ Be direct, pragmatic, and thorough. Focus on correctness, security,
141
+ simplicity, and maintainability. Call out real problems; skip trivial noise.
142
+
143
+ ## Output Format
144
+
145
+ Return a JSON array wrapped in a ```json fenced code block.
146
+ Each element must have exactly these fields:
147
+
148
+ | Field | Type | Description |
149
+ |------------|--------|-------------|
150
+ | `path` | string | File path exactly as shown in the diff header (e.g. `src/utils.py`) |
151
+ | `line` | int | Line number in the **new** file where the issue occurs |
152
+ | `severity` | string | One of: `"critical"`, `"major"`, `"minor"`, `"nit"` |
153
+ | `body` | string | Concise description of the issue, including a suggested fix |
154
+
155
+ ### Severity guide
156
+ - **critical** — bug, security vulnerability, or data loss
157
+ - **major** — incorrect logic, missing error handling, performance issue
158
+ - **minor** — style, readability, or minor correctness concern
159
+ - **nit** — cosmetic or trivial preference
160
+
161
+ ### Example
162
+
163
+ ```json
164
+ [
165
+ {{"path": "src/utils.py", "line": 42, "severity": "major", "body": "Unchecked `None` return — add a guard before accessing `.value`."}},
166
+ {{"path": "src/utils.py", "line": 78, "severity": "nit", "body": "Unused import `os`."}}
167
+ ]
168
+ ```
169
+
170
+ If you find no issues, return:
171
+ ```json
172
+ []
173
+ ```
174
+
175
+ When you are done, call the `finish` tool with the JSON array as the message.
176
+ """
177
+
178
+
179
+ def format_prompt(
180
+ skill_trigger: str,
181
+ title: str,
182
+ body: str,
183
+ repo_name: str,
184
+ base_branch: str,
185
+ head_branch: str,
186
+ pr_number: str,
187
+ commit_id: str,
188
+ diff: str,
189
+ files_manifest: str = "",
190
+ review_context: str = "",
191
+ require_evidence: bool = False,
192
+ collect_feedback: bool = False,
193
+ review_run_url: str = "",
194
+ use_sub_agents: bool = False,
195
+ ) -> str:
196
+ """Format the PR review prompt with all parameters.
197
+
198
+ Args:
199
+ skill_trigger: The skill trigger (e.g., '/codereview')
200
+ title: PR title
201
+ body: PR description
202
+ repo_name: Repository name (owner/repo)
203
+ base_branch: Base branch name
204
+ head_branch: Head branch name
205
+ pr_number: PR number
206
+ commit_id: HEAD commit SHA
207
+ diff: Git diff content
208
+ review_context: Formatted previous review context. If empty or whitespace-only,
209
+ the review context section is omitted from the prompt.
210
+ require_evidence: Whether to instruct the reviewer to enforce PR description
211
+ evidence showing the code works.
212
+ collect_feedback: Whether to instruct the reviewer to append the feedback
213
+ footer to the main review body.
214
+ review_run_url: Workflow run URL to embed in the feedback footer.
215
+ use_sub_agents: When True, the agent gets the TaskToolSet and decides
216
+ at runtime whether to delegate file-level reviews to
217
+ sub-agents based on diff size and complexity.
218
+
219
+ Returns:
220
+ Formatted prompt string
221
+ """
222
+ # Only include the review context section if there is actual context
223
+ if review_context and review_context.strip():
224
+ review_context_section = _REVIEW_CONTEXT_SECTION.format(
225
+ review_context=review_context
226
+ )
227
+ else:
228
+ review_context_section = ""
229
+
230
+ evidence_requirements_section = (
231
+ _EVIDENCE_REQUIREMENT_SECTION if require_evidence else ""
232
+ )
233
+
234
+ feedback_footer_section = ""
235
+ if collect_feedback:
236
+ feedback_footer_section = _FEEDBACK_FOOTER_SECTION.format(
237
+ review_run_url=review_run_url or "unavailable",
238
+ feedback_comment_marker=FEEDBACK_COMMENT_MARKER,
239
+ )
240
+
241
+ prompt = PROMPT.format(
242
+ skill_trigger=skill_trigger,
243
+ title=title,
244
+ body=body,
245
+ repo_name=repo_name,
246
+ base_branch=base_branch,
247
+ head_branch=head_branch,
248
+ pr_number=pr_number,
249
+ commit_id=commit_id,
250
+ review_context_section=review_context_section,
251
+ evidence_requirements_section=evidence_requirements_section,
252
+ feedback_footer_section=feedback_footer_section,
253
+ files_manifest=files_manifest,
254
+ diff=diff,
255
+ )
256
+
257
+ if use_sub_agents:
258
+ prompt += _DELEGATION_SUFFIX
259
+
260
+ return prompt
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: PR Review by OpenHands
3
+
4
+ on:
5
+ # Use pull_request_target to allow fork PRs to access secrets when triggered by maintainers
6
+ # Security: This workflow runs when:
7
+ # 1. A new PR is opened (non-draft), OR
8
+ # 2. A draft PR is marked as ready for review, OR
9
+ # 3. A maintainer adds the 'review-this' label, OR
10
+ # 4. A maintainer requests openhands-agent or all-hands-bot as a reviewer
11
+ # Adding labels and requesting reviewers requires write access.
12
+ # The PR code is explicitly checked out for review, but secrets are only accessible
13
+ # because the workflow runs in the base repository context.
14
+ pull_request_target:
15
+ types: [opened, ready_for_review, labeled, review_requested]
16
+
17
+ permissions:
18
+ contents: read
19
+ pull-requests: write
20
+ issues: write
21
+
22
+ jobs:
23
+ pr-review:
24
+ # Run when one of the following conditions is met:
25
+ # 1. A new non-draft PR is opened by a non-first-time contributor, OR
26
+ # 2. A draft PR is converted to ready for review by a non-first-time contributor, OR
27
+ # 3. 'review-this' label is added, OR
28
+ # 4. openhands-agent or all-hands-bot is requested as a reviewer
29
+ # Note: FIRST_TIME_CONTRIBUTOR and NONE PRs require manual trigger via label/reviewer request.
30
+ if: |
31
+ (github.event.action == 'opened' && github.event.pull_request.draft == false && github.event.pull_request.author_association != 'FIRST_TIME_CONTRIBUTOR' && github.event.pull_request.author_association != 'NONE') ||
32
+ (github.event.action == 'ready_for_review' && github.event.pull_request.author_association != 'FIRST_TIME_CONTRIBUTOR' && github.event.pull_request.author_association != 'NONE') ||
33
+ github.event.label.name == 'review-this' ||
34
+ github.event.requested_reviewer.login == 'openhands-agent' ||
35
+ github.event.requested_reviewer.login == 'all-hands-bot'
36
+ concurrency:
37
+ group: pr-review-${{ github.event.pull_request.number }}
38
+ cancel-in-progress: true
39
+ runs-on: ubuntu-24.04
40
+ steps:
41
+ - name: Run PR Review
42
+ uses: OpenHands/extensions/plugins/pr-review@main
43
+ with:
44
+ llm-model: litellm_proxy/claude-sonnet-4-5-20250929
45
+ llm-base-url: https://llm-proxy.app.all-hands.dev
46
+ # [DEPRECATED] review-style is no longer used; standard and roasted are merged
47
+ # review-style: roasted
48
+ use-sub-agents: 'false' # Disabled by default (issue #208: high cost / timeouts)
49
+ llm-api-key: ${{ secrets.LLM_API_KEY }}
50
+ github-token: ${{ secrets.OPENHANDS_BOT_GITHUB_PAT_PUBLIC }}
51
+ lmnr-api-key: ${{ secrets.LMNR_SKILLS_API_KEY }}
@@ -0,0 +1,85 @@
1
+ ---
2
+ name: PR Review Evaluation
3
+
4
+ # This workflow evaluates how well PR review comments were addressed.
5
+ # It runs when a PR is closed to assess review effectiveness.
6
+ #
7
+ # Security note: pull_request_target is safe here because:
8
+ # 1. Only triggers on PR close (not on code changes)
9
+ # 2. Does not checkout PR code - only downloads artifacts from trusted workflow runs
10
+ # 3. Runs evaluation scripts from the extensions repo, not from the PR
11
+
12
+ on:
13
+ pull_request_target:
14
+ types: [closed]
15
+
16
+ permissions:
17
+ contents: read
18
+ pull-requests: read
19
+
20
+ jobs:
21
+ evaluate:
22
+ runs-on: ubuntu-24.04
23
+ env:
24
+ PR_NUMBER: ${{ github.event.pull_request.number }}
25
+ REPO_NAME: ${{ github.repository }}
26
+ PR_MERGED: ${{ github.event.pull_request.merged }}
27
+
28
+ steps:
29
+ - name: Download review trace artifact
30
+ id: download-trace
31
+ uses: dawidd6/action-download-artifact@v6
32
+ continue-on-error: true
33
+ with:
34
+ workflow: pr-review-by-openhands.yml
35
+ name: pr-review-trace-${{ github.event.pull_request.number }}
36
+ path: trace-info
37
+ search_artifacts: true
38
+ if_no_artifact_found: warn
39
+
40
+ - name: Check if trace file exists
41
+ id: check-trace
42
+ run: |
43
+ if [ -f "trace-info/laminar_trace_info.json" ]; then
44
+ echo "trace_exists=true" >> $GITHUB_OUTPUT
45
+ echo "Found trace file for PR #$PR_NUMBER"
46
+ else
47
+ echo "trace_exists=false" >> $GITHUB_OUTPUT
48
+ echo "No trace file found for PR #$PR_NUMBER - skipping evaluation"
49
+ fi
50
+
51
+ # Always checkout main branch for security - cannot test script changes in PRs
52
+ - name: Checkout extensions repository
53
+ if: steps.check-trace.outputs.trace_exists == 'true'
54
+ uses: actions/checkout@v5
55
+ with:
56
+ repository: OpenHands/extensions
57
+ path: extensions
58
+
59
+ - name: Set up Python
60
+ if: steps.check-trace.outputs.trace_exists == 'true'
61
+ uses: actions/setup-python@v6
62
+ with:
63
+ python-version: '3.12'
64
+
65
+ - name: Install dependencies
66
+ if: steps.check-trace.outputs.trace_exists == 'true'
67
+ run: pip install lmnr
68
+
69
+ - name: Run evaluation
70
+ if: steps.check-trace.outputs.trace_exists == 'true'
71
+ env:
72
+ # Script expects LMNR_PROJECT_API_KEY; org secret is named LMNR_SKILLS_API_KEY
73
+ LMNR_PROJECT_API_KEY: ${{ secrets.LMNR_SKILLS_API_KEY }}
74
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
75
+ run: |
76
+ python extensions/plugins/pr-review/scripts/evaluate_review.py \
77
+ --trace-file trace-info/laminar_trace_info.json
78
+
79
+ - name: Upload evaluation logs
80
+ uses: actions/upload-artifact@v5
81
+ if: always() && steps.check-trace.outputs.trace_exists == 'true'
82
+ with:
83
+ name: pr-review-evaluation-${{ github.event.pull_request.number }}
84
+ path: '*.log'
85
+ retention-days: 30
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "qa-changes",
3
+ "version": "0.1.0",
4
+ "description": "Automated QA validation of PR changes — sets up the environment, runs tests, exercises changed behavior, and reports results",
5
+ "author": {
6
+ "name": "OpenHands",
7
+ "email": "contact@all-hands.dev"
8
+ },
9
+ "license": "MIT",
10
+ "repository": "https://github.com/OpenHands/extensions"
11
+ }
@@ -0,0 +1,185 @@
1
+ # QA Changes Plugin
2
+
3
+ Automated pull request QA validation using OpenHands agents. Unlike the [PR Review plugin](../pr-review/) which reads diffs and posts code review comments, this plugin **actually runs the software** — setting up the environment, exercising changed behavior as a real user would, and posting a structured QA report. It does not re-run the test suite (that's CI's job) or analyze code style/logic (that's code review's job).
4
+
5
+ ## Quick Start
6
+
7
+ Copy the workflow file to your repository:
8
+
9
+ ```bash
10
+ cp plugins/qa-changes/workflows/qa-changes-by-openhands.yml \
11
+ .github/workflows/qa-changes-by-openhands.yml
12
+ ```
13
+
14
+ Then configure the required secrets (see [Installation](#installation) below).
15
+
16
+ ## How It Works
17
+
18
+ The QA agent follows a four-phase methodology:
19
+
20
+ 1. **Understand** — Reads the PR diff, title, and description. Classifies changes and identifies entry points (CLI commands, API endpoints, UI pages).
21
+ 2. **Setup** — Bootstraps the repo: installs dependencies, builds the project. Notes CI status but does not re-run tests.
22
+ 3. **Exercise** — The core phase. Actually uses the software the way a human would: spins up servers, opens browsers, runs CLI commands, makes HTTP requests. Focuses on functional verification that CI and code review cannot do.
23
+ 4. **Report** — Posts a structured QA report as a PR review with evidence (commands, outputs, screenshots) and a verdict.
24
+
25
+ The agent knows when to give up: if a verification approach fails after three materially different attempts, it switches to a different approach. If two fundamentally different approaches fail, it reports honestly what could not be verified and suggests `AGENTS.md` guidance for future runs.
26
+
27
+ ## Plugin Contents
28
+
29
+ ```
30
+ plugins/qa-changes/
31
+ ├── README.md # This file
32
+ ├── action.yml # Composite GitHub Action
33
+ ├── skills/ # Symbolic links to QA skills
34
+ │ └── qa-changes -> ../../../skills/qa-changes
35
+ ├── workflows/ # Example GitHub workflow files
36
+ │ └── qa-changes-by-openhands.yml
37
+ └── scripts/ # Python scripts for QA execution
38
+ ├── agent_script.py # Main QA agent script
39
+ └── prompt.py # Prompt template
40
+ ```
41
+
42
+ ## Installation
43
+
44
+ ### 1. Copy the Workflow File
45
+
46
+ Copy the workflow file to your repository's `.github/workflows/` directory:
47
+
48
+ ```bash
49
+ mkdir -p .github/workflows
50
+ cp plugins/qa-changes/workflows/qa-changes-by-openhands.yml \
51
+ .github/workflows/qa-changes-by-openhands.yml
52
+ ```
53
+
54
+ ### 2. Configure Secrets
55
+
56
+ Add the following secrets in your repository settings (**Settings → Secrets and variables → Actions**):
57
+
58
+ | Secret | Required | Description |
59
+ |--------|----------|-------------|
60
+ | `LLM_API_KEY` | Yes | API key for your LLM provider |
61
+ | `GITHUB_TOKEN` | Auto | Provided automatically by GitHub Actions |
62
+
63
+ ### 3. Create the QA Label (Optional)
64
+
65
+ Create a `qa-this` label for manual QA triggers:
66
+
67
+ 1. Go to **Issues → Labels**
68
+ 2. Click **New label**
69
+ 3. Name: `qa-this`
70
+ 4. Description: `Trigger OpenHands QA validation`
71
+
72
+ ## Usage
73
+
74
+ ### Automatic Triggers
75
+
76
+ QA validation is automatically triggered when:
77
+ - A new non-draft PR is opened (by trusted contributors)
78
+ - A draft PR is marked as ready for review
79
+ - The `qa-this` label is added
80
+ - `openhands-agent` is requested as a reviewer
81
+
82
+ ### Requesting QA
83
+
84
+ **Option 1: Add Label**
85
+
86
+ Add the `qa-this` label to any PR.
87
+
88
+ **Option 2: Request as Reviewer**
89
+
90
+ Request `openhands-agent` as a reviewer on the PR.
91
+
92
+ ## Action Inputs
93
+
94
+ | Input | Required | Default | Description |
95
+ |-------|----------|---------|-------------|
96
+ | `llm-model` | No | `anthropic/claude-sonnet-4-5-20250929` | LLM model to use |
97
+ | `llm-base-url` | No | `''` | Custom LLM endpoint URL |
98
+ | `extensions-repo` | No | `OpenHands/extensions` | Extensions repository |
99
+ | `extensions-version` | No | `main` | Git ref (tag, branch, or SHA) |
100
+ | `max-budget` | No | `10.0` | Maximum LLM cost in dollars — agent stops when exceeded |
101
+ | `timeout-minutes` | No | `30` | Wall-clock timeout for the QA step |
102
+ | `max-iterations` | No | `500` | Maximum agent iterations (each is one LLM call + action) |
103
+ | `llm-api-key` | Yes | - | LLM API key |
104
+ | `github-token` | Yes | - | GitHub token for API access |
105
+
106
+ ## QA Report Format
107
+
108
+ The agent posts a PR comment with this structure:
109
+
110
+ ```
111
+ ## QA Report
112
+
113
+ **Summary**: [One-sentence verdict]
114
+
115
+ ### Environment Setup
116
+ [Build/install results]
117
+
118
+ ### CI Status
119
+ [Note whether CI checks pass or fail — do not re-run tests]
120
+
121
+ ### Functional Verification
122
+ [Commands run, outputs observed, screenshots, behavior verified]
123
+
124
+ ### Unable to Verify (if applicable)
125
+ [What could not be verified, what was attempted, suggested AGENTS.md guidance]
126
+
127
+ ### Issues Found
128
+ - 🔴 **Blocker**: [Description]
129
+ - 🟠 **Issue**: [Description]
130
+ - 🟡 **Minor**: [Description]
131
+
132
+ ### Verdict
133
+ ✅ PASS / ⚠️ PASS WITH ISSUES / ❌ FAIL / 🟡 PARTIAL
134
+ ```
135
+
136
+ ## Customizing QA Guidelines
137
+
138
+ Add project-specific QA guidelines to your repository:
139
+
140
+ ### Option 1: Custom QA Skill
141
+
142
+ Create `.agents/skills/qa-guide.md`:
143
+
144
+ ```markdown
145
+ ---
146
+ name: qa-guide
147
+ description: Project-specific QA guidelines
148
+ triggers:
149
+ - /qa-changes
150
+ ---
151
+
152
+ # Project QA Guidelines
153
+
154
+ ## Setup Commands
155
+ - `make install` to install dependencies
156
+ - `make build` to build the project
157
+
158
+ ## How to Run the App
159
+ - `make serve` to start the dev server on port 8080
160
+ - `python -m myapp --help` for CLI usage
161
+
162
+ ## Key Behaviors to Verify
163
+ - [List critical user flows]
164
+ - [List known fragile areas]
165
+ ```
166
+
167
+ ### Option 2: Repository AGENTS.md
168
+
169
+ Add setup and test commands to `AGENTS.md` at your repository root. The agent reads this file automatically.
170
+
171
+ ## Security
172
+
173
+ The workflow uses `pull_request` (not `pull_request_target`) so that fork PRs do **not** get access to the base repository's secrets. Since the QA agent *executes* code from the PR (unlike a code-review agent which only reads diffs), using `pull_request_target` would allow untrusted fork code to run with the repo's `GITHUB_TOKEN` and `LLM_API_KEY`.
174
+
175
+ The trade-off is that fork PRs won't have access to repository secrets. In the example `pull_request` workflow, the action now detects that case and exits successfully with a clear skip notice instead of failing. Maintainers can run QA locally or set up a separate trusted workflow for those cases.
176
+
177
+ **Note**: The `FIRST_TIME_CONTRIBUTOR` and `NONE` author associations are excluded from automatic triggers as an additional safety layer.
178
+
179
+ ## Contributing
180
+
181
+ See the main [extensions repository](https://github.com/OpenHands/extensions) for contribution guidelines.
182
+
183
+ ## License
184
+
185
+ This plugin is part of the OpenHands extensions repository. See [LICENSE](/LICENSE) for details.