JNZader/ghagga

GitHub: JNZader/ghagga

结合 15 种静态分析工具与 LLM 多智能体的 AI 代码审查平台,支持记忆学习、三种部署模式和多种审查策略。

Stars: 1 | Forks: 0

GHAGGA Logo — AI-powered code review with static analysis

# GHAGGA — AI 驱动的代码审查 **多智能体代码审查器**,可在你的 Pull Request 上发布智能评论。结合 LLM 分析与多达 15 种静态分析工具,以及跨审查学习的项目记忆。 **[网站](https://jnzader.github.io/ghagga/)** · **[文档](https://jnzader.github.io/ghagga/docs/)** · **[仪表板](https://jnzader.github.io/ghagga/app/)** ## 目录 - [这是什么?](#what-is-this) - [快速开始](#quick-start) - [架构](#architecture) - [审查模式](#review-modes) - [静态分析](#static-analysis) - [Runner 架构](#runner-architecture) - [记忆系统](#memory-system) - [仪表板](#dashboard) - [安全性](#security) - [Monorepo 结构](#monorepo-structure) - [配置](#configuration) - [开发](#development) - [技术栈](#tech-stack) - [相较 v1 的变化](#what-changed-from-v1) - [许可证](#license) ## 这是什么? GHAGGA 是一个 AI 代码审查工具,它可以: 1. **接收** PR diff(通过 webhook、CLI 或 GitHub Action) 2. **扫描** 使用静态分析工具 —— 针对已知问题零 LLM token 消耗 3. **搜索** 项目记忆以查找过去的决策、模式和错误修复 4. **发送** 将 diff + 静态分析上下文 + 记忆发送给 AI 智能体 5. **发布** 在 PR 上发布结构化的审查评论,包含发现、严重程度和建议 6. **学习** 通过从审查中提取观察结果并存储以备下次使用 你需要自带 API key (BYOK)。GHAGGA 绝不会以明文形式查看或存储你的密钥 —— 它们在静态存储时使用 AES-256-GCM 加密。 ### 主要功能 | 功能 | 描述 | |---------|-------------| | **3 种审查模式** | Simple (单一 LLM), Workflow (5 个专家智能体), Consensus (多模型投票) | | **15 种静态分析工具** | Semgrep, Trivy, CPD, Gitleaks, ShellCheck, markdownlint, Lizard + 8 种自动检测工具 —— 零 token 消耗 | | **项目记忆** | 跨审查学习模式、决策和错误修复 (PostgreSQL + tsvector FTS) | | **多提供商** | 6 个提供商: GitHub Models, Anthropic, OpenAI, Google, Ollama (本地), Qwen (Alibaba)。**模式说明**: SaaS/服务器模式需要具有 `models:read` 权限的 PAT 才能使用 GitHub Models;CLI 和 GitHub Action 模式可以使用你已经控制的 GitHub token。 | | **3 种分发模式** | SaaS, GitHub Action, CLI | | **分页支持** | 完整的 GitHub API 分页支持,适用于超过 100 个文件/提交的 PR —— 无静默截断 | | **评论触发** | 在任何 PR 上输入 `ghagga review` 即可按需重新触发审查 | | **仪表板** | GitHub Pages 上的 React SPA —— 审查历史、统计、设置、记忆浏览器 | | **BYOK 安全** | AES-256-GCM 加密, HMAC-SHA256 webhook 验证, 隐私脱敏 | ## 快速开始 ### 选项 0: GitHub App (SaaS) — ⭐ 推荐 最简单的入门方式。安装 App,在仪表板中配置,即可获得审查。 1. **[安装 GHAGGA GitHub App](https://github.com/apps/ghagga-review/installations/new)** 到你的仓库 2. **[打开仪表板](https://jnzader.github.io/ghagga/app/)** 并使用 GitHub 登录 3. **配置你的 LLM 提供商** — 在 SaaS 模式下,GitHub Models 需要具有 `models:read` 权限的 PAT,或者自带提供商密钥 4. **打开一个 PR** — 在约 1-2 分钟内获得 AI 驱动的审查 ### 选项 1: GitHub Action (公共仓库免费) 无需服务器 —— 直接在 GitHub 的基础设施中运行。对于使用 GitHub Models 的公共仓库 100% 免费。 ``` # .github/workflows/ghagga.yml name: Code Review on: pull_request: types: [opened, synchronize, reopened] permissions: pull-requests: write jobs: review: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: JNZader/ghagga-action@v1 ``` #### Action 输入 | 输入 | 必需 | 默认值 | 描述 | |-------|----------|---------|-------------| | `provider` | 否 | `github` | LLM 提供商: `github`, `anthropic`, `openai`, `google`, `ollama`, `qwen` | | `model` | 否 | 自动 | 模型标识符 (每个提供商自动选择最佳) | | `mode` | 否 | `simple` | 审查模式: `simple`, `workflow`, `consensus` | | `api-key` | 否 | — | LLM 提供商 API key。`github` 提供商不需要 (免费默认值)。 | | `github-token` | 否 | `${{ github.token }}` | 用于 PR 访问的 GitHub token。自动获取。 | | `enabled-tools` | 否 | — | 强制启用的工具列表 (逗号分隔) | | `disabled-tools` | 否 | — | 强制禁用的工具列表 (逗号分隔) | | `enable-memory` | 否 | `true` | 启用 SQLite 审查记忆 (跨运行缓存) | #### Action 输出 | 输出 | 描述 | |--------|-------------| | `status` | 审查结果: `PASSED`, `FAILED`, `NEEDS_HUMAN_REVIEW`, `SKIPPED` | | `findings-count` | 检测到的发现数量 | 📋 **[完整 GitHub Action 指南](docs/github-action.md)** — 包含提供商示例、故障排除和配置参考的完整设置指南。 ### 选项 2: CLI 从你的终端审查本地更改。无需服务器。 ``` # 安装 npm install -g ghagga # 使用 GitHub 登录 (免费,无需 API key) ghagga login # 审查暂存的更改 ghagga review # 带选项审查 ghagga review --mode workflow --provider openai --api-key sk-xxx ghagga review --provider ollama --model qwen2.5-coder:7b # 项目健康检查 ghagga health ghagga health ./src --top 5 # 管理审查记忆 ghagga memory list ghagga memory search "error handling" ghagga memory stats # 安装 git hooks (可选) ghagga hooks install ``` #### CLI 命令 | 命令 | 描述 | |---------|-------------| | `ghagga login` | 使用 GitHub 认证 (免费 AI 模型) | | `ghagga logout` | 清除存储的凭据 | | `ghagga status` | 显示认证和配置 | | `ghagga review [path]` | 审查本地代码更改 | | `ghagga memory ` | 检查、搜索和管理审查记忆 (`list`, `search`, `show`, `delete`, `stats`, `clear`) | | `ghagga hooks ` | 安装、卸载和检查 git hooks 的状态 (`install`, `uninstall`, `status`) | | `ghagga health [path]` | 运行项目健康评估,包含评分、趋势和建议 | #### CLI 选项 | 选项 | 简写 | 默认值 | 描述 | |--------|-------|---------|-------------| | `[path]` | — | `.` | 仓库或子目录的路径 | | `--mode ` | `-m` | `simple` | 审查模式: `simple`, `workflow`, `consensus` | | `--provider ` | `-p` | `github` | LLM 提供商: `github`, `anthropic`, `openai`, `google`, `ollama`, `qwen` | | `--model ` | — | 自动 | 模型标识符 (或 `GHAGGA_MODEL` 环境变量) | | `--api-key ` | — | — | API key (或 `GHAGGA_API_KEY` 环境变量) | | `--output ` | `-o` | `markdown` | 输出格式: `markdown`, `json`, `sarif` | | `--format ` | `-f` | — | **已弃用** — 使用 `--output`。输出格式 | | `--enhance` | — | — | AI 驱动的后期分析增强 (分组发现,添加修复建议) | | `--issue ` | — | — | 创建 (`new`) 或更新 (``) 一个包含审查结果的 GitHub issue | | `--enable-tool ` | — | — | 强制启用特定工具 | | `--disable-tool ` | — | — | 强制禁用特定工具 | | `--list-tools` | — | — | 显示所有 15 种工具及其状态 | | `--no-memory` | — | — | 禁用审查记忆 | | `--staged` | — | — | 仅审查暂存的文件 (用于 pre-commit hook) | | `--quick` | — | — | 仅静态分析,跳过 AI 审查 (~5-10秒 vs ~30-60秒) | | `--commit-msg ` | — | — | 从文件验证提交消息 | | `--exit-on-issues` | — | — | 如果发现严重/高危问题则退出码为 1 | | `--memory-backend ` | — | `sqlite` | 记忆后端: `sqlite` 或 `engram` | | `--plain` | — | — | 禁用终端样式输出 (在非 TTY/CI 中自动启用) | | `--config ` | `-c` | `.ghagga.json` | 配置文件路径 | | `--verbose` | `-v` | — | 显示每个 pipeline 步骤的实时进度 | #### 退出码 | 代码 | 含义 | |------|---------| | `0` | 审查通过或被跳过 | | `1` | 审查失败或需要人工审查 | #### 配置文件 (`.ghagga.json`) 在你的仓库根目录放置一个 `.ghagga.json` 以设置项目级默认值: ``` { "mode": "workflow", "provider": "anthropic", "model": "claude-sonnet-4-20250514", "enabledTools": ["ruff", "bandit"], "disabledTools": ["markdownlint"], "customRules": [".semgrep/custom-rules.yml"], "ignorePatterns": ["*.test.ts", "*.spec.ts", "docs/**"], "reviewLevel": "strict" } ``` 使用 `--config` 指向特定的配置文件:`ghagga review --config .ghagga.json` 优先级:CLI flags > 配置文件 > 环境变量 > 默认值。 📋 **[完整 CLI 指南](docs/cli.md)** — 包含所有命令、提供商示例和故障排除的完整设置指南。 ### 选项 3: 自托管 支持 PostgreSQL、记忆和仪表板的完整部署。 ``` # 克隆 git clone https://github.com/JNZader/ghagga.git cd ghagga # 配置 cp .env.example .env # 使用你的凭证编辑 .env (参见下方 Configuration 部分) # 启动 docker compose up -d ``` 这将启动: - **PostgreSQL 16** 在端口 5432 上,带有健康检查 - **GHAGGA Server** (Hono) 在端口 3000 上,预装静态分析工具 ## 架构 ``` graph TB subgraph Distribution["Distribution Layer"] Server["Server
Hono"] Action["Action
GitHub Action"] CLI["CLI"] end subgraph Runner["Delegated Runner"] RunnerRepo["ghagga-runner
GitHub Actions"] RunnerTools["Static Analysis Tools
7GB RAM"] end subgraph Core["@ghagga/core"] SA["Static Analysis
15-tool registry"] Agents["AI Agents
Simple · Workflow · Consensus"] Memory["Memory
Search · Persist · Privacy"] end subgraph DB["@ghagga/db"] PG["PostgreSQL
+ tsvector"] Drizzle["Drizzle ORM
+ Migrations"] Crypto["AES-256-GCM
Encryption"] end Server -- "workflow_dispatch" --> RunnerRepo RunnerRepo --> RunnerTools RunnerTools -- "callback" --> Server Server --> Core Action --> Core CLI --> Core Core --> DB ``` ### 核心 + 适配器模式 审查引擎 (`@ghagga/core`) 对 HTTP、webhook 或 CLI **一无所知**。它接收一个 diff + 配置,运行分析,编排智能体,并返回结构化结果。 每种分发模式 (`apps/*`) 都是一个薄适配器: | 适配器 | 输入 | 输出 | 记忆 | 静态分析 | |---------|-------|--------|--------|----------------| | **Server** | GitHub webhook | 通过 GitHub API 发表 PR 评论 | 是 | 委托给 runner | | **Action** | GitHub Actions 中的 PR 事件 | 通过 Octokit 发表 PR 评论 | 是 | 在 runner 上直接运行 | | **CLI** | 本地 `git diff` | 终端输出 | 是 | 如果在本地安装 | ### 审查 Pipeline 无论采用哪种分发模式,每次审查都遵循相同的 pipeline: ``` flowchart LR Input["Input
diff + config"] --> S1["Validate"] S1 --> S2["Parse &
Filter Diff"] S2 --> S3["Detect
Stacks"] S3 --> S4["Token
Budget"] S4 --> S5["Static Analysis
+ Memory Search"] S5 --> S6["AI Agent
Execution"] S6 --> S7["Merge
Findings"] S7 --> S8["Persist
Memory"] S8 --> Output["ReviewResult"] ``` 每个步骤都会优雅降级 —— 如果静态分析失败,或记忆不可用,pipeline 会使用现有资源继续执行。 ## 审查模式 ### Simple 模式 使用全面的系统提示进行单次 LLM 调用。最适合中小型 PR。 ``` flowchart LR Input["Diff + Static Analysis
+ Memory + Stack Hints"] --> LLM["1 LLM Call"] LLM --> Output["STATUS / SUMMARY / FINDINGS"] ``` **Token 用量**: ~1x (一次调用) **最适合**: 快速审查、小型 PR、低 token 预算 ### Workflow 模式 5 个专家智能体 **并行** 运行,然后通过综合步骤合并它们的发现。 ``` flowchart LR Input["Diff + Context"] --> S1["Scope Analysis"] Input --> S2["Coding Standards"] Input --> S3["Error Handling"] Input --> S4["Security Audit"] Input --> S5["Performance"] S1 --> Synth["Synthesis
merge + deduplicate"] S2 --> Synth S3 --> Synth S4 --> Synth S5 --> Synth Synth --> Output["Structured Response"] ``` **Token 用量**: ~6x (5 个专家 + 1 次综合) **最适合**: 彻底的审查、大型 PR、当你希望针对每个区域进行专注分析时 ### Consensus 模式 多个模型以指定立场(支持/反对/中立)进行审查,然后通过加权投票决定结果。 ``` flowchart LR Input["Diff + Context"] --> A["Advocate
looks for good"] Input --> C["Critic
looks for problems"] Input --> O["Observer
balanced view"] A --> Vote["Weighted Vote"] C --> Vote O --> Vote Vote --> Status["Final STATUS"] ``` **Token 用量**: ~3x (3 种立场) **最适合**: 关键代码路径、高置信度决策、安全敏感的更改 ## 静态分析 第 0 层分析在 **任何** LLM 调用之前运行。零 token 消耗。已知问题被注入到智能体提示中,以便 AI 专注于逻辑、架构和静态分析无法检测的事物。 GHAGGA 支持 5 个类别的 **15 种静态分析工具**,分为两个层级: - **7 种常开工具** 在每次审查时运行:Semgrep (安全), Trivy (SCA), CPD (重复), Gitleaks (密钥), ShellCheck (shell lint), markdownlint (文档 lint), Lizard (复杂度) - **8 种自动检测工具** 当 diff 中包含匹配文件时激活:Ruff (Python), Bandit (Python 安全), golangci-lint (Go), Bi (JS/TS), PMD (Java), Psalm (PHP), clippy (Rust), Hadolint (Docker) ### 优雅降级 工具是可选的。如果未安装工具,它将被静默跳过。审查将使用可用的任何工具继续进行。 | 分发方式 | 可用工具 | 方式 | |-------------|---------------|-----| | Docker (server) | 全部预装 | 包含在 Docker 镜像中 | | GitHub Action (node20) | 全部自动安装 + 缓存 | runner 上的 `@actions/cache` | | CLI | 如果在本地安装 | 使用本地二进制文件 | ### 自定义 Semgrep 规则 GHAGGA 在 `packages/core/src/tools/semgrep-rules.yml` 中内置了 20 条安全规则。你可以通过 `customRules` 配置选项添加自定义规则: ``` { "customRules": [".semgrep/my-rules.yml"] } ``` ## Runner 架构 Render 免费层 (512MB RAM) 无法同时运行所有静态分析工具。GHAGGA 通过将静态分析委托给公共仓库上的 **用户拥有的 GitHub Actions runners** 来解决这个问题(无限制免费分钟数,7GB RAM)。 ### 工作原理 1. **设置**:用户从 [`ghagga-runner-template`](https://github.com/JNZader/ghagga-runner-template) 创建一个公共仓库 2. **发现**:服务器检查 `{owner}/ghagga-runner` 是否存在(基于约定,GET → 200/404) 3. **密钥**:服务器通过 GitHub API 在 runner 仓库上设置每次调度的 HMAC 密钥 4. **调度**:服务器使用 10 个输入(repo、PR、SHA、回调 URL、工具配置)触发 `workflow_dispatch` 5. **执行**:Runner 安装/缓存静态分析工具并运行分析(~18 秒) 6. **回调**:Runner 使用 HMAC-SHA256 签名将结果 POST 到 `POST /runner/callback` 7. **合并**:服务器将静态发现与 AI 审查合并并发布组合评论 ### 安全模型 通过公共 runner 分析的私有仓库代码受 **4 层安全层** 保护: | 层 | 保护 | |-------|-----------| | **输出抑制** | 所有工具输出重定向到 `/dev/null` — workflow 日志中无任何内容 | | **日志掩码** | 对所有敏感值应用 `::add-mask::` | | **日志删除** | 完成后通过 GitHub API 删除 workflow 运行日志 | | **保留策略** | Runner 仓库配置为 1 天日志保留 | 每次调度都会生成一个唯一的 `callbackSecret`,存储在具有 11 分钟 TTL 的内存 Map 中。HMAC-SHA256 验证确保只有合法的 runner 可以交付结果。 ### 优雅回退 如果未发现 runner 仓库,服务器将回退到 **仅 LLM 审查**(无静态分析)。审查仍然有效 —— 只是跳过第 0 层。 ## 记忆系统 GHAGGA 使用 PostgreSQL 全文搜索从过去的审查中学习。设计模式受 [Engram](https://github.com/Gentleman-Programming/engram) 启发(会话模型、topic-key upsert、去重、隐私脱敏)—— 直接在 PostgreSQL 中实现,以支持多租户和可扩展性。 ### 工作原理 1. **每次审查后**,自动提取观察结果(决策、模式、错误、学习) 2. **去重** 防止存储相同的观察结果(内容哈希 + 15 分钟滚动窗口) 3. **Topic-key upsert** 演进现有知识而不是创建重复项 4. **每次审查前**,通过 tsvector 全文搜索检索相关观察结果并注入到智能体提示中 5. **隐私脱敏** 在存储任何内容之前删除 API key、token 和密钥 ### 观察类型 | 类型 | 描述 | 示例 | |------|-------------|---------| | `decision` | 架构和设计选择 | "团队决定使用 Zustand 而不是 Redux 进行状态管理" | | `pattern` | 代码模式和约定 | "所有 API 路由使用 zod 验证中间件" | | `bugfix` | 常见错误及其修复 | "React useEffect 缺少清理会导致仪表板内存泄漏" | | `learning` | 一般项目知识 | "计费模块使用 Stripe webhook 进行支付确认" | | `architecture` | 系统设计决策 | "微服务通过事件总线通信,而不是直接 HTTP" | | `config` | 配置模式 | "特定于环境的配置位于 /config/{env}.ts" | | `discovery` | 代码库发现 | "/lib/auth 中的旧版认证模块已弃用,使用 /modules/auth" | ### 隐私脱敏 在将任何观察结果存储到记忆中之前,GHAGGA 使用 16 种正则表达式模式脱敏敏感数据: | 模式 | 示例 | 脱敏为 | |---------|---------|-------------| | Anthropic API keys | `sk-ant-api03-...` | `[REDACTED_ANTHROPIC_KEY]` | | OpenAI API keys | `sk-proj-...` | `[REDACTED_OPENAI_KEY]` | | AWS Access Key IDs | `AKIA...` | `[REDACTED_AWS_KEY]` | | GitHub tokens | `ghp_...`, `gho_...`, `ghs_...`, `github_pat_...` | `[REDACTED_GITHUB_*]` | | Google API keys | `AIza...` | `[REDACTED_GOOGLE_KEY]` | | Slack tokens | `xoxb-...`, `xoxp-...` | `[REDACTED_SLACK_TOKEN]` | | Bearer tokens | `Bearer eyJ...` | `Bearer [REDACTED_TOKEN]` | | JWT tokens | `eyJ...eyJ...xxx` | `[REDACTED_JWT]` | | PEM private keys | `-----BEGIN PRIVATE KEY-----` | `[REDACTED_PRIVATE_KEY]` | | 密码/密钥分配 | `password = "..."` | `[REDACTED]` | | Base64 凭据 | `SECRET=aGVsbG8...` | `[REDACTED_BASE64]` | ## 仪表板 部署在 GitHub Pages 上的 React SPA。深色主题,采用 GitHub-dark 调色板和紫色点缀。 **在线访问**: [https://jnzader.github.io/ghagga/app/](https://jnzader.github.io/ghagga/app/) ### 页面 | 页面 | 描述 | |------|-------------| | **登录** | GitHub OAuth Web Flow 登录,带 PAT 回退 | | **仪表板** | 4 个统计卡片(总审查数、通过率、平均发现数、平均时间)+ Recharts 面积图显示审查趋势 | | **审查** | 可过滤表格,带有状态徽章、严重程度指示器、详情展开和分页 | | **设置** | 每个仓库或全局设置 — 提供商链、审查模式、工具、忽略模式 | | **全局设置** | 安装范围的提供商链和默认值,适用于所有仓库 | | **记忆** | 观察列表,带有严重程度徽章、StatsBar(按类型/项目计数)、会话侧边栏、删除/清除/清理操作(3 级确认)、ObservationDetailModal(PR 链接、文件路径、修订计数、相对时间戳)、严重程度和排序过滤器 | ### 技术细节 - React 19 + TypeScript + Vite - TanStack Query 5 用于数据获取和缓存 - Recharts 用于数据可视化 - Tailwind CSS 4 搭配深色主题 - HashRouter 用于 GitHub Pages 兼容(无需服务器端路由) - 代码分割:延迟加载页面组件,配合 vendor chunk 分割 - 基础路径:`/ghagga/app/` 用于 GitHub Pages 部署 ### 记忆管理 记忆页面提供审查观察结果和会话的完整 CRUD 管理,并为破坏性操作提供 **3 级确认系统**: | 级别 | 操作 | 确认 | 示例 | |------|--------|-------------|---------| | **级别 1** | 删除单个观察 | 简单确认弹窗 | 删除一个观察 | | **级别 2** | 清除仓库观察 | 输入仓库名称确认 | 清除 `owner/repo` 的所有观察 | | **级别 3** | 清除所有观察 | 输入 "DELETE ALL" + 5 秒倒计时 | 擦除整个记忆数据库 | 其他管理操作: - **删除会话** — 删除单个记忆会话 - **清理空会话** — 删除没有剩余观察的会话 **ObservationDetailModal** 显示完整的观察详情,包括 PR 链接、文件路径、修订计数和相对时间戳。所有破坏性操作都会触发 **Toast 通知** 确认成功或失败。 ## 安全性 | 措施 | 实现 | |---------|---------------| | **API key 加密** | AES-256-GCM,每个安装有独立的加密密钥。密钥从不以明文存储。 | | **Webhook 验证** | HMAC-SHA256 签名验证,使用 `crypto.timingSafeEqual`(常量时间比较以防止时序攻击) | | **JWT 生成** | 为 GitHub App 安装 token 手动构建 RS256 JWT(无需外部 JWT 库) | | **隐私脱敏** | 16 种正则表达式模式在存储到记忆前删除 API key、token、密码和密钥 | | **无密钥日志** | 控制台输出和错误消息从不包含敏感数据(由自动化安全测试验证) | | **BYOK 模式** | 用户提供自己的 LLM API key。GHAGGA 绝不支付或以明文查看你的 LLM 使用情况。 | | **安装范围** | API 路由按 GitHub 安装 ID 限定范围 — 用户只能访问自己的仓库 | | **HTTP 超时** | 所有 `fetch()` 调用使用 `AbortSignal.timeout()` (10s/15s/5s) 以防止资源耗尽 | | **环境变量验证 (快速失败)** | 服务器在启动时验证所有必需的环境变量,如果有任何缺失则立即退出并显示清晰的错误 | | **错误 ID** | 所有 500 响应包含 `errorId`(8 字符 UUID)用于支持工单与服务器日志的关联 | | **关联 ID** | 每次审查生成一个 `reviewId`,通过 webhook → Inngest → pipeline → PR 评论 传播,用于端到端追踪 | | **FK 级联删除** | 所有外键使用 `ON DELETE CASCADE` 以在删除安装时防止孤立数据 | | **Dockerfile HEALTHCHECK** | 通过 Docker `HEALTHCHECK` 指令进行容器健康监控 | ### 自动化安全测试 测试套件包含 14 项专门的安全审计测试,验证: - 整个代码库中没有使用敏感变量名的 `console.log` 调用 - 源文件中没有硬编码的 API key、token 或密码 - 没有使用 `eval()` 或 `Function()` 构造函数 - AES-256-GCM 加密往返正确性 - 篡改密文检测 - webhook 签名比较使用 `timingSafeEqual` - 隐私脱敏覆盖所有 16 种密钥模式 ## Monorepo 结构 ``` ghagga/ ├── packages/ │ ├── core/ # @ghagga/core — Review engine │ │ └── src/ │ │ ├── pipeline.ts # Main orchestrator (validate → analyze → agent → persist) │ │ ├── types.ts # All TypeScript interfaces and types │ │ ├── index.ts # Public API exports │ │ ├── agents/ │ │ │ ├── prompts.ts # All agent prompts (rescued from v1) │ │ │ ├── simple.ts # Simple single-pass review │ │ │ ├── workflow.ts # 5-specialist parallel workflow │ │ │ └── consensus.ts # Multi-model voting │ │ ├── tools/ │ │ │ ├── semgrep.ts # Semgrep runner + JSON parser │ │ │ ├── trivy.ts # Trivy runner + JSON parser │ │ │ ├── cpd.ts # PMD/CPD runner + XML parser │ │ │ ├── runner.ts # Parallel orchestrator │ │ │ └── semgrep-rules.yml # 20 custom security rules │ │ ├── memory/ │ │ │ ├── search.ts # tsvector full-text search │ │ │ ├── persist.ts # Observation extraction + dedup │ │ │ ├── context.ts # Format observations as markdown │ │ │ └── privacy.ts # Privacy stripping (16 patterns) │ │ ├── providers/ │ │ │ ├── index.ts # Vercel AI SDK provider factory │ │ │ └── fallback.ts # Fallback chain with retry logic │ │ └── utils/ │ │ ├── diff.ts # Diff parsing, filtering, truncation │ │ ├── stack-detect.ts # File extension → tech stack │ │ └── token-budget.ts # Model-aware token allocation │ │ │ └── db/ # @ghagga/db — Database layer │ └── src/ │ ├── schema.ts # Drizzle table definitions (7 tables) │ ├── client.ts # Database connection factory │ ├── crypto.ts # AES-256-GCM encrypt/decrypt │ ├── queries.ts # All typed query functions │ └── index.ts # Re-exports │ ├── apps/ │ ├── server/ # @ghagga/server — Hono API │ │ └── src/ │ │ ├── index.ts # Hono app (CORS, health, webhook, Inngest, API) │ │ ├── middleware/auth.ts # GitHub PAT authentication middleware │ │ ├── inngest/ # Durable review function (7 steps + runner dispatch) │ │ ├── github/ │ │ │ ├── client.ts # GitHub API client (diff, comment, verify, JWT) │ │ │ └── runner.ts # Runner discovery, secret setup, dispatch │ │ ├── routes/ │ │ │ ├── runner-callback.ts # POST /runner/callback (HMAC verification) │ │ │ └── ... # Webhook + 8 REST API endpoints │ │ │ ├── dashboard/ # @ghagga/dashboard — React SPA │ │ └── src/ │ │ ├── App.tsx # HashRouter with lazy-loaded routes │ │ ├── lib/ # API hooks, auth context, utilities │ │ ├── components/ # Layout, Card, StatusBadge, SeverityBadge, │ │ │ │ # ConfirmDialog (3-tier), Toast, ObservationDetailModal │ │ │ ├── ConfirmDialog.tsx # 3-tier destructive action confirmation │ │ │ ├── Toast.tsx # Non-blocking success/error notifications │ │ │ └── ObservationDetailModal.tsx # Full observation detail with PR links │ │ └── pages/ # Login, Dashboard, Reviews, Settings, Memory │ │ │ ├── cli/ # ghagga — CLI tool │ │ └── src/ │ │ ├── index.ts # Commander entry point │ │ ├── commands/ │ │ │ ├── review.ts # Git diff → pipeline → output │ │ │ ├── review-commit-msg.ts # Commit message validation │ │ │ ├── hooks/ # Git hooks management │ │ │ │ ├── index.ts # Hooks command group │ │ │ │ ├── install.ts # Install pre-commit/commit-msg hooks │ │ │ │ ├── uninstall.ts # Remove GHAGGA-managed hooks │ │ │ │ └── status.ts # Show hook status │ │ │ └── memory/ # Memory management subcommands │ │ │ ├── list.ts # List observations (with filters) │ │ │ ├── search.ts # Full-text search across memory │ │ │ ├── show.ts # Show observation/session detail │ │ │ ├── delete.ts # Delete observation or session │ │ │ ├── stats.ts # Memory statistics by type/repo │ │ │ ├── clear.ts # Clear repo or all observations │ │ │ └── utils.ts # Shared formatting helpers │ │ └── ui/ # Terminal UI components │ │ ├── tui.ts # Interactive TUI renderer │ │ ├── theme.ts # Color theme and styling │ │ └── format.ts # Output formatters (table, json) │ │ │ └── action/ # @ghagga/action — GitHub Action │ ├── action.yml # Action definition (node20 runtime) │ ├── Dockerfile # Docker variant with static analysis tools │ └── src/index.ts # Fetch diff → pipeline → comment │ ├── templates/ # Runner dispatch templates │ ├── ghagga-analysis.yml # GitHub Actions workflow for static analysis │ └── ghagga-runner-README.md # Template repo README │ ├── landing/ # Marketing landing page │ └── index.html # Static HTML (GitHub Pages) │ ├── docs/ # Documentation site (Docsify) │ ├── index.html # Docsify configuration │ ├── _sidebar.md # Navigation structure │ └── *.md # Documentation pages │ ├── openspec/ # Spec-Driven Development artifacts │ └── changes/ghagga-v2-rewrite/ │ ├── proposal.md # Full rewrite proposal │ ├── design.md # Architecture decisions │ ├── tasks.md # 10 phases, tracked tasks │ └── specs/ # Detailed specs per module │ ├── Dockerfile # Multi-stage build (static analysis tools pre-installed) ├── docker-compose.yml # PostgreSQL + server for local dev ├── render.yaml # Render Blueprint for SaaS deployment ├── .github/workflows/ │ ├── ci.yml # Typecheck + build + test pipeline │ └── deploy-pages.yml # Auto-deploy dashboard to GitHub Pages └── README.md ``` ## 配置 ### 环境变量 | 变量 | 必需 | 描述 | |----------|----------|-------------| | `DATABASE_URL` | 仅服务器 | PostgreSQL 连接字符串 | | `GITHUB_APP_ID` | 仅服务器 | GitHub App ID | | `GITHUB_PRIVATE_KEY` | 仅服务器 | Base64 编码的 `.pem` 文件内容 | | `GITHUB_WEBHOOK_SECRET` | 仅服务器 | 在 GitHub App webhook 设置中配置的密钥 | | `INNGEST_EVENT_KEY` | 仅服务器 | Inngest 事件摄取密钥 | | `INNGEST_SIGNING_KEY` | 仅服务器 | Inngest webhook 签名密钥 | | `ENCRYPTION_KEY` | 仅服务器 | 用于 AES-256-GCM 加密的 64 字符十六进制字符串 | | `GHAGGA_MEMORY_BACKEND` | 仅 CLI | 记忆后端: `sqlite` (默认) 或 `engram` | | `GHAGGA_ENGRAM_HOST` | 仅 CLI | Engram 服务器 URL (默认: `http://localhost:7437`) | | `GHAGGA_ENGRAM_TIMEOUT` | 仅 CLI | Engram 连接超时(秒)(默认: `5`) | | `CALLBACK_TTL_MINUTES` | 否 | Runner 回调密钥 TTL(分钟)(默认: `11`) | | `PORT` | 否 | 服务器端口 (默认: `3000`) | | `NODE_ENV` | 否 | `development` 或 `production` | ### 默认模型 | 提供商 | 默认模型 | |----------|--------------| | GitHub Models | `gpt-4o-mini` | | Anthropic | `claude-sonnet-4-20250514` | | OpenAI | `gpt-4o` | | Google | `gemini-2.5-flash` | | Ollama | `qwen25-coder:7b` | | Qwen | `qwen-coder-plus` | ### Token 预算 diff 使用 70/30 分割自动截断以适应每个模型的上下文窗口: | 分配 | 百分比 | 用途 | |-----------|-----------|---------| | Diff 内容 | 70% | 实际的代码更改 | | 智能体提示 + 上下文 | 30% | 系统提示、静态分析、记忆、技术栈提示 | ## 开发 ### 先决条件 - **Node.js** 22+ - **pnpm** 9+ (通过 package.json 中的 `packageManager` 管理精确版本) - **PostgreSQL** 16+ (或使用 Docker) ### 设置 ``` # 克隆并安装 git clone https://github.com/JNZader/ghagga.git cd ghagga pnpm install # 启动 PostgreSQL (通过 Docker) docker compose up postgres -d # 配置环境 cp .env.example .env # 使用你的凭证编辑 .env # 运行数据库迁移 pnpm --filter @ghagga/db db:push # 启动开发服务器 pnpm --filter @ghagga/server dev # 启动 dashboard 开发服务器 (在另一个终端中) pnpm --filter @ghagga/dashboard dev ``` ### 命令 ``` pnpm exec turbo typecheck # Typecheck all packages pnpm exec turbo build # Build all packages pnpm exec turbo test # Run all ~2,859 tests ``` ### 测试套件 跨 8 个包约 2,859 个测试。全部通过。完成 4 轮审计(62 项改进)。 | 包 | 测试数 | 覆盖内容 | |---------|------:|----------------| | `@ghagga/core` | 1,328 | Pipeline、diff 解析、技术栈检测、token 预算、提示、智能体 (simple, workflow, consensus)、回退提供商、隐私、记忆 (搜索、持久化、上下文)、静态分析工具 (semgrep, trivy, cpd)、解析器、安全审计、审查校准、Engram 记忆适配器、熔断器 | | `@ghagga/db` | 118 | 查询 (CRUD、有效设置、提供商链)、AES-256-GCM 加密 (往返、篡改、边缘情况)、索引验证 | | `@ghagga/server` | 523 | API 路由 (6 个域模块)、webhook 处理器、认证中间件 + token 缓存、提供商验证、Inngest 审查函数、GitHub 客户端、runner 调度、回调验证、优雅关闭、健康检查、关联 ID、错误 ID、HTTP 超时、环境变量验证、Zod 负面测试 | | `ghagga` (CLI) | 272 | 配置解析、review 命令 — 输入验证、输出格式化、退出码、git hooks (安装、卸载、状态) | | `@ghagga/action` | 195 | 输入解析、输出设置、评论格式化、错误处理、工具安装、缓存管理 | | `@ghagga/dashboard` | 342 | 组件渲染、ErrorBoundary、a11y (7 项 axe 测试)、焦点陷阱、虚拟滚动 | | `@ghagga/types` | 24 | 共享 API 类型导出和契约验证 | | E2E | 14 | Webhook→pipeline→comment、CLI 审查流程、Action 审查流程 | ## 技术栈 | 层 | 技术 | 原因 | |-------|-----------|-----| | **Monorepo** | pnpm workspaces + Turborepo | 快速安装、并行构建、缓存 | | **语言** | TypeScript 5.7 (严格模式) | 跨所有包的类型安全 | | **后端** | Hono 4 | 最快的 TS 框架,14KB,随处运行 | | **数据库** | PostgreSQL 16 + Drizzle ORM | 零开销 SQL、tsvector FTS、纯 TS 迁移 | | **AI** | Vercel AI SDK 6 | 多提供商 (6 个提供商)、流式传输、结构化输出、回退链 | | **异步** | Inngest 3 | 零基础设施持久函数、步骤检查点、自动重试 | | **前端** | React 19 + Vite + Tailwind 4 | 延迟加载路由、vendor 分割、深色主题 | | **数据获取** | TanStack Query 5 | 缓存、后台重新获取、乐观更新 | | **图表** | Recharts 2 | 可组合的 React 图表组件 | | **UI 模式** | ConfirmDialog (3 级) + Toast | 分层破坏性操作安全、非阻塞通知 | | **CLI** | Commander 13 | Node.js 的标准 CLI 框架 | | **测试** | Vitest 4 | 快速、ESM 原生、兼容 Jest API | | **静态分析** | 15 工具插件注册表 | 安全、SCA、重复、lint、复杂度 —— 零 token | | **加密** | Node.js `crypto` (AES-256-GCM) | 加密操作无外部依赖 | ### 为什么选择这些 - **Vercel AI SDK 胜过 LangGraph/agentlib**:GHAGGA 的审查流程是可预测的(不是动态图)。AI SDK 以更少的开销提供多提供商支持。[agentlib](https://github.com/sammwy) 经过评估但仅支持 OpenAI 且没有多智能体支持。 - **Hono 胜过 Express/Fastify**:14KB,最快的基准测试,在 Node/Bun/Deno/Workers 上运行。Express 是遗留的,Fastify 比需要的更重。 - **Drizzle 胜过 Prisma**:零开销 SQL,无二进制依赖,支持原始 tsvector 操作。 - **PostgreSQL 记忆胜过 Engram**:Engram 有很好的设计模式但没有多租户、没有认证,且是 SQLite 单写入器。我们在 PostgreSQL 中采用了它的模式(会话、topic_key upsert、去重、隐私脱敏)。 - **Inngest 胜过 BullMQ**:零基础设施(无需 Redis)。每月 5 万事件免费。基于步骤的检查点意味着 LLM 重试不会重新运行静态分析。 ## 相较 v1 的变化 GHAGGA v2 是从头开始的 **完全重写**。v1 代码库(~11,000 行)保留在 `main-bkp` 分支上。 ### v1 有什么问题 | 问题 | 详情 | |---------|---------| | **重复实现** | 两个审查流程:webhook 内联处理器 AND 一个从未被调用的 ReviewService 类 | | **死代码** | Hebbian Learning 存储数据但从未使用。Threads、chunking 和 embedding 缓存模块存在但被孤立 | | **重度依赖** | 需要 Supabase CLI、Docker、Deno 运行时和一个单独的 Python 微服务用于 Semgrep | | **混合搜索回退** | 回退到客户端过滤而不是使用 SQL RPC 函数 | | **复杂的部署** | 多个手动步骤、多个运行时、多个服务 | ### 从 v1 中挽救了什么 | 组件 | 详情 | |-----------|---------| | **智能体提示** | 所有系统提示(simple、5 个 workflow 专家、synthesis、consensus 立场)—— 经过实战检验且设计良好 | | **多提供商抽象** | 支持多个 LLM 提供商带回退的概念 | | **加密模块** | 用于 API key 的 AES-256-GCM 加密模式 | | **Semgrep 规则** | 跨 7 种以上语言的 20 条自定义安全规则 | | **技术栈检测** | 文件扩展名 → 技术栈映射用于审查提示 | | **隐私脱敏** | 记忆持久化前基于模式的密钥脱敏 | ### v1 vs v2 对比 | 方面 | v1 | v2 | |--------|----|----| | 代码行数 | ~11,000 | ~6,000 (实现) + ~3,000 (测试) | | 运行时 | Deno + Node.js + Python | 仅 Node.js | | 数据库 | Supabase (托管 PostgreSQL) | 任何 PostgreSQL (自托管或云) | | 部署步骤 | 10+ 个手动步骤 | 3 个环境变量 + `docker compose up` | | 测试套件 | 0 个测试 | ~2,859 个测试 | | 分发模式 | 1 (仅 webhook) | 3 (SaaS, Action, CLI) | | 静态分析 | 仅 Semgrep (通过微服务) | 通过插件注册表的 15 种工具 (直接二进制执行) | | 记忆 | 部分 (存储但从未使用) | 完整 pipeline (搜索 → 注入 → 审查 → 提取 → 持久化) | | 死代码 | ~40% 的代码库 | 0% | ## 许可证 MIT — 详见 [LICENSE](LICENSE)。
标签:DevSecOps, DLL 劫持, DNS 反向解析, GitHub Action, Gitleaks, MITM代理, Pull Request, Python, Ruff, SaaS, SARIF, Semgrep, StruQ, WordPress安全扫描, 上游代理, 云安全监控, 人工智能, 代码审查, 多智能体, 大语言模型, 安全专业人员, 安全扫描, 密钥泄露检测, 文档安全, 无后门, 时序注入, 测试用例, 用户模式Hook绕过, 自动化CI/CD, 自动化攻击, 记忆系统, 请求拦截, 静态分析