Skip to content

jsdnaasd/context-aware-diff-reviewer

Repository files navigation

Context-aware Diff Reviewer

一个只审查 Git Diff 新增行 的 TypeScript 代码审查工具。它用 Tree-sitter 补齐函数、类型和调用位置,把确定性问题交给 ESLint/Semgrep,把需要上下文推理的逻辑问题交给 OpenAI 兼容 LLM;最后再次校验文件和行号,无法落到真实新增代码的结果不会发布到 PR。

CI

Context-aware Diff Reviewer walkthrough using the Web regression fixture

真实回归样例:Diff 映射 → AST/静态分析/LLM → 行号校验 → GitHub 行内评论。

Context-aware Diff Reviewer architecture

能解决什么

  • 资源已创建但成功、异常或提前返回路径没有释放。
  • Promise、Future 或回调中的异常被丢失。
  • 提交混入与目标无关的状态变化或业务行为。
  • LLM 因缺少上下文而引用不存在的函数、文件或行号。
  • 同一个格式/语法问题被静态工具和模型重复报告。
  • 已确认的误报在后续扫描中反复出现。

支持 .js.jsx.ts.tsx.mjs.cjs.dart。Web 与 Flutter 夹具在每次规则或 Prompt 变更后都会重新运行。

工作方式

flowchart LR
  A[Git Diff] --> B[新增行坐标]
  B --> C[Tree-sitter 上下文]
  B --> D[ESLint]
  B --> E[Semgrep]
  C --> F[上下文 LLM]
  D --> G[规范化与去重]
  E --> G
  F --> G
  G --> H[误报抑制]
  H --> I{文件与行号属于 Diff?}
  I -- 是 --> J[CLI 输出或 PR 行内评论]
  I -- 否 --> K[过滤并计数]
Loading

模型只收到本次变更涉及的 AST 片段、所在符号和有限的相关调用位置,不负责格式、语法和简单模式规则。每个保留结果都包含:filelinereasontriggerseveritysourceruleId 和稳定 fingerprint

本地使用

要求 Node.js 20+。Semgrep 是可选外部命令;未安装时会给出诊断,ESLint 与 LLM 结果仍会继续处理。

npm install
cp .diff-reviewer.example.yml .diff-reviewer.yml

export LLM_API_KEY="..."  # 不设置则自动跳过 LLM
npx tsx src/cli.ts review --base origin/main --head HEAD --format markdown

构建后也可以运行:

npm run build
node dist/cli.js review --base origin/main --format json --output review.json

OpenAI 兼容服务通过 llm.apiUrlllm.model 配置。密钥只从 LLM_API_KEY 读取,不写配置文件,也不会输出到日志。

GitHub Actions

仓库需要完整 Git 历史、项目依赖和 Semgrep。最小工作流:

name: Code review
on:
  pull_request:
    types: [opened, synchronize, reopened]

permissions:
  contents: read
  pull-requests: write
  issues: read

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v7
        with:
          node-version: 22
      - run: npm ci
      - run: pip install semgrep
      - uses: jsdnaasd/context-aware-diff-reviewer@v0.1.0
        with:
          github-token: ${{ github.token }}
          fail-on: never
        env:
          LLM_API_KEY: ${{ secrets.LLM_API_KEY }}

pull-requests: write 用于创建行内 Review,issues: read 用于读取 PR 评论里的误报命令。来自 Fork 的 PR 默认拿不到仓库 Secret,此时 LLM 会被跳过,静态扫描仍可运行。不要改用 pull_request_target 执行不可信分支代码并同时暴露 LLM 密钥。

Action 输出 findings-count 和完整 JSON resultfail-on 支持 nevererrorany

误报反馈

行内评论会显示 finding 指纹。仓库 Owner、Member 或 Collaborator 可以在 PR 普通评论中写:

/diff-reviewer ignore 3a11c09e4f20d834
/diff-reviewer ignore-rule context.subscription-not-cancelled lib/generated/**

命令可以发在 PR 普通评论或行内 Review 回复中。第一次按单条指纹跳过;第二次按规则和文件范围跳过。Action 每次运行都会重新读取这些可信成员的反馈。需要跨 PR 长期保存时,将等价规则加入 .diff-reviewer.yml

suppressions:
  - ruleId: context.subscription-not-cancelled
    path: "test/**"
    reason: fixture intentionally keeps a process-wide listener

配置

完整示例见 .diff-reviewer.example.yml。常用项:

配置 作用
include / exclude 控制进入流水线的文件 glob
severityThreshold infowarningerror
maxContextChars 单个 AST 片段上限
maxPromptChars 单次 LLM 请求上限,超出会分批
eslint.command 使用项目自身 ESLint 配置的命令
semgrep.config Semgrep 规则文件
suppressions 指纹、规则、来源与路径范围抑制

仓库自带的 rules/semgrep.yml 只放确定性较高的规则。若目标项目有自己的 ESLint/Semgrep 配置,可以直接覆盖命令或规则路径。

输出示例

{
  "file": "src/order-service.ts",
  "line": 42,
  "reason": "事务在成功路径和异常路径都没有结束。",
  "trigger": "begin 成功后 insert 返回或抛错时,没有 commit/rollback。",
  "severity": "error",
  "ruleId": "context.transaction-not-finalized",
  "source": "llm",
  "fingerprint": "3a11c09e4f20d834"
}

如果模型给出 src/order-service.ts:99,但第 99 行不是本次新增行,结果会进入 invalidFindings 统计,不会显示或评论。

开发与回归

npm run check
npm test
npm run review:fixtures
npm run build
npm run smoke:action

examples/web 验证事务未结束,examples/flutter 验证订阅未取消。测试使用假的 LLM/GitHub 边界,不发真实网络请求;规则或 Prompt 改动后会自动验证原有问题仍可定位,同时拒绝不存在的文件和行号。

限制与隐私

  • 这是 Diff Review 工具,不是完整的跨仓库数据流或 SAST 引擎。
  • 相关调用位置目前限于同一文件,避免提示词无界增长。
  • ESLint 使用目标仓库的安装与配置;Semgrep 未安装时会降级并给出诊断。
  • 只有启用 LLM 时,AST 代码片段才会发送到你配置的 API。使用前应确认代码托管和模型供应商的数据政策。
  • 二进制、删除文件、生成文件、锁文件和无法读取的文件默认不进入审查。

项目规格、验收条件和决策记录位于 docs/。许可证为 MIT。

About

AST-enriched Git diff review with ESLint, Semgrep, LLM validation, and GitHub inline comments

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages