skeptic-cli 0.5.0__tar.gz
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.
- skeptic_cli-0.5.0/LICENSE +21 -0
- skeptic_cli-0.5.0/PKG-INFO +389 -0
- skeptic_cli-0.5.0/README.md +317 -0
- skeptic_cli-0.5.0/pyproject.toml +77 -0
- skeptic_cli-0.5.0/setup.cfg +4 -0
- skeptic_cli-0.5.0/src/skeptic/__init__.py +0 -0
- skeptic_cli-0.5.0/src/skeptic/adapters/__init__.py +0 -0
- skeptic_cli-0.5.0/src/skeptic/adapters/python/__init__.py +27 -0
- skeptic_cli-0.5.0/src/skeptic/adapters/python/bandit_adapter.py +61 -0
- skeptic_cli-0.5.0/src/skeptic/adapters/python/pip_audit_adapter.py +56 -0
- skeptic_cli-0.5.0/src/skeptic/adapters/python/pyright_adapter.py +45 -0
- skeptic_cli-0.5.0/src/skeptic/adapters/python/pytest_adapter.py +59 -0
- skeptic_cli-0.5.0/src/skeptic/adapters/python/ruff_adapter.py +44 -0
- skeptic_cli-0.5.0/src/skeptic/cli/__init__.py +0 -0
- skeptic_cli-0.5.0/src/skeptic/cli/main.py +337 -0
- skeptic_cli-0.5.0/src/skeptic/core/__init__.py +0 -0
- skeptic_cli-0.5.0/src/skeptic/core/complexity.py +110 -0
- skeptic_cli-0.5.0/src/skeptic/core/config.py +72 -0
- skeptic_cli-0.5.0/src/skeptic/core/gate.py +124 -0
- skeptic_cli-0.5.0/src/skeptic/core/git_utils.py +97 -0
- skeptic_cli-0.5.0/src/skeptic/core/graph.py +157 -0
- skeptic_cli-0.5.0/src/skeptic/core/models.py +69 -0
- skeptic_cli-0.5.0/src/skeptic/core/provenance.py +90 -0
- skeptic_cli-0.5.0/src/skeptic/core/risk_score.py +99 -0
- skeptic_cli-0.5.0/src/skeptic/core/runner.py +43 -0
- skeptic_cli-0.5.0/src/skeptic/core/solid.py +266 -0
- skeptic_cli-0.5.0/src/skeptic/mcp/__init__.py +0 -0
- skeptic_cli-0.5.0/src/skeptic/mcp/call_log.py +68 -0
- skeptic_cli-0.5.0/src/skeptic/mcp/server.py +101 -0
- skeptic_cli-0.5.0/src/skeptic/narration/__init__.py +3 -0
- skeptic_cli-0.5.0/src/skeptic/narration/gemini_narrator.py +92 -0
- skeptic_cli-0.5.0/src/skeptic/verifier/__init__.py +14 -0
- skeptic_cli-0.5.0/src/skeptic/verifier/attack_runner.py +144 -0
- skeptic_cli-0.5.0/src/skeptic/verifier/gemini_generator.py +93 -0
- skeptic_cli-0.5.0/src/skeptic/verifier/models.py +88 -0
- skeptic_cli-0.5.0/src/skeptic_cli.egg-info/PKG-INFO +389 -0
- skeptic_cli-0.5.0/src/skeptic_cli.egg-info/SOURCES.txt +39 -0
- skeptic_cli-0.5.0/src/skeptic_cli.egg-info/dependency_links.txt +1 -0
- skeptic_cli-0.5.0/src/skeptic_cli.egg-info/entry_points.txt +3 -0
- skeptic_cli-0.5.0/src/skeptic_cli.egg-info/requires.txt +25 -0
- skeptic_cli-0.5.0/src/skeptic_cli.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hamza Shaikh
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: skeptic-cli
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: Independent engineering quality gate for AI-generated and human-written Python code.
|
|
5
|
+
Author-email: Hamza Shaikh <hamzashaikhm123@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Hamza Shaikh
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/HamzaShaikh17/Skeptic
|
|
29
|
+
Project-URL: Repository, https://github.com/HamzaShaikh17/Skeptic
|
|
30
|
+
Project-URL: Issues, https://github.com/HamzaShaikh17/Skeptic/issues
|
|
31
|
+
Project-URL: Documentation, https://github.com/HamzaShaikh17/Skeptic/blob/master/docs/USAGE.md
|
|
32
|
+
Keywords: code-quality,static-analysis,security,ci-cd,ai-agents,mcp,linting,skeptic
|
|
33
|
+
Classifier: Development Status :: 3 - Alpha
|
|
34
|
+
Classifier: Environment :: Console
|
|
35
|
+
Classifier: Intended Audience :: Developers
|
|
36
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
37
|
+
Classifier: Operating System :: OS Independent
|
|
38
|
+
Classifier: Programming Language :: Python :: 3
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
43
|
+
Classifier: Topic :: Security
|
|
44
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
45
|
+
Classifier: Topic :: Software Development :: Testing
|
|
46
|
+
Requires-Python: >=3.10
|
|
47
|
+
Description-Content-Type: text/markdown
|
|
48
|
+
License-File: LICENSE
|
|
49
|
+
Requires-Dist: click>=8.1
|
|
50
|
+
Requires-Dist: pydantic>=2.6
|
|
51
|
+
Requires-Dist: rich>=13.7
|
|
52
|
+
Requires-Dist: ruff>=0.4
|
|
53
|
+
Requires-Dist: bandit>=1.7
|
|
54
|
+
Requires-Dist: pyright>=1.1
|
|
55
|
+
Requires-Dist: pytest>=8.0
|
|
56
|
+
Requires-Dist: pytest-cov>=5.0
|
|
57
|
+
Requires-Dist: pytest-json-report>=1.5
|
|
58
|
+
Requires-Dist: pip-audit>=2.7
|
|
59
|
+
Requires-Dist: pyyaml>=6.0
|
|
60
|
+
Requires-Dist: mcp>=1.2
|
|
61
|
+
Provides-Extra: dev
|
|
62
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
63
|
+
Requires-Dist: anyio>=4.0; extra == "dev"
|
|
64
|
+
Provides-Extra: narration
|
|
65
|
+
Requires-Dist: google-genai>=1.0; extra == "narration"
|
|
66
|
+
Requires-Dist: python-dotenv>=1.0; extra == "narration"
|
|
67
|
+
Provides-Extra: verify
|
|
68
|
+
Requires-Dist: google-genai>=1.0; extra == "verify"
|
|
69
|
+
Requires-Dist: python-dotenv>=1.0; extra == "verify"
|
|
70
|
+
Requires-Dist: httpx>=0.27; extra == "verify"
|
|
71
|
+
Dynamic: license-file
|
|
72
|
+
|
|
73
|
+
# Skeptic
|
|
74
|
+
|
|
75
|
+
An independent engineering quality gate for AI-generated (and human-written) Python
|
|
76
|
+
code. Skeptic doesn't take a change's word for it — it orchestrates Ruff, Pyright,
|
|
77
|
+
Bandit, pytest/coverage, and pip-audit into one pass/fail verdict, with evidence
|
|
78
|
+
attached to every failure, so an AI coding agent (or a human) can be required to
|
|
79
|
+
satisfy it before a change counts as done.
|
|
80
|
+
|
|
81
|
+
## Status
|
|
82
|
+
|
|
83
|
+
Phase 1 CLI MVP (`v0.3`), Phase 2's MCP server, and Phase 3 complete through
|
|
84
|
+
milestone 8 (LLM verifier/pricing/billing, milestone 9, not built). All five
|
|
85
|
+
deterministic adapters (Ruff, Pyright, Bandit, pytest, pip-audit) plus
|
|
86
|
+
structural SOLID checks, complexity, Change Risk Score, and AI provenance
|
|
87
|
+
tagging are wired and unit-tested against fixture repos; LLM-backed
|
|
88
|
+
narration and verification are live-tested against the real Gemini API. See
|
|
89
|
+
`Plan.md` for the full build plan and current milestone.
|
|
90
|
+
|
|
91
|
+
## Install
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pip install -e .
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
This installs `skeptic` as a console command, backed by Click. Verified against
|
|
98
|
+
a clean `python -m venv` + `pip install -e .` with no other setup. Not yet on
|
|
99
|
+
PyPI — install from a local clone until it is.
|
|
100
|
+
|
|
101
|
+
## Prerequisites
|
|
102
|
+
|
|
103
|
+
**Install and activate the target repo's own dependencies before running `skeptic check`.**
|
|
104
|
+
`skeptic` shells out to `pyright` (and `pytest`) using whatever Python environment
|
|
105
|
+
is currently active — it does not install the target repo's dependencies for you.
|
|
106
|
+
If they aren't installed, Pyright can't resolve most imports and will report a
|
|
107
|
+
flood of `reportMissingImports` errors that have nothing to do with real type
|
|
108
|
+
safety, and `pytest` will fail to collect tests at all. Since the default gate
|
|
109
|
+
is zero-tolerance (`types_max_errors: 0`), this alone is enough to fail every
|
|
110
|
+
real repo. The fix: `cd` into the target repo, activate its venv (or otherwise
|
|
111
|
+
make sure its dependencies are installed in the active environment — e.g.
|
|
112
|
+
`pip install -r requirements.txt`, `uv sync`, `poetry install`), *then* run
|
|
113
|
+
`skeptic check`. Ruff, Bandit, and pip-audit don't need this — they analyze
|
|
114
|
+
source/dependency manifests directly rather than resolving imports.
|
|
115
|
+
|
|
116
|
+
## Usage
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# Generate a starter config in your repo
|
|
120
|
+
skeptic init /path/to/your/repo
|
|
121
|
+
|
|
122
|
+
# Run the gate
|
|
123
|
+
skeptic check /path/to/your/repo
|
|
124
|
+
|
|
125
|
+
# Machine-readable output (for CI or an agent to parse)
|
|
126
|
+
skeptic check /path/to/your/repo --json
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Example
|
|
130
|
+
|
|
131
|
+
Given a repo with an unused import, a real type error, and a vulnerable pinned
|
|
132
|
+
dependency:
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
$ skeptic check .
|
|
136
|
+
|
|
137
|
+
Engineering Gate: FAIL
|
|
138
|
+
|
|
139
|
+
+----------------------------------------------------------------------------+
|
|
140
|
+
| Rule | Status | Detail |
|
|
141
|
+
|-------------------+--------+-----------------------------------------------|
|
|
142
|
+
| lint | FAIL | 1 lint findings (max allowed: 0) |
|
|
143
|
+
| types | FAIL | 1 type errors (max allowed: 0) |
|
|
144
|
+
| security_critical | PASS | 0 critical security findings (max allowed: 0) |
|
|
145
|
+
| security_high | PASS | 0 high security findings (max allowed: 0) |
|
|
146
|
+
| coverage | PASS | 88.9% coverage (min required: 0.0%) |
|
|
147
|
+
| dependencies | FAIL | 12 critical/high CVEs (max allowed: 0) |
|
|
148
|
+
+----------------------------------------------------------------------------+
|
|
149
|
+
|
|
150
|
+
lint findings:
|
|
151
|
+
app.py:1 `os` imported but unused (F401)
|
|
152
|
+
|
|
153
|
+
types findings:
|
|
154
|
+
app.py:14 Argument of type "Literal['not a number']" cannot be assigned to
|
|
155
|
+
parameter "a" of type "int" in function "add" (reportArgumentType)
|
|
156
|
+
...
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Exit code `1`. Fix the issues (or explicitly relax `skeptic.yaml`) and the same
|
|
160
|
+
command exits `0` with `Engineering Gate: PASS`.
|
|
161
|
+
|
|
162
|
+
## Configuration
|
|
163
|
+
|
|
164
|
+
Edit `skeptic.yaml` in your repo root:
|
|
165
|
+
|
|
166
|
+
```yaml
|
|
167
|
+
lint:
|
|
168
|
+
max_errors: 0
|
|
169
|
+
types:
|
|
170
|
+
max_errors: 0
|
|
171
|
+
security:
|
|
172
|
+
max_critical: 0
|
|
173
|
+
max_high: 0
|
|
174
|
+
coverage:
|
|
175
|
+
min_percent: 80
|
|
176
|
+
dependencies:
|
|
177
|
+
max_critical_cves: 0
|
|
178
|
+
|
|
179
|
+
# Optional, unset by default - see "Architecture findings" below. Neither
|
|
180
|
+
# blocks the gate until you uncomment it.
|
|
181
|
+
# architecture:
|
|
182
|
+
# max_findings: 0
|
|
183
|
+
# ai_review:
|
|
184
|
+
# max_risk_label: MEDIUM # LOW | MEDIUM | HIGH
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
No `skeptic.yaml`? Defaults are strict (zero tolerance on everything) for
|
|
188
|
+
lint/types/security/dependencies — `architecture` and `ai_review` are the
|
|
189
|
+
two exceptions: they stay off until you explicitly configure them (see
|
|
190
|
+
below for why).
|
|
191
|
+
|
|
192
|
+
For the full walkthrough — reading output, `--json`/CI integration, what
|
|
193
|
+
each check actually does, troubleshooting — see [`docs/USAGE.md`](docs/USAGE.md).
|
|
194
|
+
|
|
195
|
+
## Architecture findings (SOLID + complexity) + narration
|
|
196
|
+
|
|
197
|
+
`skeptic check` also runs four deterministic, LLM-free structural checks —
|
|
198
|
+
SRP, ISP, DIP (`tool="solid"`), and McCabe cyclomatic complexity
|
|
199
|
+
(`tool="complexity"`, functions over 10 flagged by default). They show up
|
|
200
|
+
in the table output and `--json` (`solid_findings`/`complexity_findings`)
|
|
201
|
+
either way, but whether they can **fail** the gate depends on `skeptic.yaml`:
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
architecture findings (informational - not yet gated):
|
|
205
|
+
app/god_service.py:11 class 'GodService' touches 3 unrelated external
|
|
206
|
+
systems (database, email, http) via: ... (SRP)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Not gated by default, deliberately** — unlike lint/types/security/
|
|
210
|
+
dependencies, which default to zero-tolerance. These checks are new and
|
|
211
|
+
haven't been broadly triaged the way an established linter has, so turning
|
|
212
|
+
every existing repo's gate from PASS to FAIL the moment you upgrade would
|
|
213
|
+
be a surprising, unrequested breaking change. Opt in explicitly:
|
|
214
|
+
|
|
215
|
+
```yaml
|
|
216
|
+
architecture:
|
|
217
|
+
max_findings: 0 # gates both solid and complexity findings together
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Change Risk Score
|
|
221
|
+
|
|
222
|
+
Every `skeptic check` run (CLI table, `--json`, and MCP output) includes a
|
|
223
|
+
composite LOW/MEDIUM/HIGH label — security + regression (test health) +
|
|
224
|
+
architecture + complexity + test confidence, each scored 0-100 and always
|
|
225
|
+
shown, not just the label:
|
|
226
|
+
|
|
227
|
+
```
|
|
228
|
+
Change Risk Score: MEDIUM (38.2/100 - security=40.0, regression=0.0, architecture=45.0, complexity=10.0, test_confidence=100.0)
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
The weights and LOW/MEDIUM/HIGH thresholds are a documented first-pass
|
|
232
|
+
heuristic (see `src/skeptic/core/risk_score.py`), not an empirically
|
|
233
|
+
calibrated model — treat the label as a prioritization signal, not a
|
|
234
|
+
certified verdict. Gate on it explicitly if you want it to block:
|
|
235
|
+
|
|
236
|
+
```yaml
|
|
237
|
+
ai_review:
|
|
238
|
+
max_risk_label: MEDIUM # fails the gate if the label exceeds this
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### AI provenance (`skeptic provenance`)
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
skeptic provenance /path/to/your/repo --since-ref HEAD~20
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Estimates what share of recent commits landed while an AI agent was
|
|
248
|
+
actively using `skeptic-mcp` against this repo, correlating each commit's
|
|
249
|
+
timestamp against the local [MCP call log](#call-logging). **This is an
|
|
250
|
+
approximation, not a precise record**: `skeptic-mcp`'s tools are read-only
|
|
251
|
+
analysis, so the call log records when an agent called them, not which
|
|
252
|
+
lines it edited — a commit landing within `--window-minutes` (default 15)
|
|
253
|
+
of a logged call is labeled `ai_generated` (pure addition) or
|
|
254
|
+
`ai_modified` (touched existing lines); everything else is `human`. No
|
|
255
|
+
model identification, just the ratio. Requires no setup — with zero MCP
|
|
256
|
+
history for a repo, everything is reported as `human`.
|
|
257
|
+
|
|
258
|
+
### Plain-language narration (optional, costs an API call)
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
skeptic check /path/to/your/repo --narrate
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Sends each SOLID finding to Gemini for a short "why this matters + how to
|
|
265
|
+
fix it" explanation, printed under the finding. The LLM never originates a
|
|
266
|
+
finding or changes the verdict — it only narrates one a deterministic check
|
|
267
|
+
already produced, and if narration fails (no key, network error, rate
|
|
268
|
+
limit) `skeptic check` still runs and reports normally, just without the
|
|
269
|
+
narration text.
|
|
270
|
+
|
|
271
|
+
Requires `GEMINI_API_KEY`:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
pip install -e ".[narration]" # installs google-genai + python-dotenv
|
|
275
|
+
cp .env.example .env # then fill in GEMINI_API_KEY
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
`.env` is loaded automatically (and is gitignored — never commit it). The
|
|
279
|
+
model is `gemini-3.5-flash` by default, overridable via `SKEPTIC_GEMINI_MODEL`
|
|
280
|
+
if it gets deprecated later — Gemini model availability shifted twice while
|
|
281
|
+
building this feature (see `src/skeptic/narration/gemini_narrator.py`), so
|
|
282
|
+
this is a real, not hypothetical, concern.
|
|
283
|
+
|
|
284
|
+
## Adversarial verifier (`skeptic verify`)
|
|
285
|
+
|
|
286
|
+
Generates and runs attack test cases against a **running instance you
|
|
287
|
+
control** — boundary values, invalid input, injection, auth bypass, IDOR,
|
|
288
|
+
concurrency (race conditions), and failure-mode (timeout) probes — and
|
|
289
|
+
reports pass/fail per category with the exact request that triggered each
|
|
290
|
+
result.
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
pip install -e ".[verify]" # installs google-genai + python-dotenv + httpx
|
|
294
|
+
# start your own app locally first, e.g.: uvicorn app.main:app --port 8000
|
|
295
|
+
|
|
296
|
+
skeptic verify /path/to/your/repo --target http://localhost:8000
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**Safety, by design, not as an afterthought:**
|
|
300
|
+
- **Read-only against your code.** It never writes to the repo path — only
|
|
301
|
+
generates requests and sends them to `--target`.
|
|
302
|
+
- **The LLM never executes anything.** Gemini returns structured data
|
|
303
|
+
(method/path/headers/body) via a JSON schema, never code — the only thing
|
|
304
|
+
that ever runs is an HTTP request Skeptic's own code sends. Real
|
|
305
|
+
arbitrary-code-execution risk was a deliberate design decision *not* to
|
|
306
|
+
take on for this milestone.
|
|
307
|
+
- **Refuses non-local targets by default.** `--target` must resolve to
|
|
308
|
+
localhost or a private address (`10.x`, `172.16–31.x`, `192.168.x`, link-
|
|
309
|
+
local) or the command exits immediately, before generating anything —
|
|
310
|
+
it's sending real injection/auth-bypass/IDOR payloads, so this shouldn't
|
|
311
|
+
be pointable at a service you don't own by accident. Pass
|
|
312
|
+
`--allow-external` if you're certain the target is yours.
|
|
313
|
+
|
|
314
|
+
`--diff-ref` (default `HEAD`) focuses attack-case generation on your
|
|
315
|
+
uncommitted changes if `path` is a git repo; falls back to general-purpose
|
|
316
|
+
REST-API cases otherwise (not a git repo, or the ref doesn't exist) — never
|
|
317
|
+
a hard failure. `passed: null` on a result means the heuristic genuinely
|
|
318
|
+
can't tell (e.g. every concurrent request to a mutating endpoint succeeding
|
|
319
|
+
identically — could be a race condition, could be a correctly-idempotent
|
|
320
|
+
endpoint) and a human should look at `detail`; it's never silently coerced
|
|
321
|
+
to a pass.
|
|
322
|
+
|
|
323
|
+
Uses the same `GEMINI_API_KEY`/`.env` as `--narrate` above.
|
|
324
|
+
|
|
325
|
+
## MCP server (Claude Code / Cursor)
|
|
326
|
+
|
|
327
|
+
Skeptic's engine is also exposed as an MCP server, so an AI coding
|
|
328
|
+
agent can call it mid-task instead of you running `skeptic check` by hand.
|
|
329
|
+
Same engine, same adapters, same gate — the CLI and the MCP server are both
|
|
330
|
+
thin clients of `skeptic.core`.
|
|
331
|
+
|
|
332
|
+
### Install
|
|
333
|
+
|
|
334
|
+
`pip install -e .` (see above) also installs the `skeptic-mcp` console
|
|
335
|
+
command, which starts the server over stdio.
|
|
336
|
+
|
|
337
|
+
### Configure your project
|
|
338
|
+
|
|
339
|
+
Add this to your project's `.mcp.json` (Claude Code) or `.cursor/mcp.json`
|
|
340
|
+
(Cursor) — not Skeptic's own repo, *the repo you want the agent to check*:
|
|
341
|
+
|
|
342
|
+
```json
|
|
343
|
+
{
|
|
344
|
+
"mcpServers": {
|
|
345
|
+
"skeptic": {
|
|
346
|
+
"command": "skeptic-mcp",
|
|
347
|
+
"args": []
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
`skeptic-mcp` must resolve on `PATH` in whatever environment your editor
|
|
354
|
+
launches subprocesses from — same as any other locally-installed MCP server.
|
|
355
|
+
Skeptic's own repo ships this file too (dogfooding: Claude Code sessions
|
|
356
|
+
working on Skeptic itself get the tools automatically).
|
|
357
|
+
|
|
358
|
+
### Tools exposed
|
|
359
|
+
|
|
360
|
+
| Tool | Signature | Returns |
|
|
361
|
+
| --- | --- | --- |
|
|
362
|
+
| `skeptic_check` | `(repo_path: str)` | Full pass/fail verdict + evidence for every failing rule + tool statuses. Equivalent to `skeptic check --json`. |
|
|
363
|
+
| `skeptic_get_findings` | `(repo_path: str, severity: str \| None)` | Every raw finding across all 5 tools, optionally filtered to one severity (`critical`/`high`/`medium`/`low`) — not limited to findings tied to a failing gate rule. |
|
|
364
|
+
| `skeptic_gate_status` | `(repo_path: str)` | Same gate evaluation as `skeptic_check`, without the findings payload — a cheap pass/fail poll. |
|
|
365
|
+
|
|
366
|
+
The same [Prerequisites](#prerequisites) caveat applies: the target repo's
|
|
367
|
+
own dependencies need to be installed/active in the environment the MCP
|
|
368
|
+
server runs in, or `types` findings will mostly be import-resolution noise.
|
|
369
|
+
|
|
370
|
+
### Call logging
|
|
371
|
+
|
|
372
|
+
Every call to any of the three tools is appended to a local, per-repo,
|
|
373
|
+
append-only JSONL log at `~/.skeptic/mcp_logs/<repo-name>-<hash>.jsonl` —
|
|
374
|
+
timestamp, session id, tool name, args, and the full result. Nothing reads
|
|
375
|
+
this back today; it's the seed of future evidence/provenance work, logged
|
|
376
|
+
now because the cost of doing so later (once real usage has already
|
|
377
|
+
happened without a record of it) is much higher.
|
|
378
|
+
|
|
379
|
+
## Architecture
|
|
380
|
+
|
|
381
|
+
See `Plan.md` and `src/skeptic/core/models.py` for the language-agnostic schema.
|
|
382
|
+
Python-specific tool wrappers live in `src/skeptic/adapters/python/` — adding a
|
|
383
|
+
new language later means adding a new adapter directory, not rewriting the core.
|
|
384
|
+
|
|
385
|
+
## Development
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
pytest tests/
|
|
389
|
+
```
|