patchdrill 0.1.0
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.
- package/.patchdrill.yml +33 -0
- package/CHANGELOG.md +150 -0
- package/CONTRIBUTING.md +59 -0
- package/LICENSE +21 -0
- package/README.md +601 -0
- package/SECURITY.md +28 -0
- package/action.yml +338 -0
- package/dist/baseline.d.ts +9 -0
- package/dist/baseline.js +38 -0
- package/dist/baseline.js.map +1 -0
- package/dist/cli.d.ts +19 -0
- package/dist/cli.js +662 -0
- package/dist/cli.js.map +1 -0
- package/dist/codeowners.d.ts +14 -0
- package/dist/codeowners.js +104 -0
- package/dist/codeowners.js.map +1 -0
- package/dist/command-plan.d.ts +3 -0
- package/dist/command-plan.js +26 -0
- package/dist/command-plan.js.map +1 -0
- package/dist/demo.d.ts +5 -0
- package/dist/demo.js +525 -0
- package/dist/demo.js.map +1 -0
- package/dist/dependency.d.ts +4 -0
- package/dist/dependency.js +1424 -0
- package/dist/dependency.js.map +1 -0
- package/dist/doctor.d.ts +26 -0
- package/dist/doctor.js +183 -0
- package/dist/doctor.js.map +1 -0
- package/dist/evidence.d.ts +64 -0
- package/dist/evidence.js +352 -0
- package/dist/evidence.js.map +1 -0
- package/dist/git.d.ts +16 -0
- package/dist/git.js +349 -0
- package/dist/git.js.map +1 -0
- package/dist/i18n-catalog.d.ts +8 -0
- package/dist/i18n-catalog.js +446 -0
- package/dist/i18n-catalog.js.map +1 -0
- package/dist/i18n.d.ts +20 -0
- package/dist/i18n.js +67 -0
- package/dist/i18n.js.map +1 -0
- package/dist/init.d.ts +13 -0
- package/dist/init.js +312 -0
- package/dist/init.js.map +1 -0
- package/dist/markdown-links.d.ts +18 -0
- package/dist/markdown-links.js +180 -0
- package/dist/markdown-links.js.map +1 -0
- package/dist/package-scripts.d.ts +3 -0
- package/dist/package-scripts.js +55 -0
- package/dist/package-scripts.js.map +1 -0
- package/dist/planner.d.ts +8 -0
- package/dist/planner.js +2351 -0
- package/dist/planner.js.map +1 -0
- package/dist/policy.d.ts +12 -0
- package/dist/policy.js +255 -0
- package/dist/policy.js.map +1 -0
- package/dist/project.d.ts +2 -0
- package/dist/project.js +1085 -0
- package/dist/project.js.map +1 -0
- package/dist/release-readiness.d.ts +25 -0
- package/dist/release-readiness.js +426 -0
- package/dist/release-readiness.js.map +1 -0
- package/dist/report-annotations.d.ts +3 -0
- package/dist/report-annotations.js +28 -0
- package/dist/report-annotations.js.map +1 -0
- package/dist/report-contract.d.ts +2 -0
- package/dist/report-contract.js +82 -0
- package/dist/report-contract.js.map +1 -0
- package/dist/report-html.d.ts +7 -0
- package/dist/report-html.js +706 -0
- package/dist/report-html.js.map +1 -0
- package/dist/report-sarif.d.ts +2 -0
- package/dist/report-sarif.js +90 -0
- package/dist/report-sarif.js.map +1 -0
- package/dist/report.d.ts +14 -0
- package/dist/report.js +310 -0
- package/dist/report.js.map +1 -0
- package/dist/risk.d.ts +19 -0
- package/dist/risk.js +1226 -0
- package/dist/risk.js.map +1 -0
- package/dist/runner.d.ts +8 -0
- package/dist/runner.js +113 -0
- package/dist/runner.js.map +1 -0
- package/dist/scan.d.ts +2 -0
- package/dist/scan.js +195 -0
- package/dist/scan.js.map +1 -0
- package/dist/schema.d.ts +12 -0
- package/dist/schema.js +30 -0
- package/dist/schema.js.map +1 -0
- package/dist/stack-coverage.d.ts +8 -0
- package/dist/stack-coverage.js +94 -0
- package/dist/stack-coverage.js.map +1 -0
- package/dist/types.d.ts +206 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/verification.d.ts +11 -0
- package/dist/verification.js +108 -0
- package/dist/verification.js.map +1 -0
- package/docs/ANNOTATIONS.md +34 -0
- package/docs/ARCHITECTURE.md +79 -0
- package/docs/BASELINES.md +32 -0
- package/docs/CASE_STUDIES.md +106 -0
- package/docs/CODEOWNERS.md +23 -0
- package/docs/DASHBOARD.md +87 -0
- package/docs/EVIDENCE.md +55 -0
- package/docs/LAUNCH_PLAYBOOK.md +103 -0
- package/docs/MONOREPOS.md +74 -0
- package/docs/POLICY.md +98 -0
- package/docs/PROOF_PACKS.md +57 -0
- package/docs/PR_COMMENTS.md +56 -0
- package/docs/RELEASE.md +35 -0
- package/docs/ROADMAP.md +152 -0
- package/docs/RULE_CATALOG.md +90 -0
- package/docs/SARIF.md +74 -0
- package/docs/SCHEMAS.md +49 -0
- package/docs/SECURITY_POSTURE.md +32 -0
- package/docs/STACK_COVERAGE.md +20 -0
- package/docs/assets/patchdrill-demo.svg +21 -0
- package/docs/media/patchdrill-dashboard.png +0 -0
- package/docs/media/patchdrill-demo.gif +0 -0
- package/examples/case-studies/README.md +20 -0
- package/examples/demo/README.md +21 -0
- package/examples/demo/patchdrill-demo-summary.md +35 -0
- package/examples/demo/patchdrill-demo.html +623 -0
- package/examples/demo/patchdrill-demo.json +355 -0
- package/examples/demo/patchdrill-demo.md +120 -0
- package/examples/demo/patchdrill-demo.sarif +195 -0
- package/examples/report.md +128 -0
- package/examples/risky-agent-pr/README.md +15 -0
- package/examples/risky-agent-pr/patchdrill-demo-summary.md +41 -0
- package/examples/risky-agent-pr/patchdrill-demo.html +681 -0
- package/examples/risky-agent-pr/patchdrill-demo.json +483 -0
- package/examples/risky-agent-pr/patchdrill-demo.md +140 -0
- package/examples/risky-agent-pr/patchdrill-demo.sarif +398 -0
- package/fixtures/stacks/README.md +4 -0
- package/fixtures/stacks/android-gradle/fixture.json +33 -0
- package/fixtures/stacks/aspnet-core-service/fixture.json +36 -0
- package/fixtures/stacks/bazel-workspace/fixture.json +30 -0
- package/fixtures/stacks/buck2-workspace/fixture.json +30 -0
- package/fixtures/stacks/cargo-workspace/fixture.json +48 -0
- package/fixtures/stacks/django-app/fixture.json +25 -0
- package/fixtures/stacks/docker-compose/fixture.json +17 -0
- package/fixtures/stacks/dockerfile-service/fixture.json +17 -0
- package/fixtures/stacks/dotnet-service/fixture.json +36 -0
- package/fixtures/stacks/dotnet-solution-filter/fixture.json +62 -0
- package/fixtures/stacks/fastapi-app/fixture.json +29 -0
- package/fixtures/stacks/go-workspace/fixture.json +48 -0
- package/fixtures/stacks/java-gradle/fixture.json +29 -0
- package/fixtures/stacks/java-maven/fixture.json +32 -0
- package/fixtures/stacks/kubernetes-helm/fixture.json +25 -0
- package/fixtures/stacks/kubernetes-kustomize/fixture.json +21 -0
- package/fixtures/stacks/nested-go-workspace/fixture.json +51 -0
- package/fixtures/stacks/nextjs-app/fixture.json +34 -0
- package/fixtures/stacks/node-turbo-workspace/fixture.json +39 -0
- package/fixtures/stacks/pants-python/fixture.json +33 -0
- package/fixtures/stacks/php-composer/fixture.json +31 -0
- package/fixtures/stacks/python-service/fixture.json +21 -0
- package/fixtures/stacks/rails-app/fixture.json +25 -0
- package/fixtures/stacks/spring-boot-gradle/fixture.json +29 -0
- package/fixtures/stacks/spring-boot-maven/fixture.json +43 -0
- package/fixtures/stacks/swift-package/fixture.json +21 -0
- package/fixtures/stacks/terraform-module/fixture.json +17 -0
- package/fixtures/stacks/uv-python-service/fixture.json +47 -0
- package/fixtures/stacks/xcode-app/fixture.json +72 -0
- package/package.json +80 -0
- package/schemas/patchdrill-doctor.schema.json +171 -0
- package/schemas/patchdrill-evidence.schema.json +239 -0
- package/schemas/patchdrill-policy.schema.json +170 -0
- package/schemas/patchdrill-release-check.schema.json +78 -0
- package/schemas/patchdrill-report.schema.json +647 -0
package/README.md
ADDED
|
@@ -0,0 +1,601 @@
|
|
|
1
|
+
# PatchDrill
|
|
2
|
+
|
|
3
|
+
[](https://github.com/seungdori/patchdrill/actions/workflows/ci.yml)
|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
## Your AI reviewer says LGTM. CI is green. The PR still shouldn't merge.
|
|
12
|
+
|
|
13
|
+
PatchDrill is the **deterministic proof layer between code review and CI** for AI-generated and human patches. It reads the git diff and tells you exactly what proof should exist before you merge — **no model call, no network, the same answer every time.**
|
|
14
|
+
|
|
15
|
+
**Not a linter. Not SAST. Not an AI reviewer.** It answers the one question those tools never ask: *what proof should exist for THIS diff before merge — and what's missing?*
|
|
16
|
+
|
|
17
|
+
[](docs/media/patchdrill-dashboard.png)
|
|
18
|
+
|
|
19
|
+
*An AI agent opened this PR. PatchDrill scored it **FAIL · 94/100** — a privileged `pull_request_target` workflow checkout, a leaked secret, a disabled test script — in one offline, deterministic command. No model call. (Click for the full still report; regenerate the GIF with `vhs demo/patchdrill.tape`.)*
|
|
20
|
+
|
|
21
|
+
**What it catches in a diff:**
|
|
22
|
+
|
|
23
|
+
- **Leaked secrets** — `.env` files, private keys, and token-shaped strings added in the patch
|
|
24
|
+
- **Prompt injection** — instructions slipped into `AGENTS.md`, issue templates, and docs an agent will read
|
|
25
|
+
- **Workflow escalation** — broad token writes, `pull_request_target`, OIDC exchange, `secrets: inherit`, unpinned actions, remote-script pipes
|
|
26
|
+
- **Missing proof** — source changed with no test changed; required checks planned but never run
|
|
27
|
+
- **Dependency drift** — manifest changes with no matching lockfile (and lockfile drift with no manifest intent)
|
|
28
|
+
- **The verification it implies** — the actual commands for the *changed* packages + downstream dependents across ~25 ecosystems, not just root-level defaults
|
|
29
|
+
|
|
30
|
+
> **Built for teams merging AI-/agent-authored PRs who can't eyeball every diff anymore.** Run it locally in 30 seconds — no config, no CI changes, no API key:
|
|
31
|
+
>
|
|
32
|
+
> ```bash
|
|
33
|
+
> npx --yes github:seungdori/patchdrill demo --scenario risky-agent-pr
|
|
34
|
+
> ```
|
|
35
|
+
|
|
36
|
+
Output is a portable **Proof Pack** — Markdown, JSON, SARIF, a self-contained HTML dashboard, and a hash-stamped evidence manifest — that a human, a CI gate, an auditor, or a frontier model can all inspect. Run it in your language with `--locale ko|ja|zh`.
|
|
37
|
+
|
|
38
|
+
## 30-Second Demo
|
|
39
|
+
|
|
40
|
+
Generate a risky AI-agent PR scenario without needing a git repository:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx --yes github:seungdori/patchdrill demo --scenario risky-agent-pr --output patchdrill-risky-demo
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Then inspect the reviewer-facing artifacts:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
cat patchdrill-risky-demo/patchdrill-demo-summary.md
|
|
50
|
+
open patchdrill-risky-demo/patchdrill-demo.html
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
PatchDrill should show a privileged workflow boundary, secret-looking content, package lifecycle script risk, and the verification plan a reviewer should ask for before merge.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npx --yes github:seungdori/patchdrill scan --base origin/main --run \
|
|
57
|
+
--evidence patchdrill-evidence.json \
|
|
58
|
+
--summary-markdown patchdrill-summary.md \
|
|
59
|
+
--markdown patchdrill-report.md \
|
|
60
|
+
--json patchdrill-report.json \
|
|
61
|
+
--sarif patchdrill.sarif \
|
|
62
|
+
--html patchdrill-dashboard.html \
|
|
63
|
+
--fail-on high \
|
|
64
|
+
--max-risk 69
|
|
65
|
+
npx --yes github:seungdori/patchdrill verify --evidence patchdrill-evidence.json
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Why Star It
|
|
69
|
+
|
|
70
|
+
- Makes AI-era PRs reviewable without asking another model to be the source of truth.
|
|
71
|
+
- Builds a Proof Pack for each patch: Markdown for humans, JSON for bots with required structured verification status, SARIF for GitHub code scanning, a self-contained HTML dashboard, compact PR summaries, and a later-verifiable audit manifest with report, artifact, and command-output hashes.
|
|
72
|
+
- Works locally first and in CI later. `scan` never mutates the repository, and commands only run when `--run` is set.
|
|
73
|
+
- Flags the review surfaces that routinely hide regressions: auth, billing, migrations, secrets, CI workflow supply chain, package automation scripts, infra, lockfiles, large diffs, prompt-injection content, missing test changes, and required checks that were planned but not run.
|
|
74
|
+
- Infers reviewable commands from the patch instead of only running root-level defaults.
|
|
75
|
+
- Works with the tools you already have: git, npm, pnpm, yarn, bun, pytest, Django, FastAPI, cargo, Go, Maven, Gradle, Spring Boot, Android Gradle, Ruby, Rails, RSpec, PHP, Composer, Laravel, dotnet, ASP.NET Core, Swift, Xcode, Terraform, Docker, Kubernetes, Helm, Bazel, and Buck2.
|
|
76
|
+
- Supports policy-as-code through `.patchdrill.yml`, including default, regulated, and agentic starter packs.
|
|
77
|
+
- Ships with serious open-source security posture: CodeQL, OpenSSF Scorecard, Dependabot, strict tests, and package dry-run verification.
|
|
78
|
+
- Understands Node, Cargo, Go, and Pants workspaces, plus nested Python projects, nested Cargo and Go workspaces, Turborepo, and Nx, targeting changed packages plus downstream dependents instead of blindly running only root-level commands.
|
|
79
|
+
- Includes first-party stack fixtures for Node/Turborepo, Next.js, Python, uv-managed Python, Django, FastAPI, Rails, PHP/Composer, Terraform, Docker/Compose, Kubernetes/Helm/Kustomize, Java/Maven/Gradle, Spring Boot Maven/Gradle, Android Gradle, .NET, ASP.NET Core, SwiftPM, Xcode, Bazel, Buck2, Pants, Cargo, and Go repository shapes.
|
|
80
|
+
- Explains package.json, pyproject.toml, requirements.txt, NuGet PackageReference and central PackageVersion files, Maven pom.xml, Gradle build files and version catalogs, Gemfile, composer.json, go.mod, Cargo.toml, npm package-lock, pnpm-lock, yarn.lock, bun.lock, go.sum, Cargo.lock, poetry.lock, uv.lock, Pipfile.lock, Gemfile.lock, and composer.lock dependency additions, removals, and version updates instead of only saying "lockfile changed."
|
|
81
|
+
- Flags dependency proof gaps such as manifest-only dependency changes or lockfile-only resolution drift.
|
|
82
|
+
- Adds CODEOWNERS owner hints to changed files so reviewers can see the responsible teams.
|
|
83
|
+
- Includes launch-friendly case studies, a public stack coverage matrix, and per-command verification status so teams can evaluate what evidence PatchDrill actually emits.
|
|
84
|
+
|
|
85
|
+
## What It Does
|
|
86
|
+
|
|
87
|
+
PatchDrill answers four questions every reviewer asks:
|
|
88
|
+
|
|
89
|
+
1. What changed?
|
|
90
|
+
2. Which parts of the stack are touched?
|
|
91
|
+
3. What should be run to prove this patch?
|
|
92
|
+
4. What risk remains after the drill?
|
|
93
|
+
|
|
94
|
+
PatchDrill is not another AI code reviewer. It does not ask a model whether a diff "looks good." It builds deterministic evidence:
|
|
95
|
+
|
|
96
|
+
| Layer | Primary question | Deterministic? | Runs commands? | Output |
|
|
97
|
+
| --- | --- | --- | --- | --- |
|
|
98
|
+
| AI PR reviewer | Does this diff look right? | No | Usually no | Comments, suggestions, design feedback |
|
|
99
|
+
| Traditional CI | Did preconfigured checks pass? | Yes | Yes | Logs and pass/fail status |
|
|
100
|
+
| SAST/SCA scanner | Does this match a known security or dependency rule? | Yes | Sometimes | Alerts and vulnerability findings |
|
|
101
|
+
| Review automation | Did configured review automation fire? | Yes | Sometimes | PR comments and annotations |
|
|
102
|
+
| PatchDrill | What proof should exist for this diff? | Yes | Only with `--run` | Proof Pack, risk findings, command plan, policy gate |
|
|
103
|
+
|
|
104
|
+
The boundary is intentional: models are good at judgment, while PatchDrill is good at producing the same reviewable safety evidence for the same patch every time. Run PatchDrill first, then hand the Proof Pack to a human reviewer, CI gate, audit trail, or frontier model.
|
|
105
|
+
|
|
106
|
+
## Proof Pack
|
|
107
|
+
|
|
108
|
+
A Proof Pack is the portable evidence bundle generated for a patch:
|
|
109
|
+
|
|
110
|
+
- Compact Markdown summary for PR comments and step summaries.
|
|
111
|
+
- Full Markdown report for human review.
|
|
112
|
+
- JSON report for bots, dashboards, and policy gates.
|
|
113
|
+
- SARIF report for GitHub code scanning.
|
|
114
|
+
- Self-contained HTML dashboard, including optional trend history.
|
|
115
|
+
- Evidence manifest that records report, artifact, and command-output digests.
|
|
116
|
+
|
|
117
|
+
See [docs/EVIDENCE.md](docs/EVIDENCE.md) for manifest verification and [docs/PROOF_PACKS.md](docs/PROOF_PACKS.md) for how to use Proof Packs in review workflows.
|
|
118
|
+
|
|
119
|
+
Print the boundary and suggested first commands from the CLI:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
patchdrill explain
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Example summary:
|
|
126
|
+
|
|
127
|
+
```text
|
|
128
|
+
PatchDrill Gate PASS - assessment WARN, risk 42/100, confidence 58/100
|
|
129
|
+
Gate policy: fail-on critical, max-risk 69
|
|
130
|
+
Changed files: 4, +121/-18
|
|
131
|
+
Required commands: 3, optional commands: 1
|
|
132
|
+
Verification evidence: 0 run, 0 passed, 0 failed, 0 timed out, 3 missing required, 1 optional skipped
|
|
133
|
+
Added lines inspected: 121
|
|
134
|
+
Top findings:
|
|
135
|
+
- [high] High-impact product area changed (src/auth/session.ts)
|
|
136
|
+
- [medium] Source changed without test changes
|
|
137
|
+
Run with --run to execute required verification commands. Add --run-optional to include optional checks.
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Install
|
|
141
|
+
|
|
142
|
+
Run it instantly with no install, straight from GitHub:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
npx --yes github:seungdori/patchdrill scan --base origin/main
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Once the npm package is published, the same works without the `github:` prefix:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
npx patchdrill scan --base origin/main
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Or install the published package globally:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npm install -g patchdrill
|
|
158
|
+
patchdrill scan --base origin/main
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The examples below use `patchdrill` for readability. Replace it with `npx --yes github:seungdori/patchdrill` when running directly from this repository.
|
|
162
|
+
|
|
163
|
+
## Quickstart
|
|
164
|
+
|
|
165
|
+
Try the output without a git repository:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
patchdrill demo --output patchdrill-demo
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Try the failure case that shows what PatchDrill catches in an agent-authored PR:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
patchdrill demo --scenario risky-agent-pr --output patchdrill-risky-demo
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Diagnose what PatchDrill can infer from your repository before changing CI:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
patchdrill doctor
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
For automation:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
patchdrill doctor --format json
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Analyze uncommitted work:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
patchdrill scan
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Analyze a branch against `main`:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
patchdrill scan --base origin/main
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Run the inferred required commands:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
patchdrill scan --base origin/main --run
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Include optional checks such as browser/e2e and static-analysis plans:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
patchdrill scan --base origin/main --run --run-optional
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Write and verify a Proof Pack:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
patchdrill scan --base origin/main --run \
|
|
217
|
+
--evidence patchdrill-evidence.json \
|
|
218
|
+
--summary-markdown patchdrill-summary.md \
|
|
219
|
+
--markdown patchdrill-report.md \
|
|
220
|
+
--json patchdrill-report.json \
|
|
221
|
+
--sarif patchdrill.sarif \
|
|
222
|
+
--html patchdrill-dashboard.html
|
|
223
|
+
patchdrill verify --evidence patchdrill-evidence.json
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Create a static dashboard from a saved JSON report:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
patchdrill dashboard --json patchdrill-report.json --output patchdrill-dashboard.html
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
`patchdrill dashboard` validates each saved JSON report contract before rendering, so stale or incomplete reports do not become polished dashboards.
|
|
233
|
+
|
|
234
|
+
Verify an evidence manifest against its generated artifacts:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
patchdrill verify --evidence patchdrill-evidence.json
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Check whether this repository is ready for npm/GitHub Action release:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
patchdrill release-check
|
|
244
|
+
patchdrill release-check --format json
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
The release workflow also runs required PatchDrill verification, generates a local Proof Pack smoke bundle, and verifies its evidence manifest before `npm pack --dry-run`.
|
|
248
|
+
|
|
249
|
+
For automation:
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
patchdrill release-check --format json
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Regenerate an evidence manifest after final artifact post-processing:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
patchdrill evidence --json patchdrill-report.json --evidence patchdrill-evidence.json \
|
|
259
|
+
--summary-markdown patchdrill-summary.md \
|
|
260
|
+
--markdown patchdrill-report.md \
|
|
261
|
+
--sarif patchdrill.sarif \
|
|
262
|
+
--html patchdrill-dashboard.html
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
`patchdrill evidence` validates the saved JSON report contract first, including the required structured verification status, before writing the manifest.
|
|
266
|
+
|
|
267
|
+
See committed demo outputs in [examples/demo](examples/demo), including `patchdrill-demo-summary.md` as the PR comment preview.
|
|
268
|
+
|
|
269
|
+
Read the launch case studies in [docs/CASE_STUDIES.md](docs/CASE_STUDIES.md) and the fixture-backed support matrix in [docs/STACK_COVERAGE.md](docs/STACK_COVERAGE.md).
|
|
270
|
+
|
|
271
|
+
Add repeated JSON reports in oldest-to-newest order to show run trends:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
patchdrill dashboard --json previous-report.json --json patchdrill-report.json --output patchdrill-dashboard.html
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Use the GitHub Action with PR comments:
|
|
278
|
+
|
|
279
|
+
```yaml
|
|
280
|
+
- uses: seungdori/patchdrill@v0
|
|
281
|
+
with:
|
|
282
|
+
base: origin/${{ github.base_ref }}
|
|
283
|
+
pr-comment: "true"
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
The Action emits GitHub Checks annotations by default. See [docs/ANNOTATIONS.md](docs/ANNOTATIONS.md).
|
|
287
|
+
|
|
288
|
+
Use policy-as-code:
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
patchdrill scan --config .patchdrill.yml
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Export JSON Schemas for editors and bots:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
patchdrill schema policy > patchdrill-policy.schema.json
|
|
298
|
+
patchdrill schema report > patchdrill-report.schema.json
|
|
299
|
+
patchdrill schema evidence > patchdrill-evidence.schema.json
|
|
300
|
+
patchdrill schema doctor > patchdrill-doctor.schema.json
|
|
301
|
+
patchdrill schema release-check > patchdrill-release-check.schema.json
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Compare against a previous report:
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
patchdrill scan --baseline previous-patchdrill-report.json --max-risk-delta 0 --json patchdrill-report.json
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
Add a GitHub Actions workflow:
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
patchdrill init
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Add a workflow and starter policy:
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
patchdrill init --policy
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Use a stricter starter policy pack:
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
patchdrill init --policy-pack regulated
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## CLI
|
|
329
|
+
|
|
330
|
+
```text
|
|
331
|
+
patchdrill scan [options]
|
|
332
|
+
patchdrill dashboard --json <report.json> [--json <report.json>...] [--output <dashboard.html>]
|
|
333
|
+
patchdrill demo [--scenario <name>] [--output <directory>]
|
|
334
|
+
patchdrill doctor [--format text|json]
|
|
335
|
+
patchdrill evidence --json <report.json> --evidence <evidence.json> [artifact options]
|
|
336
|
+
patchdrill init [--force] [--policy] [--policy-pack <name>]
|
|
337
|
+
patchdrill explain
|
|
338
|
+
patchdrill release-check [--format text|json]
|
|
339
|
+
patchdrill schema [policy|report|evidence|doctor|release-check] [--output <path>]
|
|
340
|
+
patchdrill verify --evidence <patchdrill-evidence.json>
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Options:
|
|
344
|
+
|
|
345
|
+
| Option | Description |
|
|
346
|
+
| --- | --- |
|
|
347
|
+
| `--base <ref>` | Compare against a base ref, for example `origin/main`. |
|
|
348
|
+
| `--head <ref>` | Head ref when using `--base`, default `HEAD`. |
|
|
349
|
+
| `--config <path>` | Read policy from `.patchdrill.yml/json` or a specific path. |
|
|
350
|
+
| `--baseline <path>` | Compare against a previous PatchDrill JSON report. |
|
|
351
|
+
| `--evidence <path>` | Write a Proof Pack evidence manifest during `scan`/`evidence`, or select one for `verify`. `scan --evidence` requires `--json` so the manifest can verify the report contract. |
|
|
352
|
+
| `--run` | Execute required inferred verification commands. |
|
|
353
|
+
| `--run-optional` | With `--run`, also execute optional verification commands. |
|
|
354
|
+
| `--github-annotations` | Emit GitHub Actions log annotations for findings. |
|
|
355
|
+
| `--summary-markdown <path>` | Write a compact Markdown summary for PR comments or step summaries. |
|
|
356
|
+
| `--markdown <path>` | Write a Markdown report. |
|
|
357
|
+
| `--json <path>` | Write a JSON report. |
|
|
358
|
+
| `--sarif <path>` | Write a SARIF report for GitHub code scanning. |
|
|
359
|
+
| `--html <path>` | Write a self-contained static HTML dashboard. |
|
|
360
|
+
| `--fail-on <level>` | Fail when findings meet severity: `info`, `low`, `medium`, `high`, `critical`. |
|
|
361
|
+
| `--max-risk <score>` | Fail when risk score is above a 0-100 threshold, default `69`. |
|
|
362
|
+
| `--max-risk-delta <score>` | Fail when baseline risk increase is above a 0-100 threshold. Requires `--baseline`. |
|
|
363
|
+
| `--max-output-chars <n>` | Keep the last `n` characters from each command output stream, default `20000`. |
|
|
364
|
+
| `--command-timeout-ms <n>` | Stop each verification command after `n` milliseconds. |
|
|
365
|
+
| `--quiet` | Only use exit code. |
|
|
366
|
+
| `--locale <lang>` | Language for human-facing reports (markdown, summary, HTML, console): `en`, `ko`, `ja`, `zh`. Defaults to the system locale (`LC_ALL`/`LANG`), then English. JSON and SARIF stay English. |
|
|
367
|
+
| `--policy` | Create `.patchdrill.yml` when used with `patchdrill init`. |
|
|
368
|
+
| `--policy-pack <name>` | Starter policy pack for `patchdrill init`: `default`, `regulated`, `agentic`. |
|
|
369
|
+
| `--scenario <name>` | Demo scenario for `patchdrill demo`: `review-ready`, `risky-agent-pr`. |
|
|
370
|
+
| `--format <format>` | Output format for `doctor` and `release-check`: `text`, `json`. |
|
|
371
|
+
| `--list` | List available schemas when used with `patchdrill schema`. |
|
|
372
|
+
| `--output <path>` | Write a schema/dashboard file or demo artifact directory. |
|
|
373
|
+
|
|
374
|
+
Boolean flags accept explicit values such as `--run=false`, `--quiet=true`, and `--github-annotations=off`.
|
|
375
|
+
|
|
376
|
+
## Supported Signals
|
|
377
|
+
|
|
378
|
+
PatchDrill detects project shape from repo manifests:
|
|
379
|
+
|
|
380
|
+
| Ecosystem | Signals | Typical commands |
|
|
381
|
+
| --- | --- | --- |
|
|
382
|
+
| Node | `package.json`, lockfiles, scripts | `npm run typecheck`, `npm run check:types`, `npm run lint`, `npm run test`, `npm run test:unit`, `npm run build`, optional `npm run test:e2e` |
|
|
383
|
+
| Python | `pyproject.toml`, `uv.lock`, `requirements.txt`, `setup.py`, `manage.py`, nested Python package roots, `FastAPI()`, FastAPI routers/dependencies, Ruff/mypy/Pyright config | `uv run pytest tests/test_module.py`, `cd packages/api && uv run pytest`, `python -m pytest`, `python manage.py test`, `python -m compileall .`, optional `uv run ruff check .`, optional `uv run mypy .`, optional `uv run pyright`, FastAPI app and changed-module import smoke |
|
|
384
|
+
| Rust | `Cargo.toml`, root and nested Cargo workspaces | `cargo test --all-targets`, `cargo test -p crate --all-targets`, `cargo test --manifest-path packages/wasm/Cargo.toml -p crate --all-targets`, `cargo clippy -p crate --all-targets -- -D warnings` |
|
|
385
|
+
| Go | `go.mod`, `go.work`, nested Go module and workspace roots | `go test ./...`, `cd services/api && go test ./...`, `go test ./module/...`, `cd services/go && go test ./module/...`, `go vet ./module/...` |
|
|
386
|
+
| Java/Kotlin | `pom.xml`, `build.gradle`, wrappers | `mvn test`, `gradle test`, `./gradlew test`, `./gradlew bootJar` |
|
|
387
|
+
| Android | `com.android.application`, `com.android.library`, `AndroidManifest.xml`, build types, product flavors, `variantFilter`, variant source sets, generated source paths | `./gradlew testDebugUnitTest`, `./gradlew testReleaseUnitTest`, `./gradlew testFreeDebugUnitTest`, `./gradlew testMinApi24DemoDebugUnitTest`, `./gradlew assemble<Variant>`, `./gradlew lint<Variant>` |
|
|
388
|
+
| Ruby/Rails | `Gemfile`, `Gemfile.lock`, `config/application.rb`, RSpec metadata | `bin/rails test`, `bundle exec rails test`, `bundle exec rspec`, `bundle exec rake test` |
|
|
389
|
+
| PHP/Laravel | `composer.json`, `composer.lock`, `artisan`, `phpunit.xml` | `composer validate --strict`, `composer test`, `php artisan test`, `vendor/bin/phpunit`, PHP syntax lint fallback |
|
|
390
|
+
| .NET | `global.json`, `.slnf`, `.sln`, `.csproj`, `ProjectReference` | `dotnet test App.slnf`, `dotnet test tests/Api.Tests/Api.Tests.csproj`, `dotnet build src/Api/Api.csproj --no-restore`, `dotnet publish src/Api/Api.csproj --no-restore` |
|
|
391
|
+
| Swift | `Package.swift`, `Package.resolved`, `*.swift` | `swift test`, `swift build` |
|
|
392
|
+
| Xcode | `.xcworkspace`, `.xcodeproj`, shared `.xcscheme`, `.xctestplan`, Apple app source/resources, scheme target platforms | `xcodebuild -workspace App.xcworkspace -scheme App -testPlan AppTests test`, `xcodebuild -project App.xcodeproj -scheme App -destination generic/platform=iOS build`, `xcodebuild -project App.xcodeproj -scheme App -showdestinations` |
|
|
393
|
+
| Terraform | `*.tf`, `*.tfvars` | `terraform fmt -check && terraform validate` |
|
|
394
|
+
| Docker | `Dockerfile`, Compose files | `docker build .`, `docker compose -f compose.yaml config` |
|
|
395
|
+
| Kubernetes | `Chart.yaml`, `kustomization.yaml`, `k8s/`, `kubernetes/`, `manifests/` | `helm lint .`, `kubectl kustomize .`, `kubectl apply --dry-run=client -f k8s` |
|
|
396
|
+
| Bazel | `MODULE.bazel`, `WORKSPACE`, `BUILD.bazel`, `.bazelrc` | `bazel test //path/...`, `bazel build //path/...`, `bazel query 'rdeps(//..., set(//path/...))'`, optional downstream `tests(rdeps(...))` promotion, graph-wide fallback for root metadata |
|
|
397
|
+
| Buck2 | `.buckconfig`, `BUCK`, `BUCK.v2` | `buck2 test //path/...`, `buck2 build //path/...`, `buck2 uquery 'rdeps(//..., set(//path/...))'`, optional downstream `testsof(rdeps(...))` promotion, graph-wide fallback for root metadata |
|
|
398
|
+
| Pants | `pants.toml` | `pants --changed-since=HEAD --changed-dependents=transitive test` |
|
|
399
|
+
| GitHub Actions | `.github/workflows/*` | workflow diff review |
|
|
400
|
+
|
|
401
|
+
For Node workspaces, PatchDrill detects `package.json` workspaces and `pnpm-workspace.yaml`, then emits package-scoped commands such as `pnpm --filter @acme/api run test` or `npm --workspace @acme/api run build` for directly changed packages and downstream dependents. When `turbo.json` or `nx.json` is present, it plans native task-runner commands such as `pnpm exec turbo run test --filter=@acme/api` or `npx nx run api:test`. See [docs/MONOREPOS.md](docs/MONOREPOS.md).
|
|
402
|
+
|
|
403
|
+
For nested Python projects, PatchDrill treats each discovered `pyproject.toml`, `uv.lock`, `requirements.txt`, or `manage.py` package root as its own verification scope, so a monorepo can plan `cd packages/pine-engine && uv run pytest` instead of incorrectly collapsing every Python change into a root command.
|
|
404
|
+
|
|
405
|
+
For Cargo workspaces, including workspaces nested below a JavaScript or polyglot monorepo root, PatchDrill reads `[workspace].members`, crate names, and workspace-internal dependencies, then emits `cargo test -p crate --all-targets` or `cargo test --manifest-path packages/wasm/Cargo.toml -p crate --all-targets` plus optional clippy plans for changed crates and downstream dependent crates.
|
|
406
|
+
|
|
407
|
+
For nested Go modules and Go workspaces, PatchDrill treats each discovered `go.mod` or `go.work` root as its own verification scope. For Go workspaces, PatchDrill reads `go.work` `use` entries, module names, and workspace-internal `require` dependencies, then emits `go test ./module/...` or `cd services/go && go test ./module/...` plus optional `go vet` plans for changed modules and downstream dependent modules.
|
|
408
|
+
|
|
409
|
+
For Pants repositories, PatchDrill uses Pants' native Git-aware changed target selection with `--changed-since` and `--changed-dependents=transitive`, so Pants keeps ownership of target graph expansion across languages.
|
|
410
|
+
|
|
411
|
+
## Risk Model
|
|
412
|
+
|
|
413
|
+
PatchDrill scores a patch from 0 to 100. Higher is riskier.
|
|
414
|
+
|
|
415
|
+
The current deterministic rules look for:
|
|
416
|
+
|
|
417
|
+
- Any changed files that need review and verification evidence.
|
|
418
|
+
- Secret-bearing files such as `.env` and private keys.
|
|
419
|
+
- Secret-looking values added inside the diff, including private keys and common token formats.
|
|
420
|
+
- Prompt-injection instructions added to agent-visible files such as `AGENTS.md`, issue templates, and Markdown docs.
|
|
421
|
+
- High-impact paths: auth, billing, sessions, migrations, security, crypto, permissions.
|
|
422
|
+
- Infra and release behavior: Docker, Terraform, Kubernetes, GitHub Actions.
|
|
423
|
+
- Workflow supply-chain risk: broad token writes, `pull_request_target`, inherited secrets, local reusable workflow fan-out to mutable remote reusable workflows, mutable reusable workflows receiving inherited secrets or caller OIDC permissions, environment-scoped OIDC deployment jobs, cloud OIDC credential exchange without environment protection, unpinned actions, mutable `docker://` action images, remote script pipes, untrusted PR metadata interpolation, and privileged PR-head checkout combinations.
|
|
424
|
+
- Package automation script risk: install/prepare/pack/publish lifecycle scripts, verification scripts removed or replaced with no-op commands, and package scripts that pipe remote downloads into interpreters.
|
|
425
|
+
- Dependency manifest and lockfile changes.
|
|
426
|
+
- package.json, pyproject.toml, requirements.txt, NuGet PackageReference and central PackageVersion files, Maven pom.xml, Gradle build files and version catalogs, Gemfile, composer.json, go.mod, Cargo.toml, npm package-lock, pnpm-lock, yarn.lock, bun.lock, go.sum, Cargo.lock, poetry.lock, uv.lock, Pipfile.lock, Gemfile.lock, and composer.lock dependency additions, removals, and updates.
|
|
427
|
+
- Dependency proof gaps: direct dependency manifest changes without matching lockfile evidence, and lockfile resolution changes without matching manifest dependency intent.
|
|
428
|
+
- Legacy binary `bun.lockb` changes with guidance to migrate toward the text `bun.lock` format.
|
|
429
|
+
- Source changes without nearby, mirrored, or framework-convention matching test changes.
|
|
430
|
+
- Large line deltas and binary files.
|
|
431
|
+
- Required verification commands that were inferred or configured but not run.
|
|
432
|
+
- Failed verification commands.
|
|
433
|
+
- Custom policy rules from `.patchdrill.yml`.
|
|
434
|
+
|
|
435
|
+
The risk model is intentionally explainable. Every score increase is represented as a finding in the report.
|
|
436
|
+
|
|
437
|
+
See [docs/RULE_CATALOG.md](docs/RULE_CATALOG.md) for the built-in rule IDs and what each one means.
|
|
438
|
+
|
|
439
|
+
## Policy-As-Code
|
|
440
|
+
|
|
441
|
+
PatchDrill reads `.patchdrill.yml`, `.patchdrill.yaml`, or `.patchdrill.json` from the repository root.
|
|
442
|
+
|
|
443
|
+
```yaml
|
|
444
|
+
failOn: high
|
|
445
|
+
maxRisk: 69
|
|
446
|
+
|
|
447
|
+
ignoredPaths:
|
|
448
|
+
- generated/**
|
|
449
|
+
|
|
450
|
+
requiredCommands:
|
|
451
|
+
- id: contract-tests
|
|
452
|
+
command: npm run test:contracts
|
|
453
|
+
reason: API surfaces changed.
|
|
454
|
+
|
|
455
|
+
rules:
|
|
456
|
+
- id: payments-owner-review
|
|
457
|
+
title: Payments owner review required
|
|
458
|
+
severity: critical
|
|
459
|
+
path: src/payments/**
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
See [docs/POLICY.md](docs/POLICY.md).
|
|
463
|
+
|
|
464
|
+
## GitHub Actions
|
|
465
|
+
|
|
466
|
+
Generate a workflow:
|
|
467
|
+
|
|
468
|
+
```bash
|
|
469
|
+
patchdrill init
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
Or add it manually:
|
|
473
|
+
|
|
474
|
+
```yaml
|
|
475
|
+
name: PatchDrill
|
|
476
|
+
|
|
477
|
+
on:
|
|
478
|
+
pull_request:
|
|
479
|
+
|
|
480
|
+
permissions:
|
|
481
|
+
contents: read
|
|
482
|
+
pull-requests: write
|
|
483
|
+
security-events: write
|
|
484
|
+
|
|
485
|
+
jobs:
|
|
486
|
+
patchdrill:
|
|
487
|
+
runs-on: ubuntu-latest
|
|
488
|
+
steps:
|
|
489
|
+
- uses: actions/checkout@v6
|
|
490
|
+
with:
|
|
491
|
+
fetch-depth: 0
|
|
492
|
+
- uses: seungdori/patchdrill@v0
|
|
493
|
+
id: patchdrill
|
|
494
|
+
with:
|
|
495
|
+
base: origin/${{ github.base_ref }}
|
|
496
|
+
evidence: patchdrill-evidence.json
|
|
497
|
+
summary: patchdrill-summary.md
|
|
498
|
+
markdown: patchdrill-report.md
|
|
499
|
+
json: patchdrill-report.json
|
|
500
|
+
sarif: patchdrill.sarif
|
|
501
|
+
html: patchdrill-dashboard.html
|
|
502
|
+
fail-on: high
|
|
503
|
+
max-risk: "69"
|
|
504
|
+
run: "true"
|
|
505
|
+
command-timeout-ms: "600000"
|
|
506
|
+
annotations: "true"
|
|
507
|
+
step-summary: "true"
|
|
508
|
+
pr-comment: "true"
|
|
509
|
+
# Optional: newline-separated previous JSON reports downloaded from earlier artifacts.
|
|
510
|
+
# dashboard-history: |
|
|
511
|
+
# reports/patchdrill-previous.json
|
|
512
|
+
- uses: github/codeql-action/upload-sarif@v4
|
|
513
|
+
if: always()
|
|
514
|
+
with:
|
|
515
|
+
sarif_file: ${{ steps.patchdrill.outputs.report-sarif }}
|
|
516
|
+
- uses: actions/upload-artifact@v7
|
|
517
|
+
if: always()
|
|
518
|
+
with:
|
|
519
|
+
name: patchdrill-report
|
|
520
|
+
path: |
|
|
521
|
+
${{ steps.patchdrill.outputs.report-evidence }}
|
|
522
|
+
${{ steps.patchdrill.outputs.report-markdown }}
|
|
523
|
+
${{ steps.patchdrill.outputs.report-summary }}
|
|
524
|
+
${{ steps.patchdrill.outputs.report-json }}
|
|
525
|
+
${{ steps.patchdrill.outputs.report-html }}
|
|
526
|
+
${{ steps.patchdrill.outputs.report-sarif }}
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
Action boolean inputs accept explicit values: `"true"`, `"false"`, `"1"`, `"0"`, `"yes"`, `"no"`, `"on"`, and `"off"`. Execution and annotation toggles are passed through the same CLI boolean parser, so `run: "false"` never executes repository commands.
|
|
530
|
+
|
|
531
|
+
## Example Report
|
|
532
|
+
|
|
533
|
+
See [examples/report.md](examples/report.md).
|
|
534
|
+
For Proof Pack review workflows, see [docs/PROOF_PACKS.md](docs/PROOF_PACKS.md).
|
|
535
|
+
For code scanning integration, see [docs/SARIF.md](docs/SARIF.md).
|
|
536
|
+
For repository security posture, see [docs/SECURITY_POSTURE.md](docs/SECURITY_POSTURE.md).
|
|
537
|
+
For pull request comments, see [docs/PR_COMMENTS.md](docs/PR_COMMENTS.md).
|
|
538
|
+
For static HTML dashboards, see [docs/DASHBOARD.md](docs/DASHBOARD.md).
|
|
539
|
+
For evidence manifest verification, see [docs/EVIDENCE.md](docs/EVIDENCE.md).
|
|
540
|
+
For machine-readable schemas, see [docs/SCHEMAS.md](docs/SCHEMAS.md).
|
|
541
|
+
For owner hints, see [docs/CODEOWNERS.md](docs/CODEOWNERS.md).
|
|
542
|
+
For risk deltas, see [docs/BASELINES.md](docs/BASELINES.md).
|
|
543
|
+
For the built-in risk rules, see [docs/RULE_CATALOG.md](docs/RULE_CATALOG.md).
|
|
544
|
+
|
|
545
|
+
## Release Provenance
|
|
546
|
+
|
|
547
|
+
PatchDrill includes a release workflow for npm trusted publishing and provenance. Configure the package as a trusted publisher in npm, then publish from a GitHub Release. See [docs/RELEASE.md](docs/RELEASE.md).
|
|
548
|
+
|
|
549
|
+
Before publishing, run:
|
|
550
|
+
|
|
551
|
+
```bash
|
|
552
|
+
patchdrill release-check
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
## Dependency Review
|
|
556
|
+
|
|
557
|
+
PatchDrill summarizes dependency changes from changed `package.json`, `pyproject.toml`, `requirements.txt`, NuGet `PackageReference` / `PackageVersion` manifests, Maven `pom.xml`, Gradle `build.gradle` / `build.gradle.kts` / `libs.versions.toml`, `Gemfile`, `composer.json`, `go.mod`, `Cargo.toml`, npm `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `bun.lock`, `go.sum`, `Cargo.lock`, `poetry.lock`, `uv.lock`, `Pipfile.lock`, `Gemfile.lock`, and `composer.lock` files, listing the package, dependency section or lockfile path, change type, previous version, and new version in Markdown and JSON reports. It also flags dependency proof gaps, such as direct manifest changes without matching lockfile evidence or lockfile-only resolution drift without manifest intent. This complements heavier SCA tools by making reviewer-visible dependency intent explicit.
|
|
558
|
+
|
|
559
|
+
## Package Script Review
|
|
560
|
+
|
|
561
|
+
PatchDrill also summarizes `package.json` script additions, removals, and updates in Markdown, JSON, and HTML reports. Risk findings call out install/prepare/pack/publish lifecycle hooks, no-op verification scripts, removed test/lint/build scripts, and package scripts that pipe remote downloads into interpreters.
|
|
562
|
+
|
|
563
|
+
## Design Principles
|
|
564
|
+
|
|
565
|
+
- Deterministic first. No model call is required to get a useful answer. Findings, risk score, and command plan are reproducible for the same diff; the report's `generatedAt` timestamp is the only intentionally variable field, and it honors `SOURCE_DATE_EPOCH` so reports can be made byte-identical for caching, snapshotting, and reproducible audits.
|
|
566
|
+
- Proof Packs over vibes. A reviewer should see the exact commands, findings, artifacts, and digests.
|
|
567
|
+
- Local by default. Source code stays in your checkout.
|
|
568
|
+
- Conservative scoring. PatchDrill would rather ask for proof than silently bless a risky patch.
|
|
569
|
+
- Extensible later. The rule engine is small enough for contributors to add ecosystems and policies.
|
|
570
|
+
- Trustworthy distribution. CI verifies build, tests, SARIF generation, and npm package contents.
|
|
571
|
+
|
|
572
|
+
## Roadmap
|
|
573
|
+
|
|
574
|
+
- Broader first-party fixture coverage for common open-source stacks.
|
|
575
|
+
- More native affected-task integrations beyond Turborepo, Nx, Pants, Cargo, Go, Bazel, and Buck workspaces.
|
|
576
|
+
- Local TUI for interactively accepting or rejecting inferred verification commands.
|
|
577
|
+
- Optional LLM summary mode that never replaces deterministic findings.
|
|
578
|
+
|
|
579
|
+
## FAQ
|
|
580
|
+
|
|
581
|
+
**Is this an AI tool?** No. PatchDrill makes **zero model calls**, needs no API key, and runs fully offline. The same diff in produces a byte-identical Proof Pack out (it honors `SOURCE_DATE_EPOCH`). It is the deterministic layer that exists *because* AI writes code now — not another AI.
|
|
582
|
+
|
|
583
|
+
**Isn't this just a linter or SAST?** No. A linter checks code against fixed rules; SAST matches known vulnerability patterns. PatchDrill infers what verification *this specific diff* implies and reports the proof that *should* exist but doesn't — including required checks that were planned but never run. No linter or SAST tracks that gap.
|
|
584
|
+
|
|
585
|
+
**Is it another CI gate I have to add?** It doesn't have to be. Run it locally in 30 seconds with no config (`npx --yes github:seungdori/patchdrill demo`). It maps what your existing review and CI should each cover for a diff; `scan` never mutates your repo and commands run only with `--run`.
|
|
586
|
+
|
|
587
|
+
**Does it phone home?** No network calls, no telemetry, no account. Your source never leaves your checkout.
|
|
588
|
+
|
|
589
|
+
**Why trust a new project?** You don't have to trust the maintainer or a star count — re-run any Proof Pack and get byte-identical output, and verify every artifact hash yourself. CI proves the tool against first-party fixtures for ~25 stack shapes.
|
|
590
|
+
|
|
591
|
+
## Contributing
|
|
592
|
+
|
|
593
|
+
Read [CONTRIBUTING.md](CONTRIBUTING.md). Good first contributions are new ecosystem detectors, risk rules, and real-world report fixtures.
|
|
594
|
+
|
|
595
|
+
## Security
|
|
596
|
+
|
|
597
|
+
PatchDrill executes commands only when you pass `--run`. It runs inferred required commands in your repository shell; optional commands require both `--run` and `--run-optional`. When required checks are planned but not executed, PatchDrill reports that as missing verification evidence instead of silently treating the patch as proven. Markdown, compact summaries, the HTML dashboard, and console output label each planned command as passed, failed, timed out, not run, or skipped optional. `patchdrill init` writes a CI workflow with `run: "true"` and a per-command timeout so pull requests produce command evidence by default. Review the verification plan first when scanning untrusted repos. See [SECURITY.md](SECURITY.md).
|
|
598
|
+
|
|
599
|
+
## License
|
|
600
|
+
|
|
601
|
+
MIT
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Reporting a Vulnerability
|
|
4
|
+
|
|
5
|
+
Please open a private security advisory on GitHub or email the maintainers once a public contact is listed.
|
|
6
|
+
|
|
7
|
+
Include:
|
|
8
|
+
|
|
9
|
+
- PatchDrill version or commit.
|
|
10
|
+
- Operating system and Node version.
|
|
11
|
+
- A minimal repo or diff that reproduces the issue.
|
|
12
|
+
- Whether `--run` was used.
|
|
13
|
+
|
|
14
|
+
## Execution Model
|
|
15
|
+
|
|
16
|
+
PatchDrill has two modes:
|
|
17
|
+
|
|
18
|
+
- `scan`: reads git metadata and local files, then emits a plan and risk report.
|
|
19
|
+
- `scan --run`: executes inferred required verification commands in the repository shell.
|
|
20
|
+
- `scan --run --run-optional`: also executes optional verification commands such as browser, e2e, or static-analysis checks.
|
|
21
|
+
|
|
22
|
+
Do not use `--run` or `--run-optional` on untrusted repositories until you have reviewed the verification plan.
|
|
23
|
+
|
|
24
|
+
PatchDrill omits matched secret values from findings and SARIF messages. File names and line numbers can still be sensitive in private repositories, so treat generated reports as internal artifacts unless reviewed.
|
|
25
|
+
|
|
26
|
+
## Data Handling
|
|
27
|
+
|
|
28
|
+
PatchDrill does not send source code or reports to a network service. Reports are written only to paths you request.
|