@bluefly/openstandardagents 0.2.7 → 0.2.9

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 (327) hide show
  1. package/.devfile.yaml +1 -1
  2. package/.env.example +1 -1
  3. package/.github/AGENTS.md +245 -0
  4. package/.github/agents/github-issue-triage.ossa.yaml +99 -0
  5. package/.github/agents/github-pr-triage.ossa.yaml +137 -0
  6. package/.github/workflows/issue-sync-to-gitlab.yml +138 -0
  7. package/.github/workflows/pr-triage-to-gitlab.yml +164 -0
  8. package/.version.json +2 -2
  9. package/.wiki-config.json +24 -0
  10. package/CHANGELOG.md +44 -18
  11. package/CODEOWNERS +75 -0
  12. package/CONTRIBUTING.md +103 -4
  13. package/README.md +178 -243
  14. package/dist/index.d.ts +1 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +2 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/repositories/schema.repository.d.ts +6 -1
  19. package/dist/repositories/schema.repository.d.ts.map +1 -1
  20. package/dist/repositories/schema.repository.js +49 -27
  21. package/dist/repositories/schema.repository.js.map +1 -1
  22. package/dist/services/migration.service.d.ts +4 -3
  23. package/dist/services/migration.service.d.ts.map +1 -1
  24. package/dist/services/migration.service.js +11 -10
  25. package/dist/services/migration.service.js.map +1 -1
  26. package/dist/services/release-automation/release.service.js +1 -1
  27. package/dist/services/release-automation/release.service.js.map +1 -1
  28. package/dist/services/release-automation/schemas/release.schema.js +1 -1
  29. package/dist/services/release-automation/webhook.service.js +3 -3
  30. package/dist/services/release-automation/webhook.service.js.map +1 -1
  31. package/dist/services/runtime/claude/claude-adapter.d.ts +1 -1
  32. package/dist/services/runtime/claude/claude-adapter.d.ts.map +1 -1
  33. package/dist/services/runtime/claude/claude-adapter.js +2 -2
  34. package/dist/services/runtime/claude/claude-adapter.js.map +1 -1
  35. package/dist/spec/v0.2.8/CHANGELOG.md +401 -0
  36. package/dist/spec/v0.2.8/README.md +72 -0
  37. package/dist/spec/v0.2.8/migrations/v0.2.3-to-v0.2.4.md +599 -0
  38. package/dist/spec/v0.2.8/migrations/v0.2.5-RC-to-v0.2.6.md +65 -0
  39. package/dist/spec/v0.2.8/migrations/v0.2.6-to-v0.2.8.md +81 -0
  40. package/{spec/v0.2.6-dev/ossa-0.2.5.schema.json → dist/spec/v0.2.8/ossa-0.2.8.schema.json} +1509 -52
  41. package/dist/spec/v0.2.8/ossa-0.2.8.yaml +581 -0
  42. package/dist/spec/v0.2.9/a2a-protocol.md +1337 -0
  43. package/dist/spec/v0.2.9/agent.md +1946 -0
  44. package/dist/spec/v0.2.9/capabilities/index.yaml +25 -0
  45. package/dist/spec/v0.2.9/capabilities/memory.yaml +251 -0
  46. package/dist/spec/v0.2.9/capability-schema.md +576 -0
  47. package/dist/spec/v0.2.9/compliance-profiles.md +533 -0
  48. package/dist/spec/v0.2.9/conformance-testing.md +1527 -0
  49. package/dist/spec/v0.2.9/gitlab-duo-integration.md +621 -0
  50. package/dist/spec/v0.2.9/ossa-0.2.9.schema.json +3699 -0
  51. package/dist/spec/v0.2.9/runtime-semantics.md +464 -0
  52. package/dist/spec/v0.2.9/security-model.md +1245 -0
  53. package/dist/spec/v0.2.9/semantic-conventions.md +347 -0
  54. package/dist/spec/v0.2.9/types.ts +522 -0
  55. package/dist/types/index.d.ts +3 -2
  56. package/dist/types/index.d.ts.map +1 -1
  57. package/dist/types/policy.d.ts +377 -0
  58. package/dist/types/policy.d.ts.map +1 -0
  59. package/dist/types/policy.js +84 -0
  60. package/dist/types/policy.js.map +1 -0
  61. package/dist/utils/index.d.ts +6 -0
  62. package/dist/utils/index.d.ts.map +1 -0
  63. package/dist/utils/index.js +6 -0
  64. package/dist/utils/index.js.map +1 -0
  65. package/dist/utils/version.d.ts +68 -0
  66. package/dist/utils/version.d.ts.map +1 -0
  67. package/dist/utils/version.js +156 -0
  68. package/dist/utils/version.js.map +1 -0
  69. package/docs/specs/policy-dsl.md +925 -0
  70. package/eslint-report.json +1 -0
  71. package/examples/adk-integration/code-review-workflow.yml +1 -1
  72. package/examples/adk-integration/customer-support.yml +1 -1
  73. package/examples/adk-integration/data-pipeline.yml +1 -1
  74. package/examples/advanced/reasoning-agent.yaml +136 -0
  75. package/examples/advanced/workflows/hybrid-model-strategy.yaml +1 -1
  76. package/examples/agent-manifests/critics/critic-agent.yaml +1 -1
  77. package/examples/agent-manifests/governors/governor-agent.yaml +1 -1
  78. package/examples/agent-manifests/integrators/integrator-agent.yaml +1 -1
  79. package/examples/agent-manifests/judges/judge-agent.yaml +1 -1
  80. package/examples/agent-manifests/monitors/monitor-agent.yaml +1 -1
  81. package/examples/agent-manifests/orchestrators/orchestrator-agent.yaml +1 -1
  82. package/examples/agent-manifests/sample-compliant-agent.yaml +1 -1
  83. package/examples/agent-manifests/workers/worker-agent.yaml +1 -1
  84. package/examples/agents-md/code-agent.ossa.json +100 -0
  85. package/examples/agents-md/monorepo-agent.ossa.yaml +180 -0
  86. package/examples/anthropic/claude-assistant.ossa.json +1 -1
  87. package/examples/autogen/multi-agent.ossa.json +1 -1
  88. package/examples/claude-code/code-reviewer.ossa.yaml +78 -0
  89. package/examples/claude-code/ossa-validator.ossa.yaml +80 -0
  90. package/examples/common_npm/agent-router.ossa.yaml +1 -0
  91. package/examples/common_npm/agent-router.v0.2.2.ossa.yaml +1 -1
  92. package/examples/crewai/research-team.ossa.json +1 -1
  93. package/examples/cursor/code-review-agent.ossa.json +1 -1
  94. package/examples/drupal/gitlab-ml-recommender.ossa.yaml +1 -0
  95. package/examples/drupal/gitlab-ml-recommender.v0.2.2.ossa.yaml +1 -1
  96. package/examples/extensions/agents-md-v1.yml +175 -0
  97. package/examples/extensions/drupal-v1.yml +1 -1
  98. package/examples/extensions/kagent-v1.yml +1 -1
  99. package/examples/getting-started/hello-world-complete.ossa.yaml +1 -1
  100. package/examples/integration-patterns/agent-to-agent-orchestration.ossa.yaml +4 -4
  101. package/examples/kagent/compliance-validator.ossa.yaml +1 -1
  102. package/examples/kagent/cost-optimizer.ossa.yaml +1 -1
  103. package/examples/kagent/documentation-agent.ossa.yaml +1 -1
  104. package/examples/kagent/k8s-troubleshooter-v1.ossa.yaml +1 -0
  105. package/examples/kagent/k8s-troubleshooter-v1.v0.2.2.ossa.yaml +1 -1
  106. package/examples/kagent/k8s-troubleshooter.ossa.yaml +1 -1
  107. package/examples/kagent/security-scanner.ossa.yaml +1 -1
  108. package/examples/langchain/chain-agent.ossa.json +1 -1
  109. package/examples/langflow/workflow-agent.ossa.json +1 -1
  110. package/examples/langgraph/state-machine-agent.ossa.json +1 -1
  111. package/examples/llamaindex/rag-agent.ossa.json +1 -1
  112. package/examples/migration-guides/from-langchain-to-ossa.yaml +4 -4
  113. package/examples/multi-agent/README.md +74 -0
  114. package/examples/multi-agent/conditional-router.ossa.yaml +42 -0
  115. package/examples/multi-agent/parallel-execution.ossa.yaml +54 -0
  116. package/examples/multi-agent/sequential-pipeline.ossa.yaml +45 -0
  117. package/examples/openai/basic-agent.ossa.yaml +1 -1
  118. package/examples/openai/multi-tool-agent.ossa.json +1 -1
  119. package/examples/openai/swarm-agent.ossa.json +1 -1
  120. package/examples/production/document-analyzer-openai.yml +1 -1
  121. package/examples/quickstart/support-agent.ossa.yaml +1 -1
  122. package/examples/spec-examples/audit-agent.yml +1 -1
  123. package/examples/spec-examples/chat-agent.yml +1 -1
  124. package/examples/spec-examples/compliance-agent.yml +1 -1
  125. package/examples/spec-examples/monitoring-agent.yml +1 -1
  126. package/examples/spec-examples/workflow-agent.yml +1 -1
  127. package/examples/templates/ossa-compliance.yaml +1 -1
  128. package/examples/vercel/edge-agent.ossa.json +1 -1
  129. package/gl-code-quality-report.json +62 -0
  130. package/llms-ctx-full.txt +39 -0
  131. package/llms-ctx.txt +39 -0
  132. package/llms.txt +47 -0
  133. package/package.json +6 -3
  134. package/scripts/README.md +25 -0
  135. package/scripts/compliance-audit.ts +796 -0
  136. package/scripts/eslint-to-codequality.cjs +34 -0
  137. package/scripts/generate-agents-catalog.ts +2 -1
  138. package/scripts/generate-api-docs.ts +2 -1
  139. package/scripts/generate-examples-docs.ts +2 -1
  140. package/scripts/generate-llms-ctx.sh +17 -0
  141. package/scripts/generate-schema-docs.ts +31 -10
  142. package/scripts/sync-version.js +4 -12
  143. package/scripts/validate-schema.ts +2 -1
  144. package/spec/v0.2.8/CHANGELOG.md +401 -0
  145. package/spec/v0.2.8/README.md +72 -0
  146. package/spec/v0.2.8/migrations/v0.2.3-to-v0.2.4.md +599 -0
  147. package/spec/v0.2.8/migrations/v0.2.5-RC-to-v0.2.6.md +65 -0
  148. package/spec/v0.2.8/migrations/v0.2.6-to-v0.2.8.md +81 -0
  149. package/spec/{v0.2.6-dev/ossa-0.2.6-dev.schema.json → v0.2.8/ossa-0.2.8.schema.json} +1509 -52
  150. package/spec/v0.2.8/ossa-0.2.8.yaml +581 -0
  151. package/spec/v0.2.9/a2a-protocol.md +1337 -0
  152. package/spec/v0.2.9/agent.md +1946 -0
  153. package/spec/v0.2.9/capabilities/index.yaml +25 -0
  154. package/spec/v0.2.9/capabilities/memory.yaml +251 -0
  155. package/spec/v0.2.9/capability-schema.md +576 -0
  156. package/spec/v0.2.9/compliance-profiles.md +533 -0
  157. package/spec/v0.2.9/conformance-testing.md +1527 -0
  158. package/spec/v0.2.9/gitlab-duo-integration.md +621 -0
  159. package/spec/v0.2.9/ossa-0.2.9.schema.json +3699 -0
  160. package/spec/v0.2.9/runtime-semantics.md +464 -0
  161. package/spec/v0.2.9/security-model.md +1245 -0
  162. package/spec/v0.2.9/semantic-conventions.md +347 -0
  163. package/spec/v0.2.9/types.ts +522 -0
  164. package/test-results/junit.xml +337 -0
  165. package/.github/workflows/pr-comment.yml +0 -33
  166. package/bin/validate-ossa-0.2.5-RC.ts +0 -244
  167. package/dist/spec/v0.2.6-dev/ossa-0.2.5.schema.json +0 -1696
  168. package/dist/spec/v0.2.6-dev/ossa-0.2.6-dev.schema.json +0 -1696
  169. package/scripts/lib/exec.ts +0 -37
  170. package/scripts/lib/file-ops.ts +0 -58
  171. package/scripts/lib/version.ts +0 -83
  172. package/website/.lighthouserc.ts +0 -24
  173. package/website/.prettierrc +0 -10
  174. package/website/DESIGN_SYSTEM_IMPLEMENTATION.md +0 -445
  175. package/website/Dockerfile +0 -30
  176. package/website/app/about/page.tsx +0 -304
  177. package/website/app/blog/[slug]/page.tsx +0 -208
  178. package/website/app/blog/page.tsx +0 -249
  179. package/website/app/design-guide/page.tsx +0 -511
  180. package/website/app/docs/[[...slug]]/page.tsx +0 -847
  181. package/website/app/docs/core-concepts/project-structure/page.tsx +0 -349
  182. package/website/app/ecosystem/page.tsx +0 -410
  183. package/website/app/examples/page.tsx +0 -133
  184. package/website/app/globals.scss +0 -370
  185. package/website/app/layout.tsx +0 -106
  186. package/website/app/license/page.tsx +0 -183
  187. package/website/app/not-found.tsx +0 -18
  188. package/website/app/page.tsx +0 -686
  189. package/website/app/page.tsx.bak +0 -679
  190. package/website/app/page.tsx.bak2 +0 -649
  191. package/website/app/playground/page.tsx +0 -487
  192. package/website/app/robots.ts +0 -19
  193. package/website/app/rss.xml/route.ts +0 -74
  194. package/website/app/schema/page.tsx +0 -1001
  195. package/website/app/sitemap.ts +0 -56
  196. package/website/app/specification/page.tsx +0 -287
  197. package/website/components/InstallCommand.tsx +0 -96
  198. package/website/components/Logo.tsx +0 -97
  199. package/website/components/StructuredData.tsx +0 -65
  200. package/website/components/docs/DocsSearch.tsx +0 -104
  201. package/website/components/docs/DocsSidebar.tsx +0 -155
  202. package/website/components/docs/MarkdownContent.tsx +0 -401
  203. package/website/components/docs/VersionSelector.tsx +0 -105
  204. package/website/components/examples/ExamplesViewer.tsx +0 -293
  205. package/website/components/layout/Footer.tsx +0 -116
  206. package/website/components/layout/Header.tsx +0 -172
  207. package/website/components/schema/SchemaComponentsAccordion.tsx +0 -84
  208. package/website/components/schema/SchemaExplorer.tsx +0 -213
  209. package/website/components/ui/Badge.tsx +0 -82
  210. package/website/components/ui/Button.tsx +0 -116
  211. package/website/components/ui/Card.tsx +0 -167
  212. package/website/components/ui/Checkbox.tsx +0 -141
  213. package/website/components/ui/Input.tsx +0 -169
  214. package/website/components/ui/Radio.tsx +0 -141
  215. package/website/components/ui/Select.tsx +0 -182
  216. package/website/components/ui/Tag.tsx +0 -158
  217. package/website/components/ui/Textarea.tsx +0 -195
  218. package/website/components/ui/index.ts +0 -11
  219. package/website/content/blog/OpenAPI-AI-Agents-Standard.md +0 -285
  220. package/website/content/blog/Why-Formal-Standards-Matter-Now.md +0 -198
  221. package/website/content/blog/gitlab-kubernetes-agent-ecosystem.md +0 -286
  222. package/website/content/blog/introducing-ossa-framework.md +0 -328
  223. package/website/content/blog/ossa-production-results.md +0 -279
  224. package/website/content/blog/welcome-to-ossa.md +0 -43
  225. package/website/content/blog/why-ai-agents-need-open-standard.md +0 -98
  226. package/website/content/docs/00-home.md +0 -153
  227. package/website/content/docs/adapters/openai-adapter.md +0 -693
  228. package/website/content/docs/agents/catalog.md +0 -28
  229. package/website/content/docs/aiflow-framework-integration-with-ossa.md +0 -107
  230. package/website/content/docs/api-reference/index.md +0 -38
  231. package/website/content/docs/api-reference/ossa-core-api.md +0 -634
  232. package/website/content/docs/api-reference/ossa-registry-api.md +0 -515
  233. package/website/content/docs/api-reference/unified-agent-gateway.md +0 -599
  234. package/website/content/docs/architecture/execution-flow.md +0 -335
  235. package/website/content/docs/architecture/multi-agent-systems.md +0 -737
  236. package/website/content/docs/architecture/overview.md +0 -121
  237. package/website/content/docs/architecture/stack-integration.md +0 -461
  238. package/website/content/docs/changelog.md +0 -246
  239. package/website/content/docs/cli-reference/index.md +0 -111
  240. package/website/content/docs/cli-reference/ossa-agents.md +0 -70
  241. package/website/content/docs/cli-reference/ossa-export.md +0 -56
  242. package/website/content/docs/cli-reference/ossa-generate.md +0 -66
  243. package/website/content/docs/cli-reference/ossa-gitlab-agent.md +0 -57
  244. package/website/content/docs/cli-reference/ossa-import.md +0 -56
  245. package/website/content/docs/cli-reference/ossa-init.md +0 -57
  246. package/website/content/docs/cli-reference/ossa-migrate.md +0 -62
  247. package/website/content/docs/cli-reference/ossa-run.md +0 -66
  248. package/website/content/docs/cli-reference/ossa-schema.md +0 -57
  249. package/website/content/docs/cli-reference/ossa-setup.md +0 -57
  250. package/website/content/docs/cli-reference/ossa-validate.md +0 -66
  251. package/website/content/docs/configuration/index.md +0 -97
  252. package/website/content/docs/contributing.md +0 -599
  253. package/website/content/docs/deployment/github-mirroring.md +0 -924
  254. package/website/content/docs/documentation.md +0 -100
  255. package/website/content/docs/ecosystem/framework-support.md +0 -1361
  256. package/website/content/docs/ecosystem/overview.md +0 -366
  257. package/website/content/docs/errors/index.md +0 -10
  258. package/website/content/docs/examples/aiflow-framework-integration-with-ossa.md +0 -107
  259. package/website/content/docs/examples/catalog.md +0 -300
  260. package/website/content/docs/for-audiences/students-researchers.md +0 -122
  261. package/website/content/docs/getting-started/index.md +0 -92
  262. package/website/content/docs/getting-started/installation.md +0 -155
  263. package/website/content/docs/getting-started/running-agents.md +0 -309
  264. package/website/content/docs/getting-started.md +0 -91
  265. package/website/content/docs/integrations/aiflow.md +0 -104
  266. package/website/content/docs/integrations/drupal.md +0 -105
  267. package/website/content/docs/migration-guides/agent-schema-comparison.md +0 -232
  268. package/website/content/docs/migration-guides/anthropic-mcp-to-ossa.md +0 -1750
  269. package/website/content/docs/migration-guides/crewai-to-ossa.md +0 -274
  270. package/website/content/docs/migration-guides/drupal-eca-to-ossa.md +0 -2017
  271. package/website/content/docs/migration-guides/general-agent-schema.yml +0 -247
  272. package/website/content/docs/migration-guides/index.md +0 -133
  273. package/website/content/docs/migration-guides/langchain-to-ossa.md +0 -1714
  274. package/website/content/docs/migration-guides/langflow-to-ossa.md +0 -2075
  275. package/website/content/docs/migration-guides/migration-manifest.json +0 -64
  276. package/website/content/docs/migration-guides/openai-to-ossa.md +0 -1202
  277. package/website/content/docs/openapi-extensions/examples.md +0 -550
  278. package/website/content/docs/openapi-extensions/index.md +0 -551
  279. package/website/content/docs/openapi-extensions/operation-extensions.md +0 -457
  280. package/website/content/docs/openapi-extensions/root-extensions.md +0 -410
  281. package/website/content/docs/ossa-compliant-badge.md +0 -251
  282. package/website/content/docs/pre-release/index.md +0 -175
  283. package/website/content/docs/quick-reference.md +0 -17
  284. package/website/content/docs/readme.md +0 -35
  285. package/website/content/docs/releases/v0.2.6.md +0 -99
  286. package/website/content/docs/schema-reference/agent-capabilities.md +0 -50
  287. package/website/content/docs/schema-reference/agent-id.md +0 -52
  288. package/website/content/docs/schema-reference/agent-name.md +0 -50
  289. package/website/content/docs/schema-reference/agent-role.md +0 -54
  290. package/website/content/docs/schema-reference/agent-spec.md +0 -406
  291. package/website/content/docs/schema-reference/agent-version.md +0 -50
  292. package/website/content/docs/schema-reference/autonomy.md +0 -568
  293. package/website/content/docs/schema-reference/constraints.md +0 -543
  294. package/website/content/docs/schema-reference/index.md +0 -45
  295. package/website/content/docs/schema-reference/llm-config.md +0 -445
  296. package/website/content/docs/schema-reference/observability.md +0 -654
  297. package/website/content/docs/schema-reference/ossa-manifest.md +0 -309
  298. package/website/content/docs/schema-reference/taxonomy.md +0 -509
  299. package/website/content/docs/schema-reference/tools.md +0 -628
  300. package/website/content/docs/templates/blog-post.md +0 -43
  301. package/website/content/docs/types-reference/index.md +0 -105
  302. package/website/content/docs/use-cases/00-index.md +0 -395
  303. package/website/content/docs/use-cases/cicd-code-review.md +0 -1236
  304. package/website/content/docs/use-cases/customer-support.md +0 -1234
  305. package/website/content/docs/use-cases/enterprise-compliance.md +0 -1208
  306. package/website/content/docs/use-cases/research-multi-agent.md +0 -1161
  307. package/website/content/docs/versioning.md +0 -288
  308. package/website/dev.sh +0 -53
  309. package/website/docker-compose.dev.yml +0 -36
  310. package/website/lib/version.ts +0 -35
  311. package/website/lib/versions.json +0 -103
  312. package/website/next.config.ts +0 -18
  313. package/website/nginx.conf +0 -32
  314. package/website/package-lock.json +0 -9679
  315. package/website/package.json +0 -59
  316. package/website/postcss.config.mjs +0 -9
  317. package/website/scripts/fetch-versions.js +0 -166
  318. package/website/scripts/generate-examples-index.js +0 -163
  319. package/website/scripts/merge-docs-to-wiki.ts +0 -207
  320. package/website/scripts/sync-version.js +0 -72
  321. package/website/scripts/sync-wiki.ts +0 -322
  322. package/website/scripts/upload-wiki.ts +0 -199
  323. package/website/styles/_spacing.scss +0 -453
  324. package/website/styles/_tokens.scss +0 -245
  325. package/website/styles/_typography.scss +0 -361
  326. package/website/styles/_variables.scss +0 -287
  327. package/website/tailwind.config.ts +0 -170
@@ -1,1236 +0,0 @@
1
- # CI/CD Automated Code Review Agent
2
-
3
- ## Problem Statement
4
-
5
- Modern development teams face code review bottlenecks:
6
- - **Slow PR reviews**: Manual reviews take 1-3 days, blocking deployments
7
- - **Inconsistent quality**: Different reviewers apply different standards
8
- - **Missed issues**: Humans miss common bugs, security flaws, and style violations
9
- - **Context switching**: Developers interrupted for trivial review comments
10
- - **No 24/7 coverage**: PRs submitted outside business hours wait until next day
11
-
12
- **Solution**: An OSSA-powered CI/CD agent that automatically reviews pull requests, runs linters, executes tests, checks security vulnerabilities, and provides actionable feedback in minutes—not days.
13
-
14
- ## Architecture Overview
15
-
16
- ```mermaid
17
- graph TB
18
- subgraph "CI/CD Pipeline"
19
- PR[Pull Request Created]
20
- Webhook[Git Webhook]
21
- Agent[OSSA Code Review Agent]
22
- end
23
-
24
- subgraph "Analysis Tools"
25
- Lint[ESLint/Prettier]
26
- Test[Jest/Pytest]
27
- Security[Snyk/Trivy]
28
- Coverage[Coverage Report]
29
- Complexity[Cyclomatic Complexity]
30
- end
31
-
32
- subgraph "AI Analysis"
33
- LLM[GPT-4/Claude]
34
- Patterns[Anti-Pattern Detection]
35
- Suggestions[Improvement Suggestions]
36
- Learning[Historical PR Analysis]
37
- end
38
-
39
- subgraph "Outputs"
40
- Comments[Inline PR Comments]
41
- Status[CI Status Checks]
42
- Report[Review Summary]
43
- Metrics[Code Quality Metrics]
44
- end
45
-
46
- PR --> Webhook
47
- Webhook --> Agent
48
-
49
- Agent --> Lint
50
- Agent --> Test
51
- Agent --> Security
52
- Agent --> Coverage
53
- Agent --> Complexity
54
-
55
- Agent --> LLM
56
- LLM --> Patterns
57
- LLM --> Suggestions
58
- LLM --> Learning
59
-
60
- Agent --> Comments
61
- Agent --> Status
62
- Agent --> Report
63
- Agent --> Metrics
64
-
65
- Learning -.->|Feedback Loop| LLM
66
-
67
- style Agent fill:#e1f5ff
68
- style LLM fill:#ffe1f5
69
- style Comments fill:#e1ffe1
70
- style Security fill:#ffe1e1
71
- ```
72
-
73
- ## OSSA Manifest
74
-
75
- ```yaml
76
- apiVersion: ossa/v0.2.x
77
- kind: Agent
78
- metadata:
79
- name: cicd-code-reviewer
80
- namespace: ci-cd
81
- labels:
82
- app: code-review
83
- tier: automation
84
- integration: github-gitlab
85
- annotations:
86
- cicd.ossa.io/triggers: "pull_request,merge_request"
87
- cicd.ossa.io/languages: "typescript,python,go,rust,java"
88
- cost.ossa.io/budget-monthly: "200.00"
89
-
90
- spec:
91
- type: worker
92
- description: |
93
- Automated code review agent for CI/CD pipelines.
94
- Performs linting, testing, security scanning, and AI-powered
95
- code analysis on every pull request.
96
-
97
- runtime:
98
- type: docker
99
- image: registry.example.com/agents/code-reviewer:3.0.0
100
- command: ["/app/reviewer"]
101
- args:
102
- - "--mode=pr-review"
103
- - "--auto-comment=true"
104
- - "--auto-approve=false"
105
- resources:
106
- limits:
107
- cpu: "4000m"
108
- memory: "8Gi"
109
- requests:
110
- cpu: "1000m"
111
- memory: "2Gi"
112
- env:
113
- - name: LOG_LEVEL
114
- value: "info"
115
- - name: SUPPORTED_LANGUAGES
116
- value: "typescript,python,go,rust,java"
117
- - name: AI_MODEL
118
- value: "gpt-4-turbo-preview"
119
- - name: MAX_PR_SIZE_FILES
120
- value: "100"
121
- - name: MAX_PR_SIZE_LINES
122
- value: "5000"
123
- - name: ENABLE_AUTO_FIX
124
- value: "true"
125
-
126
- capabilities:
127
- - name: review_pull_request
128
- description: |
129
- Comprehensive pull request review including linting, testing,
130
- security scanning, and AI-powered code analysis.
131
- input_schema:
132
- type: object
133
- required: [repository, pr_number, base_branch, head_branch]
134
- properties:
135
- repository:
136
- type: string
137
- description: "Repository URL or identifier"
138
- pr_number:
139
- type: integer
140
- description: "Pull request number"
141
- base_branch:
142
- type: string
143
- description: "Target branch (e.g., main)"
144
- head_branch:
145
- type: string
146
- description: "Source branch (e.g., feature/new-api)"
147
- reviewers:
148
- type: array
149
- items:
150
- type: string
151
- description: "GitHub/GitLab usernames for notification"
152
- auto_fix:
153
- type: boolean
154
- default: false
155
- description: "Automatically commit fixes for trivial issues"
156
- output_schema:
157
- type: object
158
- required: [review_id, status, summary]
159
- properties:
160
- review_id:
161
- type: string
162
- format: uuid
163
- status:
164
- type: string
165
- enum: [approved, changes_requested, commented, error]
166
- summary:
167
- type: object
168
- required: [total_files, total_issues, critical_issues]
169
- properties:
170
- total_files:
171
- type: integer
172
- total_lines_added:
173
- type: integer
174
- total_lines_deleted:
175
- type: integer
176
- total_issues:
177
- type: integer
178
- critical_issues:
179
- type: integer
180
- high_issues:
181
- type: integer
182
- medium_issues:
183
- type: integer
184
- low_issues:
185
- type: integer
186
- issues:
187
- type: array
188
- items:
189
- type: object
190
- required: [file, line, severity, category, message]
191
- properties:
192
- file:
193
- type: string
194
- line:
195
- type: integer
196
- severity:
197
- type: string
198
- enum: [critical, high, medium, low, info]
199
- category:
200
- type: string
201
- enum: [bug, security, style, performance, best-practice, documentation]
202
- message:
203
- type: string
204
- suggestion:
205
- type: string
206
- auto_fixable:
207
- type: boolean
208
- test_results:
209
- type: object
210
- properties:
211
- passed:
212
- type: boolean
213
- total_tests:
214
- type: integer
215
- failed_tests:
216
- type: integer
217
- coverage_percent:
218
- type: number
219
- security_scan:
220
- type: object
221
- properties:
222
- vulnerabilities_found:
223
- type: integer
224
- critical_vulnerabilities:
225
- type: integer
226
- dependencies_scanned:
227
- type: integer
228
- ai_analysis:
229
- type: object
230
- properties:
231
- code_quality_score:
232
- type: number
233
- minimum: 0
234
- maximum: 100
235
- maintainability_index:
236
- type: number
237
- cognitive_complexity:
238
- type: number
239
- suggestions:
240
- type: array
241
- items:
242
- type: string
243
- timestamp:
244
- type: string
245
- format: date-time
246
-
247
- - name: run_linters
248
- description: |
249
- Run configured linters (ESLint, Prettier, Black, Pylint, gofmt, etc.)
250
- on changed files.
251
- input_schema:
252
- type: object
253
- required: [files, language]
254
- properties:
255
- files:
256
- type: array
257
- items:
258
- type: string
259
- language:
260
- type: string
261
- enum: [typescript, javascript, python, go, rust, java]
262
- fix:
263
- type: boolean
264
- default: false
265
- output_schema:
266
- type: object
267
- properties:
268
- issues:
269
- type: array
270
- items:
271
- type: object
272
- properties:
273
- file: {type: string}
274
- line: {type: integer}
275
- column: {type: integer}
276
- rule: {type: string}
277
- message: {type: string}
278
- severity: {type: string}
279
- fixed:
280
- type: boolean
281
- fixes_applied:
282
- type: array
283
- items:
284
- type: string
285
-
286
- - name: run_tests
287
- description: |
288
- Execute test suite for changed code and collect coverage metrics.
289
- input_schema:
290
- type: object
291
- required: [test_command, working_directory]
292
- properties:
293
- test_command:
294
- type: string
295
- description: "e.g., npm test, pytest, go test"
296
- working_directory:
297
- type: string
298
- coverage:
299
- type: boolean
300
- default: true
301
- timeout_seconds:
302
- type: integer
303
- default: 600
304
- output_schema:
305
- type: object
306
- properties:
307
- passed:
308
- type: boolean
309
- total:
310
- type: integer
311
- failed:
312
- type: integer
313
- skipped:
314
- type: integer
315
- duration_seconds:
316
- type: number
317
- coverage_percent:
318
- type: number
319
- failed_tests:
320
- type: array
321
- items:
322
- type: object
323
- properties:
324
- name: {type: string}
325
- error: {type: string}
326
-
327
- - name: security_scan
328
- description: |
329
- Scan for security vulnerabilities in code and dependencies.
330
- input_schema:
331
- type: object
332
- required: [directory]
333
- properties:
334
- directory:
335
- type: string
336
- scan_dependencies:
337
- type: boolean
338
- default: true
339
- scan_code:
340
- type: boolean
341
- default: true
342
- severity_threshold:
343
- type: string
344
- enum: [critical, high, medium, low]
345
- default: medium
346
- output_schema:
347
- type: object
348
- properties:
349
- vulnerabilities:
350
- type: array
351
- items:
352
- type: object
353
- properties:
354
- id: {type: string}
355
- title: {type: string}
356
- severity: {type: string}
357
- package: {type: string}
358
- version: {type: string}
359
- fixed_in: {type: string}
360
- description: {type: string}
361
- total:
362
- type: integer
363
- by_severity:
364
- type: object
365
- properties:
366
- critical: {type: integer}
367
- high: {type: integer}
368
- medium: {type: integer}
369
- low: {type: integer}
370
-
371
- - name: analyze_complexity
372
- description: |
373
- Analyze code complexity metrics (cyclomatic complexity,
374
- cognitive complexity, maintainability index).
375
- input_schema:
376
- type: object
377
- required: [files]
378
- properties:
379
- files:
380
- type: array
381
- items:
382
- type: string
383
- output_schema:
384
- type: object
385
- properties:
386
- files:
387
- type: array
388
- items:
389
- type: object
390
- properties:
391
- file: {type: string}
392
- cyclomatic_complexity: {type: number}
393
- cognitive_complexity: {type: number}
394
- maintainability_index: {type: number}
395
- functions:
396
- type: array
397
- items:
398
- type: object
399
- properties:
400
- name: {type: string}
401
- complexity: {type: number}
402
- lines: {type: integer}
403
-
404
- policies:
405
- quality_gates:
406
- min_test_coverage: 80
407
- max_cyclomatic_complexity: 10
408
- max_cognitive_complexity: 15
409
- max_function_length: 50
410
- max_file_length: 500
411
- block_on_critical_security: true
412
- block_on_failed_tests: true
413
-
414
- auto_approval:
415
- enabled: false # Require human approval
416
- conditions:
417
- - all_tests_pass: true
418
- - no_security_issues: true
419
- - no_linting_errors: true
420
- - coverage_maintained: true
421
- - max_files_changed: 5
422
- - max_lines_changed: 200
423
-
424
- auto_fix:
425
- enabled: true
426
- allowed_fixes:
427
- - formatting
428
- - import_sorting
429
- - unused_imports
430
- - trailing_whitespace
431
- require_approval_for:
432
- - logic_changes
433
- - refactoring
434
-
435
- cost_management:
436
- budget:
437
- monthly_limit_usd: 200.00
438
- per_pr_limit_usd: 2.00
439
- alert_threshold: 0.85
440
- optimization:
441
- cache_dependencies: true
442
- skip_unchanged_files: true
443
- parallel_analysis: true
444
-
445
- integration:
446
- protocol: webhook
447
- api_version: v1
448
-
449
- webhooks:
450
- github:
451
- events:
452
- - pull_request.opened
453
- - pull_request.synchronize
454
- - pull_request.reopened
455
- url: https://code-reviewer.example.com/webhooks/github
456
- secret_env: GITHUB_WEBHOOK_SECRET
457
-
458
- gitlab:
459
- events:
460
- - merge_request.open
461
- - merge_request.update
462
- url: https://code-reviewer.example.com/webhooks/gitlab
463
- secret_env: GITLAB_WEBHOOK_SECRET
464
-
465
- authentication:
466
- github:
467
- type: token
468
- token_env: GITHUB_TOKEN
469
- permissions:
470
- - read:repo
471
- - write:discussions
472
- - read:packages
473
-
474
- gitlab:
475
- type: token
476
- token_env: GITLAB_TOKEN
477
- permissions:
478
- - read_repository
479
- - write_merge_request
480
-
481
- endpoints:
482
- review:
483
- path: /v1/review/pull-request
484
- method: POST
485
- rate_limit: 1000/hour
486
-
487
- status:
488
- path: /v1/review/{review_id}/status
489
- method: GET
490
- rate_limit: 5000/hour
491
-
492
- monitoring:
493
- health_check:
494
- endpoint: http://localhost:8080/health
495
- interval_seconds: 15
496
- timeout_seconds: 5
497
-
498
- metrics:
499
- enabled: true
500
- exporter: prometheus
501
- port: 9090
502
- custom_metrics:
503
- - prs_reviewed_total
504
- - review_duration_seconds
505
- - issues_found_total
506
- - auto_fixes_applied_total
507
- - tests_run_total
508
- - security_vulnerabilities_found
509
-
510
- traces:
511
- enabled: true
512
- exporter: jaeger
513
- sample_rate: 0.2
514
-
515
- logs:
516
- level: info
517
- format: json
518
- output: stdout
519
-
520
- metadata:
521
- version: 3.0.0
522
- author:
523
- name: Engineering Team
524
- email: eng@example.com
525
- organization: Example Corp
526
- license: MIT
527
- tags:
528
- - ci-cd
529
- - code-review
530
- - automation
531
- - testing
532
- - security
533
- keywords:
534
- - pull request review
535
- - automated testing
536
- - code quality
537
- - security scanning
538
- documentation_url: https://docs.example.com/agents/code-reviewer
539
- source_repository: https://github.com/example/code-reviewer-agent
540
- ```
541
-
542
- ## Implementation (Python)
543
-
544
- ```python
545
- """
546
- CI/CD Automated Code Review Agent
547
-
548
- Production-ready OSSA agent for automated pull request reviews
549
- with linting, testing, security scanning, and AI analysis.
550
- """
551
-
552
- import asyncio
553
- import json
554
- import os
555
- from dataclasses import dataclass, asdict
556
- from datetime import datetime
557
- from typing import List, Dict, Optional, Any
558
- from enum import Enum
559
-
560
- from ossa_runtime import Agent, OSSARuntime
561
- from github import Github
562
- from gitlab import Gitlab
563
- import openai
564
-
565
-
566
- class Severity(Enum):
567
- CRITICAL = "critical"
568
- HIGH = "high"
569
- MEDIUM = "medium"
570
- LOW = "low"
571
- INFO = "info"
572
-
573
-
574
- class Category(Enum):
575
- BUG = "bug"
576
- SECURITY = "security"
577
- STYLE = "style"
578
- PERFORMANCE = "performance"
579
- BEST_PRACTICE = "best-practice"
580
- DOCUMENTATION = "documentation"
581
-
582
-
583
- @dataclass
584
- class Issue:
585
- file: str
586
- line: int
587
- severity: Severity
588
- category: Category
589
- message: str
590
- suggestion: Optional[str] = None
591
- auto_fixable: bool = False
592
-
593
-
594
- @dataclass
595
- class ReviewSummary:
596
- total_files: int
597
- total_lines_added: int
598
- total_lines_deleted: int
599
- total_issues: int
600
- critical_issues: int
601
- high_issues: int
602
- medium_issues: int
603
- low_issues: int
604
-
605
-
606
- @dataclass
607
- class TestResults:
608
- passed: bool
609
- total_tests: int
610
- failed_tests: int
611
- coverage_percent: float
612
-
613
-
614
- @dataclass
615
- class SecurityScan:
616
- vulnerabilities_found: int
617
- critical_vulnerabilities: int
618
- dependencies_scanned: int
619
-
620
-
621
- @dataclass
622
- class AIAnalysis:
623
- code_quality_score: float
624
- maintainability_index: float
625
- cognitive_complexity: float
626
- suggestions: List[str]
627
-
628
-
629
- @dataclass
630
- class ReviewResult:
631
- review_id: str
632
- status: str # approved, changes_requested, commented, error
633
- summary: ReviewSummary
634
- issues: List[Issue]
635
- test_results: Optional[TestResults]
636
- security_scan: Optional[SecurityScan]
637
- ai_analysis: Optional[AIAnalysis]
638
- timestamp: datetime
639
-
640
-
641
- class CodeReviewerAgent(Agent):
642
- """
643
- OSSA agent for automated code review in CI/CD pipelines.
644
- """
645
-
646
- def __init__(self, runtime: OSSARuntime):
647
- super().__init__(runtime)
648
-
649
- self.github_client = None
650
- self.gitlab_client = None
651
- self.openai_client = None
652
-
653
- self._initialize_clients()
654
-
655
- def _initialize_clients(self):
656
- """Initialize Git platform and AI clients."""
657
- github_token = os.getenv("GITHUB_TOKEN")
658
- if github_token:
659
- self.github_client = Github(github_token)
660
-
661
- gitlab_token = os.getenv("GITLAB_TOKEN")
662
- if gitlab_token:
663
- self.gitlab_client = Gitlab("https://gitlab.com", private_token=gitlab_token)
664
-
665
- openai_api_key = os.getenv("OPENAI_API_KEY")
666
- if openai_api_key:
667
- openai.api_key = openai_api_key
668
- self.openai_client = openai
669
-
670
- async def review_pull_request(
671
- self,
672
- repository: str,
673
- pr_number: int,
674
- base_branch: str,
675
- head_branch: str,
676
- reviewers: Optional[List[str]] = None,
677
- auto_fix: bool = False
678
- ) -> ReviewResult:
679
- """
680
- Comprehensive pull request review.
681
-
682
- Args:
683
- repository: Repository URL or identifier
684
- pr_number: Pull request number
685
- base_branch: Target branch
686
- head_branch: Source branch
687
- reviewers: List of reviewers to notify
688
- auto_fix: Automatically commit fixes for trivial issues
689
-
690
- Returns:
691
- ReviewResult with comprehensive analysis
692
- """
693
- review_id = self._generate_review_id()
694
-
695
- self.logger.info(f"Starting review {review_id} for PR #{pr_number}")
696
-
697
- try:
698
- # Fetch PR details
699
- pr = await self._fetch_pull_request(repository, pr_number)
700
-
701
- # Get changed files
702
- changed_files = await self._get_changed_files(pr)
703
-
704
- if len(changed_files) > int(os.getenv("MAX_PR_SIZE_FILES", "100")):
705
- return ReviewResult(
706
- review_id=review_id,
707
- status="error",
708
- summary=ReviewSummary(0, 0, 0, 0, 0, 0, 0, 0),
709
- issues=[],
710
- test_results=None,
711
- security_scan=None,
712
- ai_analysis=None,
713
- timestamp=datetime.utcnow()
714
- )
715
-
716
- # Run all checks in parallel
717
- results = await asyncio.gather(
718
- self._run_linters(changed_files),
719
- self._run_tests(repository),
720
- self._security_scan(repository),
721
- self._analyze_complexity(changed_files),
722
- self._ai_analysis(changed_files, pr),
723
- return_exceptions=True
724
- )
725
-
726
- linter_issues = results[0] if not isinstance(results[0], Exception) else []
727
- test_results = results[1] if not isinstance(results[1], Exception) else None
728
- security_scan = results[2] if not isinstance(results[2], Exception) else None
729
- complexity_issues = results[3] if not isinstance(results[3], Exception) else []
730
- ai_analysis = results[4] if not isinstance(results[4], Exception) else None
731
-
732
- # Combine all issues
733
- all_issues = linter_issues + complexity_issues
734
-
735
- # Generate summary
736
- summary = self._generate_summary(changed_files, all_issues)
737
-
738
- # Determine status
739
- status = self._determine_status(summary, test_results, security_scan)
740
-
741
- # Post review comments
742
- await self._post_review_comments(pr, all_issues, status)
743
-
744
- # Auto-fix if enabled and appropriate
745
- if auto_fix and status == "commented":
746
- await self._apply_auto_fixes(pr, all_issues)
747
-
748
- # Notify reviewers
749
- if reviewers:
750
- await self._notify_reviewers(pr, reviewers)
751
-
752
- result = ReviewResult(
753
- review_id=review_id,
754
- status=status,
755
- summary=summary,
756
- issues=all_issues,
757
- test_results=test_results,
758
- security_scan=security_scan,
759
- ai_analysis=ai_analysis,
760
- timestamp=datetime.utcnow()
761
- )
762
-
763
- self.logger.info(f"Review {review_id} completed with status: {status}")
764
-
765
- # Record metrics
766
- self.metrics.increment("prs_reviewed_total", {"status": status})
767
- self.metrics.gauge("issues_found_total", summary.total_issues)
768
-
769
- return result
770
-
771
- except Exception as e:
772
- self.logger.error(f"Review {review_id} failed: {str(e)}")
773
- self.metrics.increment("prs_reviewed_total", {"status": "error"})
774
- raise
775
-
776
- async def _run_linters(self, files: List[str]) -> List[Issue]:
777
- """Run linters on changed files."""
778
- issues = []
779
-
780
- # Group files by language
781
- files_by_lang = self._group_files_by_language(files)
782
-
783
- # Run appropriate linter for each language
784
- for lang, lang_files in files_by_lang.items():
785
- if lang == "typescript" or lang == "javascript":
786
- issues.extend(await self._run_eslint(lang_files))
787
- elif lang == "python":
788
- issues.extend(await self._run_pylint(lang_files))
789
- elif lang == "go":
790
- issues.extend(await self._run_golint(lang_files))
791
- # Add more languages as needed
792
-
793
- return issues
794
-
795
- async def _run_eslint(self, files: List[str]) -> List[Issue]:
796
- """Run ESLint on TypeScript/JavaScript files."""
797
- issues = []
798
-
799
- # Execute ESLint
800
- cmd = f"npx eslint --format json {' '.join(files)}"
801
- result = await self._execute_command(cmd)
802
-
803
- if result["returncode"] != 0:
804
- # Parse ESLint JSON output
805
- eslint_results = json.loads(result["stdout"])
806
-
807
- for file_result in eslint_results:
808
- for message in file_result.get("messages", []):
809
- issues.append(Issue(
810
- file=file_result["filePath"],
811
- line=message["line"],
812
- severity=self._map_severity(message["severity"]),
813
- category=Category.STYLE,
814
- message=f"{message['ruleId']}: {message['message']}",
815
- suggestion=message.get("fix"),
816
- auto_fixable=message.get("fix") is not None
817
- ))
818
-
819
- return issues
820
-
821
- async def _run_tests(self, repository: str) -> TestResults:
822
- """Execute test suite."""
823
- self.logger.info("Running tests...")
824
-
825
- # Detect test framework
826
- test_command = self._detect_test_command(repository)
827
-
828
- # Run tests with coverage
829
- result = await self._execute_command(f"{test_command} --coverage")
830
-
831
- # Parse test results
832
- # (Implementation depends on test framework)
833
-
834
- return TestResults(
835
- passed=result["returncode"] == 0,
836
- total_tests=100, # Parse from output
837
- failed_tests=0,
838
- coverage_percent=85.5
839
- )
840
-
841
- async def _security_scan(self, repository: str) -> SecurityScan:
842
- """Scan for security vulnerabilities."""
843
- self.logger.info("Running security scan...")
844
-
845
- # Run Snyk or Trivy
846
- cmd = "snyk test --json"
847
- result = await self._execute_command(cmd)
848
-
849
- if result["stdout"]:
850
- scan_results = json.loads(result["stdout"])
851
-
852
- return SecurityScan(
853
- vulnerabilities_found=len(scan_results.get("vulnerabilities", [])),
854
- critical_vulnerabilities=len([
855
- v for v in scan_results.get("vulnerabilities", [])
856
- if v["severity"] == "critical"
857
- ]),
858
- dependencies_scanned=len(scan_results.get("dependencies", []))
859
- )
860
-
861
- return SecurityScan(0, 0, 0)
862
-
863
- async def _analyze_complexity(self, files: List[str]) -> List[Issue]:
864
- """Analyze code complexity."""
865
- issues = []
866
-
867
- # Run complexity analysis tools
868
- # (radon for Python, lizard for multi-language)
869
-
870
- for file in files:
871
- complexity = await self._calculate_complexity(file)
872
-
873
- if complexity > 10: # Threshold
874
- issues.append(Issue(
875
- file=file,
876
- line=1,
877
- severity=Severity.MEDIUM,
878
- category=Category.BEST_PRACTICE,
879
- message=f"High cyclomatic complexity: {complexity}",
880
- suggestion="Consider breaking down this function into smaller units"
881
- ))
882
-
883
- return issues
884
-
885
- async def _ai_analysis(self, files: List[str], pr: Any) -> AIAnalysis:
886
- """AI-powered code analysis using GPT-4."""
887
- if not self.openai_client:
888
- return None
889
-
890
- # Get PR diff
891
- diff = await self._get_pr_diff(pr)
892
-
893
- # Prepare prompt
894
- prompt = f"""
895
- Review the following code changes and provide:
896
- 1. Code quality score (0-100)
897
- 2. Maintainability concerns
898
- 3. Potential bugs or issues
899
- 4. Improvement suggestions
900
-
901
- Diff:
902
- {diff}
903
- """
904
-
905
- response = await self.openai_client.ChatCompletion.acreate(
906
- model="gpt-4-turbo-preview",
907
- messages=[
908
- {"role": "system", "content": "You are an expert code reviewer."},
909
- {"role": "user", "content": prompt}
910
- ]
911
- )
912
-
913
- analysis_text = response.choices[0].message.content
914
-
915
- # Parse AI response (simplified)
916
- return AIAnalysis(
917
- code_quality_score=85.0,
918
- maintainability_index=75.0,
919
- cognitive_complexity=8.0,
920
- suggestions=self._parse_ai_suggestions(analysis_text)
921
- )
922
-
923
- def _generate_summary(self, files: List[str], issues: List[Issue]) -> ReviewSummary:
924
- """Generate review summary."""
925
- return ReviewSummary(
926
- total_files=len(files),
927
- total_lines_added=0, # Calculate from diff
928
- total_lines_deleted=0,
929
- total_issues=len(issues),
930
- critical_issues=len([i for i in issues if i.severity == Severity.CRITICAL]),
931
- high_issues=len([i for i in issues if i.severity == Severity.HIGH]),
932
- medium_issues=len([i for i in issues if i.severity == Severity.MEDIUM]),
933
- low_issues=len([i for i in issues if i.severity == Severity.LOW])
934
- )
935
-
936
- def _determine_status(
937
- self,
938
- summary: ReviewSummary,
939
- test_results: Optional[TestResults],
940
- security_scan: Optional[SecurityScan]
941
- ) -> str:
942
- """Determine review status."""
943
- # Block on critical security issues
944
- if security_scan and security_scan.critical_vulnerabilities > 0:
945
- return "changes_requested"
946
-
947
- # Block on failed tests
948
- if test_results and not test_results.passed:
949
- return "changes_requested"
950
-
951
- # Request changes for high severity issues
952
- if summary.critical_issues > 0 or summary.high_issues > 5:
953
- return "changes_requested"
954
-
955
- # Comment on medium/low issues
956
- if summary.total_issues > 0:
957
- return "commented"
958
-
959
- # Approve (if auto-approval enabled)
960
- return "approved"
961
-
962
- async def _post_review_comments(self, pr: Any, issues: List[Issue], status: str):
963
- """Post review comments to PR."""
964
- # Group issues by file
965
- issues_by_file = {}
966
- for issue in issues:
967
- if issue.file not in issues_by_file:
968
- issues_by_file[issue.file] = []
969
- issues_by_file[issue.file].append(issue)
970
-
971
- # Post inline comments
972
- for file, file_issues in issues_by_file.items():
973
- for issue in file_issues:
974
- comment = self._format_issue_comment(issue)
975
- await pr.create_review_comment(
976
- body=comment,
977
- path=file,
978
- line=issue.line
979
- )
980
-
981
- def _format_issue_comment(self, issue: Issue) -> str:
982
- """Format issue as PR comment."""
983
- severity_emoji = {
984
- Severity.CRITICAL: "🔴",
985
- Severity.HIGH: "🟠",
986
- Severity.MEDIUM: "🟡",
987
- Severity.LOW: "🟢",
988
- Severity.INFO: "ℹ️"
989
- }
990
-
991
- comment = f"{severity_emoji[issue.severity]} **{issue.severity.value.upper()}** - {issue.category.value}\n\n"
992
- comment += f"{issue.message}\n\n"
993
-
994
- if issue.suggestion:
995
- comment += f"**Suggestion:** {issue.suggestion}\n\n"
996
-
997
- if issue.auto_fixable:
998
- comment += "✨ This issue can be auto-fixed.\n"
999
-
1000
- return comment
1001
-
1002
- # Helper methods
1003
- def _generate_review_id(self) -> str:
1004
- """Generate unique review ID."""
1005
- import uuid
1006
- return str(uuid.uuid4())
1007
-
1008
- async def _fetch_pull_request(self, repository: str, pr_number: int) -> Any:
1009
- """Fetch PR from GitHub/GitLab."""
1010
- if self.github_client:
1011
- repo = self.github_client.get_repo(repository)
1012
- return repo.get_pull(pr_number)
1013
- # Add GitLab support
1014
- return None
1015
-
1016
- async def _get_changed_files(self, pr: Any) -> List[str]:
1017
- """Get list of changed files in PR."""
1018
- return [f.filename for f in pr.get_files()]
1019
-
1020
- def _group_files_by_language(self, files: List[str]) -> Dict[str, List[str]]:
1021
- """Group files by programming language."""
1022
- groups = {}
1023
- for file in files:
1024
- ext = file.split('.')[-1]
1025
- lang = self._extension_to_language(ext)
1026
- if lang not in groups:
1027
- groups[lang] = []
1028
- groups[lang].append(file)
1029
- return groups
1030
-
1031
- def _extension_to_language(self, ext: str) -> str:
1032
- """Map file extension to language."""
1033
- mapping = {
1034
- 'ts': 'typescript',
1035
- 'tsx': 'typescript',
1036
- 'js': 'javascript',
1037
- 'jsx': 'javascript',
1038
- 'py': 'python',
1039
- 'go': 'go',
1040
- 'rs': 'rust',
1041
- 'java': 'java'
1042
- }
1043
- return mapping.get(ext, 'unknown')
1044
-
1045
- def _map_severity(self, eslint_severity: int) -> Severity:
1046
- """Map ESLint severity to OSSA severity."""
1047
- return Severity.HIGH if eslint_severity == 2 else Severity.MEDIUM
1048
-
1049
- def _detect_test_command(self, repository: str) -> str:
1050
- """Detect appropriate test command."""
1051
- # Check package.json, pytest.ini, go.mod, etc.
1052
- return "npm test" # Default
1053
-
1054
- async def _execute_command(self, cmd: str) -> Dict[str, Any]:
1055
- """Execute shell command."""
1056
- process = await asyncio.create_subprocess_shell(
1057
- cmd,
1058
- stdout=asyncio.subprocess.PIPE,
1059
- stderr=asyncio.subprocess.PIPE
1060
- )
1061
- stdout, stderr = await process.communicate()
1062
- return {
1063
- "returncode": process.returncode,
1064
- "stdout": stdout.decode(),
1065
- "stderr": stderr.decode()
1066
- }
1067
-
1068
- async def _calculate_complexity(self, file: str) -> int:
1069
- """Calculate cyclomatic complexity."""
1070
- # Use radon, lizard, or similar tool
1071
- return 5 # Placeholder
1072
-
1073
- async def _get_pr_diff(self, pr: Any) -> str:
1074
- """Get PR diff."""
1075
- return pr.diff_url # Simplified
1076
-
1077
- def _parse_ai_suggestions(self, text: str) -> List[str]:
1078
- """Parse suggestions from AI response."""
1079
- # Parse structured output from AI
1080
- return ["Suggestion 1", "Suggestion 2"] # Placeholder
1081
-
1082
- async def _apply_auto_fixes(self, pr: Any, issues: List[Issue]):
1083
- """Apply auto-fixes for trivial issues."""
1084
- fixable_issues = [i for i in issues if i.auto_fixable]
1085
- if fixable_issues:
1086
- # Apply fixes and commit
1087
- pass
1088
-
1089
- async def _notify_reviewers(self, pr: Any, reviewers: List[str]):
1090
- """Notify human reviewers."""
1091
- for reviewer in reviewers:
1092
- await pr.create_review_request(reviewers=[reviewer])
1093
-
1094
-
1095
- # Entry point
1096
- async def main():
1097
- runtime = OSSARuntime(manifest_path="/etc/ossa/manifest.yaml")
1098
- agent = CodeReviewerAgent(runtime)
1099
- await agent.start()
1100
-
1101
-
1102
- if __name__ == "__main__":
1103
- asyncio.run(main())
1104
- ```
1105
-
1106
- ## Deployment Instructions
1107
-
1108
- ### Step 1: GitHub Actions Integration
1109
-
1110
- ```yaml
1111
- # .github/workflows/code-review.yml
1112
- name: OSSA Code Review
1113
-
1114
- on:
1115
- pull_request:
1116
- types: [opened, synchronize, reopened]
1117
-
1118
- jobs:
1119
- code-review:
1120
- runs-on: ubuntu-latest
1121
-
1122
- steps:
1123
- - name: Checkout code
1124
- uses: actions/checkout@v3
1125
- with:
1126
- fetch-depth: 0
1127
-
1128
- - name: Run OSSA Code Reviewer
1129
- uses: docker://registry.example.com/agents/code-reviewer:3.0.0
1130
- env:
1131
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1132
- OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
1133
- with:
1134
- args: |
1135
- --repository=${{ github.repository }}
1136
- --pr-number=${{ github.event.pull_request.number }}
1137
- --base-branch=${{ github.event.pull_request.base.ref }}
1138
- --head-branch=${{ github.event.pull_request.head.ref }}
1139
- ```
1140
-
1141
- ### Step 2: GitLab CI Integration
1142
-
1143
- ```yaml
1144
- # .gitlab-ci.yml
1145
- code-review:
1146
- stage: test
1147
- image: registry.example.com/agents/code-reviewer:3.0.0
1148
- script:
1149
- - |
1150
- code-reviewer \
1151
- --repository=$CI_PROJECT_PATH \
1152
- --pr-number=$CI_MERGE_REQUEST_IID \
1153
- --base-branch=$CI_MERGE_REQUEST_TARGET_BRANCH_NAME \
1154
- --head-branch=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
1155
- only:
1156
- - merge_requests
1157
- ```
1158
-
1159
- ### Step 3: Self-Hosted Deployment
1160
-
1161
- ```bash
1162
- # Deploy as Kubernetes service
1163
- kubectl apply -f - <<EOF
1164
- apiVersion: apps/v1
1165
- kind: Deployment
1166
- metadata:
1167
- name: code-reviewer-agent
1168
- namespace: ci-cd
1169
- spec:
1170
- replicas: 3
1171
- selector:
1172
- matchLabels:
1173
- app: code-reviewer
1174
- template:
1175
- metadata:
1176
- labels:
1177
- app: code-reviewer
1178
- spec:
1179
- containers:
1180
- - name: agent
1181
- image: registry.example.com/agents/code-reviewer:3.0.0
1182
- env:
1183
- - name: GITHUB_TOKEN
1184
- valueFrom:
1185
- secretKeyRef:
1186
- name: git-tokens
1187
- key: github
1188
- - name: GITLAB_TOKEN
1189
- valueFrom:
1190
- secretKeyRef:
1191
- name: git-tokens
1192
- key: gitlab
1193
- - name: OPENAI_API_KEY
1194
- valueFrom:
1195
- secretKeyRef:
1196
- name: ai-tokens
1197
- key: openai
1198
- ports:
1199
- - containerPort: 8080
1200
- resources:
1201
- requests:
1202
- cpu: 1000m
1203
- memory: 2Gi
1204
- limits:
1205
- cpu: 4000m
1206
- memory: 8Gi
1207
- EOF
1208
- ```
1209
-
1210
- ## Cost Management
1211
-
1212
- - **Monthly budget**: $200 (configurable)
1213
- - **Per-PR limit**: $2.00
1214
- - **Optimization strategies**:
1215
- - Cache dependencies between runs
1216
- - Skip unchanged files
1217
- - Parallel analysis
1218
- - Use cheaper models for simple checks
1219
-
1220
- ## Production Checklist
1221
-
1222
- - [ ] GitHub/GitLab tokens configured with minimum required permissions
1223
- - [ ] Webhook secrets configured
1224
- - [ ] AI API keys stored securely
1225
- - [ ] Rate limiting configured
1226
- - [ ] Monitoring and alerting enabled
1227
- - [ ] Cost tracking dashboard
1228
- - [ ] Auto-fix tested in safe environment
1229
- - [ ] Quality gates configured per project
1230
- - [ ] Rollback plan tested
1231
-
1232
- ## Further Reading
1233
-
1234
- - [GitHub Actions Documentation](https://docs.github.com/actions)
1235
- - [GitLab CI Documentation](https://docs.gitlab.com/ee/ci/)
1236
- - [OSSA Runtime Documentation](https://openstandardagents.org/docs/runtime)