sergiparpal/semantic-diff-weaver

GitHub: sergiparpal/semantic-diff-weaver

一个只读的 Python 语义 diff 静态分析工具,通过 AST 比较推断代码变更的行为影响并生成风险评级和测试义务,支持 CLI、GitHub Action 和 Hermes 插件三种运行方式。

Stars: 0 | Forks: 0

# Semantic Diff Weaver Semantic Diff Weaver 是一个建议性、只读的审查工具,用于分析两个已提交版本之间有限的 Git diff。它静态提取 Python 结构性变更,推断有证据支持的行为变更,将风险与置信度分开评级,并产出具体的测试义务以及未经验证的候选现有测试。您可以从命令行、在 pull request 上作为 GitHub Action 运行它,或作为 Hermes Agent 插件运行。 它绝不导入、执行、构建、安装、测试或修改被分析的仓库。它不运行您的测试或自行测量覆盖率——它可以*获取*您自己的 CI 已经生成的覆盖率报告,并报告该报告针对已更改行的说明。仓库内容被视为不受信任的数据,当没有可用的模型时,分析会降级为确定性的结构性发现。 ## 要求 - Python 3.11 或更高版本。 - `PATH` 中可用的 Git。 - Pydantic 2 和 PyYAML 6(随包安装)。 - 仅 0.14.0 或更高版本的 Hermes Agent 用于插件路径。该包故意不在元数据中强制安装 Hermes 或限制其版本。 ## 独立 CLI ``` pipx run --spec . semantic-diff-weaver --repo . --base main --head HEAD ``` 如果安装到当前环境中,同样的运行为: ``` python -m pip install . && semantic-diff-weaver --repo . --base main --head HEAD ``` `python -m semantic_diff_weaver` 与控制台脚本等效。 | 标志 | 含义 | | --- | --- | | `--repo PATH` | 要分析的仓库;默认为 `.` | | `--base REF` | 基础版本;**必填** | | `--head REF` | 目标版本;默认为 `HEAD` | | `--include GLOB` | 可重复的包含模式 | | `--exclude GLOB` | 可重复的排除模式 | | `--risk-profile PATH` | 额外的有限 YAML 配置文件 | | `--coverage PATH` | 作为覆盖率基准的 coverage.py JSON 或 lcov `.info` 报告 | | `--model ID` | 推理模型;覆盖 `SEMANTIC_DIFF_WEAVER_MODEL` | | `--no-llm` | 跳过推理;仅输出确定性结构性发现 | | `--format {json,markdown,both}` | 默认为 `markdown` | | `--allow-root PATH` | 可重复的额外授权根目录 | | `--fail-on {none,low,medium,high,critical}` | 默认为 `none` | `markdown` 打印适用于 PR 的简报,`json` 打印标准的 schema 版本化分析,`both` 打印包含分析和简报的信封。退出代码为: | 代码 | 含义 | | --- | --- | | `0` | 成功,且总体风险低于 `--fail-on` | | `1` | 分析错误;稳定的错误代码、消息和补救措施会输出到 stderr | | `2` | 参数错误 | | `3` | 成功,但总体风险达到 `--fail-on` | 退出代码 `3` 仍然会打印完整的报告——阈值是一个信号,而不是扣留分析结果的理由。 **在没有模型提供商的情况下,CLI 以确定性模式运行。** 它报告结构性发现、其分类法类别、风险和义务,全部仅源自 AST 比较。它没有添加的是推理层:发现被标记为 `deterministic_fallback` 而不是 `llm_supported`,描述是从内置的按类别模板中提取的,而不是针对特定 diff 编写的,并且除了确定性规则产生的问题外,不会提出任何审查问题。请参阅 [提供商部分](#model-provider) 以启用推理。 ### 基准覆盖率 将该工具指向您的 CI 已经生成的覆盖率报告,它将报告测试套件实际执行了哪些已更改的行: ``` semantic-diff-weaver --repo . --base main --coverage coverage.json ``` 接受 coverage.py JSON 和 lcov `.info` 格式,并根据内容进行识别。如果已更改的文件不在报告中,则会报告为**未知,从未发现未覆盖**,因此路径前缀不匹配会显示为警告,而不是虚假的覆盖率缺口。请参阅 [配置](docs/configuration.md#coverage-grounding)。 ### 模型提供商 推理是可选的,且从不是必需的。安装扩展并导出密钥以启用它: ``` python -m pip install '.[anthropic]' && export ANTHROPIC_API_KEY=... ``` 然后,CLI 将基于证据的推理层添加到确定性发现中。模型默认为 `claude-opus-5`,可以使用 `--model ID` 或 `SEMANTIC_DIFF_WEAVER_MODEL` 覆盖。 `--no-llm` 完全跳过提供商解析。 适配器将每个请求塑造为指定模型系列接受的形式——对于移除了采样参数的系列,会丢弃这些参数;对于思考始终开启而不是作为禁用发送的系列,会完全省略 `thinking` 参数。如果某个系列拒绝某个参数,会导致*所有*调用失败,然后运行会降级为确定性发现,仅显示一个通用的批次警告。因此,在 CI 中设置覆盖之前,请针对 `semantic_diff_weaver/providers/anthropic_client.py` 中的前缀列表进行检查;其原因详见 [docs/decisions.md](docs/decisions.md)。 当缺少包或密钥时,CLI 会向 stderr 打印一行通知,并以确定性模式继续——**缺少凭据绝不是硬性失败**,提供商报错、超时或返回 schema 拒绝的输出也同样不是。所有这些情况都会降级为相同的确定性结构发现,这是 Hermes 路径已经具备的行为。 密钥仅从环境中读取。它从不被记录,从不包含在错误路径中,也从不写入输出;`tests/security/test_provider_secrets.py` 断言,即使提供商将其嵌入到异常消息中,它也无法到达渲染的简报或 `WeaverError` 负载中。 ### CLI 授权 调用者选择的本地路径独立于仓库包含关系进行授权,并且 CLI 解析该授权的方式与插件**故意**不同。在 Hermes 下,*模型*选择 `repo_path`,因此默认的授权根目录是进程工作目录,仅此而已。在命令行上,由*人*输入路径,这就是授权。 因此,当 `SEMANTIC_DIFF_WEAVER_ALLOWED_ROOTS` **未设置**时,CLI 会为分析将其设置为解析后的 `--repo` 以及任何 `--allow-root` 值,然后恢复环境。当操作员**已经设置**了该变量时,CLI 从不扩大它:`--allow-root` 会被拒绝并返回退出代码 `2`,而操作员边界之外的 `--repo` 会像在 Hermes 下一样失败。无论是哪个路径,文件系统根目录都不会被接受为授权根目录。 外部的 `--risk-profile` 必须解析到授权根目录之下,因此当它位于仓库之外时,请使用 `--allow-root` 传递其目录。 ## GitHub Action 将简报作为单个 pull-request 评论发布。该 Action 封装了 CLI,本身不包含任何分析逻辑。 ``` name: pr-review on: [pull_request] permissions: contents: read pull-requests: write jobs: review: runs-on: ubuntu-latest steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 # required: the analyzer reads committed objects and never fetches - uses: your-org/semantic-diff-weaver@v0 with: fail-on: none ``` 重新运行会**编辑**现有评论,而不是追加新评论,这是通过隐藏的标记进行匹配的。第三方 Action 被固定到完整的 commit SHA,因为移动的标签是可变的,且此作业持有 `pull-requests: write`。输入、fork 的 pull-request 注意事项以及如何传递先前作业的覆盖率报告详见 [docs/github-action.md](docs/github-action.md)。 ## 安装并启用 Hermes 插件 作为用户目录插件进行开发时,请将此仓库目录复制到: ``` ~/.hermes/plugins/semantic-diff-weaver/ ``` 对于项目插件,请将其复制到 `.hermes/plugins/semantic-diff-weaver/` 并显式信任项目插件发现: ``` HERMES_ENABLE_PROJECT_PLUGINS=true ``` 对于包安装: ``` python -m pip install . hermes plugins enable semantic-diff-weaver hermes plugins list ``` 插件是可选的。如果发现或注册失败,请设置 `HERMES_PLUGINS_DEBUG=1` 并检查 Hermes 插件日志。该包公开了 `hermes_agent.plugins` 入口点,并且该目录同时包含 `plugin.yaml` 和根 `__init__.py`。 ## 工具输入 Hermes 仅注册一个工具 `analyze_semantic_diff`: ``` { "repo_path": "/path/to/local/repository", "base_ref": "main", "head_ref": "HEAD", "include": ["src/**/*.py"], "exclude": ["**/generated/**"], "output_format": "both" } ``` `repo_path` 和 `base_ref` 是必需的。`head_ref` 默认为 `HEAD`;`output_format` 可以为 `json`、`markdown` 或 `both`。可选的 `risk_profile` 可以显式指定一个有限的 YAML 文件,可选的 `coverage_report` 可以指定一个 coverage.py JSON 或 lcov `.info` 报告作为覆盖率基准。未知参数将被拒绝。 调用者选择的本地路径独立于仓库包含关系进行授权。默认情况下,该工具只能访问 Hermes 进程工作目录下的路径。受信任的主机操作员可以使用由平台路径分隔符分隔的 `SEMANTIC_DIFF_WEAVER_ALLOWED_ROOTS` 环境变量来授权额外的有限根目录。例如,在 Linux/macOS 上: ``` SEMANTIC_DIFF_WEAVER_ALLOWED_ROOTS=/work/project:/work/shared-profiles ``` `repo_path`、外部的 `risk_profile` 和外部的 `coverage_report` 都必须解析到这些根目录之一下。文件系统根目录永远不会被接受为授权根目录。 处理程序始终返回 JSON 编码的字符串。JSON 模式返回标准的 schema 版本化分析。Markdown 模式返回包含适用于 PR 的简报的 JSON 信封。Both 模式返回标准的分析和匹配的 Markdown。 ## 配置 所有配置都是可选的。优先级依次为工具参数、显式风险配置文件、`.hermes/semantic-diff-weaver.yaml`、`.semantic-diff-weaver.yaml` 以及内置的保守默认值。有关完整的 schema 和限制,请参阅 [配置](docs/configuration.md)。 最小示例: ``` version: 1 paths: include: ["src/**/*.py"] test_roots: ["tests"] critical_paths: - pattern: "src/auth/**" weight: 90 rules: minimum_report_confidence: 0.45 deterministic_fallback: true ``` 强制性的密钥和控制目录排除无法禁用。配置无法启用网络访问、代码执行或仓库边界之外的路径。 ## 开发门控 ``` python -m pytest python -m pytest tests/unit tests/contract python -m pytest tests/integration python -m pytest tests/security python -m pytest tests/evaluation python -m pytest tests/performance python -m pytest --cov=semantic_diff_weaver --cov-branch --cov-report=json:coverage.json python scripts/check_coverage.py coverage.json python -m ruff check . python -m ruff format --check . python -m mypy python -m build python scripts/verify_wheel.py dist python scripts/verify_hermes.py # with Hermes >=0.14.0 and the wheel installed ``` 测试使用临时 Git 仓库和伪造的 Hermes 上下文/模型。它们不会更改真实的 Hermes 主目录,也不需要付费或实时的 LLM。 ## 限制 - 仅支持 Python 源代码和常见的 pytest/unittest 布局。 - 仅支持已提交的基础/目标内容;暂存和工作树更改不在 MVP 范围内。 - 静态候选测试不是已验证的覆盖率:它们是名称和导入匹配,绝不是测试断言了已更改行为的声明。即使提供了覆盖率报告,这一点也成立——获取的报告说明测试套件执行了已更改的*行*,这是一个不同且较弱的声明。 - 该工具获取覆盖率报告而从不生成报告;报告中缺失的已更改文件会被报告为未知,而不会报告为未覆盖。 - 动态元编程和外部契约可能会产生审查问题或未知的语义更改。 - 没有网络引用查找、测试执行或测试生成。GitHub Action 通过 `gh` CLI 使用工作流自身的 token 发布评论;分析器本身不发出任何网络请求,也不读取任何 pull-request API。 - 多语言支持不在范围内:`ast_diff/` 是基于 Python 自己的 `ast` 构建的。 ## 许可证 根据 [MIT License](LICENSE) 授权。
标签:Git差异分析, SOC Prime, 代码审查, 开发工具, 恶意代码分类, 网络安全研究, 逆向工具, 错误基检测, 静态代码分析, 风险量化评估