Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- name: Compile package and scripts
run: python -m compileall -q src tests skills
run: python -m compileall -q src tests skills integrations
- name: Run tests
run: make test
- name: Install build backend
Expand Down Expand Up @@ -73,3 +73,37 @@ jobs:
path: /tmp/patchproof-audit/
if-no-files-found: error
retention-days: 14

bottle-integration:
runs-on: ubuntu-latest
env:
PATCHPROOF_IMAGE: python:3.12.10-slim@sha256:fd95fa221297a88e1cf49c55ec1828edd7c5a428187e67b5d1805692d11588db
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Check out pinned Bottle pre-fix commit
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: bottlepy/bottle
ref: 2a743a302a71460bfe4c0b8b7cb99a306b0328c6
path: external/bottle
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
- name: Pull pinned validation image
run: docker pull "$PATCHPROOF_IMAGE"
- name: Validate the real upstream Bottle fix
run: |
PYTHONPATH=src python integrations/bottle-http-preconditions/run_case.py \
--repo external/bottle \
--audit-dir /tmp/patchproof-bottle-audit \
--docker-image "$PATCHPROOF_IMAGE" \
> /tmp/patchproof-bottle-result.json
python -c 'import json; result=json.load(open("/tmp/patchproof-bottle-result.json")); assert result["proof_grade"] is True; assert result["repository_unchanged"] is True; assert result["phases"][2]["tests_run"] == 359'
- name: Upload Bottle proof artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: patchproof-bottle-integration
path: /tmp/patchproof-bottle-audit/
if-no-files-found: error
retention-days: 14
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,24 @@

All notable changes are recorded here. The project remains alpha before `1.0.0`, and minor releases may change experimental interfaces.

## 0.1.2 — 2026-08-03

### 新增 / Added

- 新增 Bottle 真实历史缺陷集成:固定修复前提交与准确的上游源码修复 Hunk,配套独立复现和边界测试,并运行 359 项 Bottle 原生回归测试。
Added a real historical Bottle defect integration with a pinned pre-fix commit, the exact upstream source-fix hunk, independent reproduction and edge-case tests, and 359 project-native regressions.
- 新增独立 `bottle-integration` Docker CI 作业并上传内容寻址审计产物。
Added a dedicated Docker-backed `bottle-integration` CI job with uploaded content-addressed audit artifacts.

### 变更 / Changed

- 固定 `unittest discover` Runner 现在可选安全的仓库相对 discovery top-level,从而支持包含相对导入的测试包。
The fixed `unittest discover` runner now accepts an optional safe repository-relative discovery top-level for test packages with relative imports.
- 默认文本快照新增 `.tpl`,使项目原生模板测试夹具能够进入只读副本和快照绑定。
Default text snapshots now include `.tpl` files so project-native template fixtures enter the read-only copy and snapshot binding.
- 外置测试复制会忽略标准 `__pycache__` 生成物,同时继续拒绝其他非 Python 文件与符号链接。
External test copying now ignores standard `__pycache__` artifacts while continuing to reject other non-Python files and symbolic links.

## 0.1.1 — 2026-08-03

### 新增 / Added
Expand Down
10 changes: 9 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
PYTHON ?= python3
RUN_DIR ?= /tmp/patchproof-demo
IMAGE ?= python:3.12.10-slim@sha256:fd95fa221297a88e1cf49c55ec1828edd7c5a428187e67b5d1805692d11588db
BOTTLE_REPO ?= /tmp/patchproof-bottle
BOTTLE_AUDIT_DIR ?= /tmp/patchproof-bottle-audit

.PHONY: test demo-local demo clean
.PHONY: test demo-local demo bottle-local clean

test:
PYTHONPATH=src $(PYTHON) -m unittest discover -s tests -v

demo-local:
PYTHONPATH=src $(PYTHON) scripts/run_demo.py

bottle-local:
PYTHONPATH=src $(PYTHON) integrations/bottle-http-preconditions/run_case.py \
--repo $(BOTTLE_REPO) \
--audit-dir $(BOTTLE_AUDIT_DIR) \
--unsafe-local

demo:
PYTHONPATH=src $(PYTHON) -m patchproof propose \
--repo fixtures/calculator \
Expand Down
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ An evidence-grade patch validator for coding-agent platforms, evaluations, and C
>
> The four phase results come from the repository's real fixture and `make demo-local`; `proof_grade=true` is established by the network-disabled, read-only, non-root Docker CI job.

**真实第三方证据 / Real third-party evidence:**PatchProof 现在固定并验证 Bottle 的真实 HTTP 条件请求修复:修复前失败、修复后通过、359 项上游回归通过、独立边界测试通过,目标 checkout 保持不变。查看 [Bottle 集成案例](integrations/bottle-http-preconditions/README.md)。

PatchProof now pins and validates a real Bottle HTTP-precondition fix: fail before, pass after, 359 upstream regressions passing, a distinct edge case passing, and an unchanged target checkout. See the [Bottle integration case](integrations/bottle-http-preconditions/README.md).

## 3 秒看懂 / Understand It in 3 Seconds

| | 中文 | English |
Expand Down Expand Up @@ -243,12 +247,14 @@ The command revalidates strict structure, phase semantics, and the content hash,

## 可验证证据 / Verifiable Evidence

- **71 项自动化测试 / 71 automated tests**:覆盖 Diff、路径、符号链接、快照、审批、补丁应用、Runner、CLI、Demo、回执与 Skill 脚本。
They cover diffs, paths, symlinks, snapshots, approvals, patch application, runners, CLI, demo behavior, receipts, and Skill scripts.
- **80 项自动化测试 / 80 automated tests**:覆盖 Diff、路径、符号链接、快照、审批、补丁应用、Runner、CLI、Demo、回执、真实集成 Manifest 与 Skill 脚本。
They cover diffs, paths, symlinks, snapshots, approvals, patch application, runners, CLI, demo behavior, receipts, the real-integration manifest, and Skill scripts.
- **Python 3.11/3.12 CI**:每次 PR 与 `main` 推送均运行。
It runs on every pull request and `main` push.
- **真实 Docker Shadow Validation / Real Docker shadow validation**:在 GitHub Actions 中执行完整四阶段闭环并上传审计产物。
It executes the full four-phase loop in GitHub Actions and uploads audit artifacts.
- **第三方开源集成 / Third-party open-source integration**:[Bottle HTTP 条件请求案例](integrations/bottle-http-preconditions/README.md)绑定真实修复前提交与上游源码修复 Hunk,并运行 359 项项目原生回归测试。
The [Bottle HTTP-precondition case](integrations/bottle-http-preconditions/README.md) binds a real pre-fix commit and the exact upstream source-fix hunk, then runs 359 project-native regression tests.
- **只读前向案例 / Read-only forward case**:[IssueLens 复用记录](docs/issuelens-case-study.md)扫描 63 个真实项目文件并验证前后快照一致。
The [IssueLens reuse record](docs/issuelens-case-study.md) scans 63 real project files and verifies identical before/after snapshots.
- **可安装 Release / Installable release**:[GitHub Releases](https://github.com/eatdrop/patchproof/releases)包含经过构建与隔离安装验证的 wheel。
Expand All @@ -259,14 +265,14 @@ The command revalidates strict structure, phase semantics, and the content hash,
| 已实现并测试 / Implemented and tested | 明确不声称 / Explicitly not claimed |
|---|---|
| 有界 UTF-8 文本与 Unified Diff / Bounded UTF-8 text and unified diffs | 任意二进制、重命名或所有 Diff 方言 / Arbitrary binaries, renames, or every diff dialect |
| 固定 Python `unittest discover` / Fixed Python `unittest discover` | pytest/tox/nox、依赖安装或任意命令 / pytest/tox/nox, dependency installation, or arbitrary commands |
| 固定 Python `unittest discover`,支持包式 discovery top-level / Fixed Python `unittest discover` with package top-level support | pytest/tox/nox、依赖安装或任意命令 / pytest/tox/nox, dependency installation, or arbitrary commands |
| 单租户可信宿主上的 Docker 加固 / Docker hardening on a trusted single-tenant host | 生产级恶意多租户沙箱 / Production hostile multi-tenant sandbox |
| 哈希完整性与内容寻址 / Hash integrity and content addressing | 数字签名、可信时间戳或身份认证 / Digital signatures, trusted timestamps, or identity authentication |
| 独立协议、测试与真实前向审计 / Independent protocol, tests, and real forward audit | 已被大量团队采用或证明适用于所有 Agent / Broad adoption or proof for every agent system |

v0.1 的优先级是把边界做窄、做真、做可拒绝。扩大 Runner 与语言生态之前,项目更需要第二个真实系统集成和外部用户反馈
v0.1 的优先级是把边界做窄、做真、做可拒绝。第二个真实系统集成已经由 Bottle 案例补齐;下一阶段重点是外部用户反馈、更多独立案例,以及在不扩大任意命令权限的前提下评估 Runner 适配器

The v0.1 priority is to keep the boundary narrow, truthful, and rejectable. Before broadening runner and language support, the project needs a second real-system integration and external user feedback.
The v0.1 priority is to keep the boundary narrow, truthful, and rejectable. The Bottle case now supplies the second real-system integration; the next priorities are external user feedback, more independent cases, and runner adapters that do not open arbitrary-command authority.

## 常见问题 / FAQ

Expand Down Expand Up @@ -359,6 +365,7 @@ The repository also includes two independently usable, structurally validated wo
- [架构与信任边界 / Architecture and trust boundaries](docs/architecture.md)
- [安全模型与限制 / Security model and limitations](SECURITY.md)
- [工程文章:把不确定补丁放进确定性边界 / Engineering article: putting uncertain patches inside deterministic boundaries](docs/engineering-boundaries.md)
- [Bottle 真实第三方集成 / Real third-party Bottle integration](integrations/bottle-http-preconditions/README.md)
- [IssueLens 真实复用案例 / Real IssueLens reuse case](docs/issuelens-case-study.md)
- [版本记录 / Changelog](CHANGELOG.md)

Expand Down
2 changes: 1 addition & 1 deletion docs/assets/patchproof-demo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
65 changes: 65 additions & 0 deletions integrations/bottle-http-preconditions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Bottle HTTP 条件请求真实集成 / Real Bottle HTTP-Precondition Integration

这个案例把 PatchProof 应用于第三方开源项目 [Bottle](https://github.com/bottlepy/bottle) 的真实历史缺陷,而不是仓库内自造的计算器样例。案例固定修复前提交、复用上游提交中准确的 `bottle.py` 修复 Hunk,并用 PatchProof 自己编写且放在目标仓库之外的复现测试和边界测试完成四阶段验证。上游提交自带的测试改动没有进入候选补丁。

This case applies PatchProof to a real historical defect in the third-party open-source [Bottle](https://github.com/bottlepy/bottle) project instead of another repository-owned calculator example. It pins the pre-fix commit, reuses the exact `bottle.py` fix hunk from upstream, and runs independently authored reproduction and edge-case tests from outside the target repository. The upstream commit's own test change is not included in the candidate patch.

## 案例证据 / Case Evidence

| 项目 / Item | 固定值 / Pinned value |
|---|---|
| 缺陷 / Defect | `If-None-Match` 存在时错误地继续处理 `If-Modified-Since` / `If-Modified-Since` was still evaluated when `If-None-Match` was present |
| 修复前提交 / Pre-fix commit | [`2a743a302a71460bfe4c0b8b7cb99a306b0328c6`](https://github.com/bottlepy/bottle/commit/2a743a302a71460bfe4c0b8b7cb99a306b0328c6) |
| 上游修复 / Upstream fix | [`b73bd1db5b7a915cf6a78656955c4059f58195ae`](https://github.com/bottlepy/bottle/commit/b73bd1db5b7a915cf6a78656955c4059f58195ae) |
| 候选改动 / Candidate change | 仅 `bottle.py`,新增 5 行、删除 4 行 / `bottle.py` only, 5 additions and 4 deletions |
| 目标快照 / Target snapshot | 67 个受支持文本文件的 SHA-256 绑定 / SHA-256 binding over 67 supported text files |
| 完整回归 / Full regression | Bottle 自己的 359 项 `unittest` / Bottle's own 359 `unittest` cases |
| 外置评测 / External grading | 1 项复现 + 1 项不同边界测试 / 1 reproduction + 1 distinct edge-case test |

复现测试证明:非匹配的 `If-None-Match` 应覆盖一个原本会触发 `304` 的较新 `If-Modified-Since`,因此正确结果是 `200`。边界测试进一步关闭响应 ETag 生成,验证优先级规则仍然成立。两个测试均不修改 Bottle 仓库,也不包含在候选补丁中。

The reproduction proves that a non-matching `If-None-Match` must override a newer `If-Modified-Since` that would otherwise produce `304`, so the correct response is `200`. The separate edge case disables response ETag generation and verifies that the precedence rule still holds. Neither test modifies the Bottle checkout or appears in the candidate patch.

这里的“hidden”表示测试位于候选工作区之外并在应用补丁后注入,不表示它在这个公开仓库中保密。

Here, “hidden” means outside the candidate workspace and injected only after patch application; it does not mean confidential inside this public repository.

## 本地复验 / Reproduce Locally

本地模式适合验证行为,但因为没有 Docker 隔离,会如实输出 `proof_grade=false`。

Local mode is suitable for checking behavior, but honestly reports `proof_grade=false` because Docker isolation is absent.

```bash
git clone https://github.com/bottlepy/bottle.git /tmp/patchproof-bottle
git -C /tmp/patchproof-bottle checkout 2a743a302a71460bfe4c0b8b7cb99a306b0328c6

PYTHONPATH=src python3 integrations/bottle-http-preconditions/run_case.py \
--repo /tmp/patchproof-bottle \
--audit-dir /tmp/patchproof-bottle-audit \
--unsafe-local
```

隔离验证使用 README 中同一个摘要固定镜像:

Isolated validation uses the same digest-pinned image documented in the main README:

```bash
IMAGE='python:3.12.10-slim@sha256:fd95fa221297a88e1cf49c55ec1828edd7c5a428187e67b5d1805692d11588db'
docker pull "$IMAGE"

PYTHONPATH=src python3 integrations/bottle-http-preconditions/run_case.py \
--repo /tmp/patchproof-bottle \
--audit-dir /tmp/patchproof-bottle-proof \
--docker-image "$IMAGE"
```

成功结果应包含 `baseline_reproduction=1`、`patched_reproduction=1`、`full_regression=359`、`hidden_tests=1`,且真实 Bottle checkout 的前后快照一致。

A successful result contains `baseline_reproduction=1`, `patched_reproduction=1`, `full_regression=359`, and `hidden_tests=1`, while the real Bottle checkout retains the same before/after snapshot.

## 来源与许可证 / Source and License

`upstream-fix.diff` 来自 Bottle 上游修复提交,版权属于 Marcel Hellkamp,并按 Bottle 的 MIT 许可证再分发;完整许可证见 [`UPSTREAM_LICENSE.txt`](UPSTREAM_LICENSE.txt)。其余集成脚本和独立测试属于 PatchProof。

`upstream-fix.diff` comes from the Bottle upstream fix commit, remains copyright Marcel Hellkamp, and is redistributed under Bottle's MIT license; see [`UPSTREAM_LICENSE.txt`](UPSTREAM_LICENSE.txt). The remaining integration runner and independent tests belong to PatchProof.
19 changes: 19 additions & 0 deletions integrations/bottle-http-preconditions/UPSTREAM_LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (c) 2009-2025, Marcel Hellkamp.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
17 changes: 17 additions & 0 deletions integrations/bottle-http-preconditions/case.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"schema_version": 1,
"case_id": "bottle-http-precondition-precedence",
"source_repository": "https://github.com/bottlepy/bottle",
"source_commit": "2a743a302a71460bfe4c0b8b7cb99a306b0328c6",
"upstream_fix_commit": "b73bd1db5b7a915cf6a78656955c4059f58195ae",
"upstream_fix_url": "https://github.com/bottlepy/bottle/commit/b73bd1db5b7a915cf6a78656955c4059f58195ae",
"license": "MIT",
"expected_snapshot": "7bdf801882e663cc8e4804504ec88de768efe89f1ded8a05b73a07fb795e5ac8",
"expected_snapshot_files": 67,
"patch_sha256": "ef2d5defef3aa5fcdb28c71474abe5186d4aa85d75f26eb9e10edeb20007ab99",
"changed_paths": [
"bottle.py"
],
"full_test_directory": "test",
"full_test_top_level": "."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from __future__ import annotations

import os
import tempfile
import unittest
import wsgiref.util
from pathlib import Path

import bottle


class ConditionalRequestHiddenTests(unittest.TestCase):
def setUp(self) -> None:
self.temporary = tempfile.TemporaryDirectory()
self.root = Path(self.temporary.name)
self.filename = "without-etag.txt"
asset = self.root / self.filename
asset.write_text("external hidden edge case\n", encoding="utf-8")
os.utime(asset, (1_000_000, 1_000_000))
environment: dict[str, object] = {}
wsgiref.util.setup_testing_defaults(environment)
bottle.request.bind(environment)
bottle.response.bind()

def tearDown(self) -> None:
self.temporary.cleanup()

def test_precedence_still_applies_when_response_etag_is_disabled(self) -> None:
bottle.request.environ["HTTP_IF_NONE_MATCH"] = '"client-supplied-tag"'
bottle.request.environ["HTTP_IF_MODIFIED_SINCE"] = bottle.http_date(2_000_000)

result = bottle.static_file(self.filename, root=str(self.root), etag=False)
body = result.body
if hasattr(body, "close"):
self.addCleanup(body.close)

self.assertEqual(200, result.status_code)


if __name__ == "__main__":
unittest.main()
Loading
Loading