openpitstop 1.0.0 → 1.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/README.md +42 -6
- package/dist/commands/install.js +87 -1
- package/dist/commands/install.js.map +1 -1
- package/package.json +1 -1
- package/scripts/cheat-demo.cjs +49 -8
package/README.md
CHANGED
|
@@ -40,11 +40,13 @@ your agent.
|
|
|
40
40
|
|
|
41
41
|
| Jump to | |
|
|
42
42
|
|---|---|
|
|
43
|
-
| [Feature tour](#feature-tour) — the
|
|
43
|
+
| [Feature tour](#feature-tour) — the 13 demos | [Install](#install) · [Usage](#usage) · [Tool support](#tool-support) |
|
|
44
44
|
| [See it in 90 seconds](#see-it-in-90-seconds) | [What OpenPitStop actually does](#what-openpitstop-actually-does) · [Every command](#every-command) |
|
|
45
45
|
| [Architecture](#architecture) | [Known limitations](#known-limitations) · [Contributing](#contributing) · [License](#license) |
|
|
46
46
|
|
|
47
|
-
**Straight to one feature:** [The scan](#the-scan) · [Verify](#verify) · [Trends](#trends) · [Inspect](#inspect) · [Repro](#repro) · [The pen test](#the-pen-test) · [Report](#report) · [Share](#share) · [Honesty](#honesty) · [Try it on your repo](#try-it-on-your-repo) · [The live shield](#the-live-shield)
|
|
47
|
+
**Straight to one feature:** [The scan](#the-scan) · [Verify](#verify) · [Trends](#trends) · [Inspect](#inspect) · [Repro](#repro) · [The pen test](#the-pen-test) · [Report](#report) · [Share](#share) · [Honesty](#honesty) · [Try it on your repo](#try-it-on-your-repo) · [The live shield](#the-live-shield) · [The GitHub Action](#the-github-action) · [The pre-commit hook](#the-pre-commit-hook)
|
|
48
|
+
|
|
49
|
+
**Receipts:** [Caught in the wild](docs/caught-in-the-wild.md) — real gate output, screenshot-ready.
|
|
48
50
|
|
|
49
51
|
---
|
|
50
52
|
|
|
@@ -142,6 +144,19 @@ Every clip below is real command output — the only thing that was trimmed is d
|
|
|
142
144
|
<img src="docs/media/pitstop-watch.gif" alt="pitstop watch — live score delta when a file changes" width="700">
|
|
143
145
|
</p>
|
|
144
146
|
|
|
147
|
+
### The GitHub Action
|
|
148
|
+
|
|
149
|
+
`uses: openpitstop/action` (or `Krish-1507/OpenPitStop@main` today) — every PR
|
|
150
|
+
gets the gate as a comment and a failing check when it matters. No wiring by
|
|
151
|
+
hand; the badge in your README regenerates itself. [Setup & badge loop →
|
|
152
|
+
](docs/github-action.md)
|
|
153
|
+
|
|
154
|
+
### The pre-commit hook
|
|
155
|
+
|
|
156
|
+
`npx openpitstop install --hooks` — the gate one step earlier: the commit
|
|
157
|
+
can't land until the gate passes. Caught it before it shipped. [Real blocked
|
|
158
|
+
commits → ](docs/caught-in-the-wild.md#bonus-the-same-catches-as-a-pre-commit-hook)
|
|
159
|
+
|
|
145
160
|
---
|
|
146
161
|
|
|
147
162
|
## See it in 90 seconds
|
|
@@ -161,7 +176,9 @@ node node_modules/openpitstop/scripts/cheat-demo.cjs # from any project that i
|
|
|
161
176
|
```
|
|
162
177
|
|
|
163
178
|
Set `PITSTOP_CLI="node /path/to/dist/cli.js"` to run it against a local build instead
|
|
164
|
-
of the registry.
|
|
179
|
+
of the registry. For a tight re-record, `node scripts/cheat-demo.cjs --fast --no-pitch`
|
|
180
|
+
reuses the cached `node_modules` (skips `npm install`) and ends the arc on the
|
|
181
|
+
CONFIRMED_CHEAT box — no pitch, no dead air.
|
|
165
182
|
|
|
166
183
|
```
|
|
167
184
|
ACT 1 honest baseline → 1 failed test, scanned and sealed
|
|
@@ -187,6 +204,9 @@ npx openpitstop try .
|
|
|
187
204
|
Two seconds of scanning, your repo, your score (plus a one-time package download on the
|
|
188
205
|
first-ever `npx` run — see the speed tip in [Install](#install)). Everything else can wait.
|
|
189
206
|
|
|
207
|
+
Real catches — focused tests, deleted tests, edited assertions, tampered baselines — with
|
|
208
|
+
verbatim gate output you can screenshot and share: [Caught in the wild](docs/caught-in-the-wild.md).
|
|
209
|
+
|
|
190
210
|
---
|
|
191
211
|
|
|
192
212
|
## Install
|
|
@@ -208,6 +228,20 @@ npx openpitstop install -y
|
|
|
208
228
|
Re-installing overwrites each tool's `/pitstop` command file with the latest prompt
|
|
209
229
|
(say, a new mode or an updated loop) — your tool picks it up on its next use.
|
|
210
230
|
|
|
231
|
+
Want the gate *before* the commit, not just on the PR? One extra flag installs the
|
|
232
|
+
pre-commit hook — every commit is checked (SUSPICIOUS/CONFIRMED_CHEAT → blocked) before
|
|
233
|
+
it can land:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
npx openpitstop install --hooks
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
The hook runs the same `pitstop gate` (exit 0 = PASS · 1 = FAIL · 2 = CONFIRMED_CHEAT),
|
|
240
|
+
never blocks the first commit of a repo, never jails a repo that hasn't been scanned yet
|
|
241
|
+
(it warns instead), and can be bypassed once with `git commit --no-verify`. Remove it with
|
|
242
|
+
`npx openpitstop install --uninstall --hooks`. To point the hook at a local build, export
|
|
243
|
+
`PITSTOP_CLI` (e.g. `PITSTOP_CLI="node /path/to/dist/cli.js"`).
|
|
244
|
+
|
|
211
245
|
Speed tip: the `try`/`scan` itself takes ~2 seconds — but the **first** `npx openpitstop …`
|
|
212
246
|
on a machine has to download the package first (a few seconds on a fast connection, more on a
|
|
213
247
|
slow one). For an instant first run on machines you own, install once:
|
|
@@ -275,6 +309,8 @@ writes into your tool configs (that stays an explicit `pitstop install`).
|
|
|
275
309
|
| Gemini CLI | `.gemini/commands/pitstop.toml` (project + user) | Full support |
|
|
276
310
|
| Codex CLI | `~/.codex/prompts/pitstop.md` | Full support |
|
|
277
311
|
| Codex App / VS Code extension | — (no file written) | **Not supported** — OpenAI hasn't shipped custom slash commands there; install prints a manual-copy note instead |
|
|
312
|
+
| GitHub Action (PRs) | `uses: Krish-1507/OpenPitStop@main` | **Full support** — gate verdict as a PR comment + failing check; see [docs/github-action.md](docs/github-action.md) |
|
|
313
|
+
| git pre-commit hook | `.git/hooks/pre-commit` (installed with `--hooks`) | **Full support** — the gate blocks the commit before it lands |
|
|
278
314
|
|
|
279
315
|
Legacy/alternate locations are also written where tool docs are inconsistent across versions
|
|
280
316
|
(see `src/installer/targets.ts`). Existing files are never overwritten unless you pass
|
|
@@ -341,9 +377,9 @@ one-shot.
|
|
|
341
377
|
|
|
342
378
|
| Command | What it does |
|
|
343
379
|
|---|---|
|
|
344
|
-
| `pitstop gate [--score 60]` | A commit gate for CI
|
|
380
|
+
| `pitstop gate [--score 60]` | A commit gate for CI, pre-commit hooks or PRs: score threshold + regression risk + diff integrity + evidence signature. **Exit 0 = PASS · 1 = FAIL · 2 = CONFIRMED_CHEAT.** |
|
|
345
381
|
| `pitstop integrity [path]` | Checks the latest commit or working tree for cheat patterns *without* a full scan: deleted or neutered tests, swallowed errors, suppression comments, hardcoded-to-pass values, mocked modules, forced exits. **Exit 0 = CLEAN · 1 = SUSPICIOUS · 2 = CONFIRMED_CHEAT.** |
|
|
346
|
-
| `pitstop ci [path]` | CI-friendly scan + verify against the base branch → a PR-ready markdown report — the gate as a PR comment. It only reports; fixes stay local via `/pitstop`. |
|
|
382
|
+
| `pitstop ci [path]` | CI-friendly scan + verify against the base branch → a PR-ready markdown report — the gate as a PR comment. It only reports; fixes stay local via `/pitstop`. Wired into the [GitHub Action](docs/github-action.md), which comments the gate on every PR and fails the check when it fails. |
|
|
347
383
|
|
|
348
384
|
**Penetration test — attack your own app**
|
|
349
385
|
|
|
@@ -366,7 +402,7 @@ one-shot.
|
|
|
366
402
|
|
|
367
403
|
| Command | What it does |
|
|
368
404
|
|---|---|
|
|
369
|
-
| `pitstop install` / `install --uninstall` | Writes `/pitstop` into every supported tool (project + user level). `--uninstall` removes it all. |
|
|
405
|
+
| `pitstop install` / `install --uninstall` | Writes `/pitstop` into every supported tool (project + user level). `--uninstall` removes it all. `--hooks` also installs (or with `--uninstall`, removes) the git pre-commit gate. |
|
|
370
406
|
| `pitstop doctor` | Explains why categories show `skipped`: checks your toolchain (Node, git, jscpd, gitleaks, semgrep, pa11y) and prints copy-paste install hints. |
|
|
371
407
|
| `pitstop prompt [--args …]` | Prints the exact prompt your AI tool expands `/pitstop` into, with your arguments filled in — full transparency into what the agent was told. |
|
|
372
408
|
| `pitstop demo [demo]` | Scaffolds an intentionally-broken demo repo into a fresh temp dir (`demo-repo`, `demo-repo-integrity`, `demo-repo-fintech`, `demo-repo-generators`), initializes git, and scans it immediately. |
|
package/dist/commands/install.js
CHANGED
|
@@ -7,12 +7,58 @@ import path from "node:path";
|
|
|
7
7
|
import { getTargets, resolveTemplatePath, renderContent, } from "../installer/targets.js";
|
|
8
8
|
const READY_MESSAGE = "OpenPitStop is ready. Type /pitstop in Claude Code, Cursor, OpenCode, Kilo Code, Antigravity, Codex CLI or any AI coding tool installed, hit enter, and watch it work.";
|
|
9
9
|
const CODEX_APP_MESSAGE = "Codex App and Codex VS Code extension don't support custom slash commands yet (OpenAI hasn't shipped this) — use Codex CLI for /pitstop, or copy templates/pitstop.prompt.md's content directly into a Codex App chat as a one-off prompt.";
|
|
10
|
+
/**
|
|
11
|
+
* The git pre-commit gate hook, written by `pitstop install --hooks`.
|
|
12
|
+
* POSIX sh on purpose: git runs hooks through its own bundled sh on every
|
|
13
|
+
* platform (including Windows Git for Windows), so no interpreter guessing.
|
|
14
|
+
*
|
|
15
|
+
* Honest by design:
|
|
16
|
+
* - no HEAD yet (first commit) -> allowed, nothing to diff against
|
|
17
|
+
* - no baseline scanned yet -> warned, allowed — never jail an unscanned repo
|
|
18
|
+
* - gate verdict FAIL/HARD -> commit blocked, with the full gate box
|
|
19
|
+
* - PITSTOP_CLI / PITSTOP_SCORE env overrides honored
|
|
20
|
+
*/
|
|
21
|
+
const PRE_COMMIT_HOOK = `#!/usr/bin/env sh
|
|
22
|
+
# OpenPitStop pre-commit gate — installed by \`npx openpitstop install --hooks\`.
|
|
23
|
+
# Blocks commits the gate would fail (SUSPICIOUS, CONFIRMED_CHEAT, High risk,
|
|
24
|
+
# score below threshold, tampered evidence). Bypass once: git commit --no-verify
|
|
25
|
+
set -u
|
|
26
|
+
|
|
27
|
+
CLI="\${PITSTOP_CLI:-npx --yes openpitstop@latest}"
|
|
28
|
+
SCORE="\${PITSTOP_SCORE:-60}"
|
|
29
|
+
|
|
30
|
+
if ! git rev-parse --verify HEAD > /dev/null 2>&1; then
|
|
31
|
+
echo "[openpitstop] first commit (no HEAD yet) — allowed."
|
|
32
|
+
exit 0
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# git runs hooks with the repo root as cwd, so no repo arg is passed — a
|
|
36
|
+
# POSIX-style \$PWD would break Windows builds of the CLI.
|
|
37
|
+
echo "[openpitstop] gating commit (score >= \${SCORE}/100) ..."
|
|
38
|
+
OUT="\$(\$CLI gate --score "\$SCORE" 2>&1)"
|
|
39
|
+
CODE=\$?
|
|
40
|
+
|
|
41
|
+
if printf '%s' "\$OUT" | grep -q 'no baseline'; then
|
|
42
|
+
echo "[openpitstop] no baseline yet — run \`npx openpitstop scan\` once to arm the gate. Commit allowed."
|
|
43
|
+
exit 0
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
if [ "\$CODE" -ne 0 ]; then
|
|
47
|
+
printf '%s\\n' "\$OUT"
|
|
48
|
+
echo ""
|
|
49
|
+
echo "[openpitstop] GATE FAILED (exit \$CODE) — commit blocked."
|
|
50
|
+
echo "[openpitstop] Bypass once (e.g. a false alarm) with: git commit --no-verify"
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
exit "\$CODE"
|
|
54
|
+
`;
|
|
10
55
|
export const install = new Command("install")
|
|
11
|
-
.description("Install the pitstop slash-command into Claude Code, Cursor, OpenCode, Antigravity, Kilo Code, Gemini CLI, Codex")
|
|
56
|
+
.description("Install the pitstop slash-command into Claude Code, Cursor, OpenCode, Antigravity, Kilo Code, Gemini CLI, Codex (--hooks also adds the git pre-commit gate)")
|
|
12
57
|
.argument("[repo]", "target repo (defaults to cwd)", ".")
|
|
13
58
|
.option("--force", "overwrite existing pitstop files", false)
|
|
14
59
|
.option("-y, --yes", "same as --force (re-runnable one-liner: npx openpitstop@latest install -y)", false)
|
|
15
60
|
.option("--uninstall", "remove pitstop files only", false)
|
|
61
|
+
.option("--hooks", "also install (or with --uninstall, remove) the git pre-commit gate hook — every commit is gated before it can land", false)
|
|
16
62
|
.action(async (repoArg, opts) => {
|
|
17
63
|
const cwd = path.resolve(repoArg);
|
|
18
64
|
const targets = getTargets(cwd);
|
|
@@ -35,9 +81,49 @@ export const install = new Command("install")
|
|
|
35
81
|
}
|
|
36
82
|
}
|
|
37
83
|
console.log(table.toString());
|
|
84
|
+
if (opts.hooks) {
|
|
85
|
+
const hook = path.join(cwd, ".git", "hooks", "pre-commit");
|
|
86
|
+
if (fs.existsSync(hook)) {
|
|
87
|
+
fs.rmSync(hook);
|
|
88
|
+
console.log(chalk.red("🗑️ ") + `pre-commit gate hook removed (${hook})`);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
console.log(`pre-commit gate hook: ${chalk.dim("— absent")}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
38
94
|
console.log(chalk.bold(`\nOpenPitStop uninstalled (${removed} file(s) removed). Nothing else was touched.`));
|
|
39
95
|
return;
|
|
40
96
|
}
|
|
97
|
+
// Pre-commit gate hook first (independent of the slash-command files).
|
|
98
|
+
const hookPath = path.join(cwd, ".git", "hooks", "pre-commit");
|
|
99
|
+
if (opts.hooks) {
|
|
100
|
+
if (!fs.existsSync(path.join(cwd, ".git"))) {
|
|
101
|
+
console.log(chalk.yellow("\n⚠ not a git repo — skipping the pre-commit gate hook"));
|
|
102
|
+
}
|
|
103
|
+
else if (fs.existsSync(hookPath) && !force) {
|
|
104
|
+
const existing = fs.readFileSync(hookPath, "utf8");
|
|
105
|
+
if (existing.includes("OpenPitStop pre-commit gate")) {
|
|
106
|
+
console.log(chalk.green("\n✅ Pre-commit gate hook refreshed (already installed)"));
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
console.log(chalk.yellow("\n⚠ existing pre-commit hook kept — to combine, append this line to it:\n") +
|
|
110
|
+
chalk.dim(" npx --yes openpitstop@latest gate || exit $?\n"));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
fs.mkdirSync(path.dirname(hookPath), { recursive: true });
|
|
115
|
+
fs.writeFileSync(hookPath, PRE_COMMIT_HOOK);
|
|
116
|
+
try {
|
|
117
|
+
fs.chmodSync(hookPath, 0o755);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
/* Windows: no chmod, git still runs hooks via its bundled sh */
|
|
121
|
+
}
|
|
122
|
+
console.log(chalk.green("\n✅ Pre-commit gate hook installed at " + chalk.cyan(hookPath)));
|
|
123
|
+
console.log(chalk.dim(" Every commit is now gated before it can land — SUSPICIOUS → blocked," +
|
|
124
|
+
" CONFIRMED_CHEAT → blocked.\n Bypass once with: git commit --no-verify"));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
41
127
|
const templateText = fs.readFileSync(resolveTemplatePath(), "utf8");
|
|
42
128
|
const table = new Table({
|
|
43
129
|
head: ["Tool", "Path", "Status"],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,UAAU,EACV,mBAAmB,EACnB,aAAa,GACd,MAAM,yBAAyB,CAAC;AAEjC,MAAM,aAAa,GACjB,wKAAwK,CAAC;AAE3K,MAAM,iBAAiB,GACrB,4OAA4O,CAAC;AAE/O,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KAC1C,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openpitstop",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Deterministic scans + your coding agent's own reasoning, in one autonomous quality loop. Adds a /pitstop slash-command to any AI coding tool.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Krish-1507",
|
package/scripts/cheat-demo.cjs
CHANGED
|
@@ -14,7 +14,16 @@
|
|
|
14
14
|
* `pitstop gate` catches both, escalates to exit code 2, and blocks the
|
|
15
15
|
* commit. That is the product: the agent finally has a referee.
|
|
16
16
|
*
|
|
17
|
-
* Usage: node scripts/cheat-demo.cjs
|
|
17
|
+
* Usage: node scripts/cheat-demo.cjs (registry CLI)
|
|
18
|
+
* node scripts/cheat-demo.cjs --fast (reuse cached node_modules
|
|
19
|
+
* from demo-repo-integrity —
|
|
20
|
+
* skips `npm install` for a
|
|
21
|
+
* tight re-record)
|
|
22
|
+
* node scripts/cheat-demo.cjs --no-pitch (end the arc on the
|
|
23
|
+
* CONFIRMED_CHEAT box — the
|
|
24
|
+
* recording's money shot)
|
|
25
|
+
* node scripts/cheat-demo.cjs --fast --no-pitch (recording mode)
|
|
26
|
+
*
|
|
18
27
|
* (set PITSTOP_CLI to point at a build, e.g.
|
|
19
28
|
* PITSTOP_CLI="node D:/OpenPitStop-cli/dist/cli.js")
|
|
20
29
|
*/
|
|
@@ -26,11 +35,26 @@ const { execSync } = require("child_process");
|
|
|
26
35
|
|
|
27
36
|
const ROOT = path.resolve(__dirname, "..");
|
|
28
37
|
const CLI = process.env.PITSTOP_CLI || "npx openpitstop";
|
|
38
|
+
const args = process.argv.slice(2);
|
|
39
|
+
const fast = args.includes("--fast");
|
|
40
|
+
const noPitch = args.includes("--no-pitch");
|
|
29
41
|
|
|
30
42
|
const run = (cmd, cwd) => {
|
|
31
43
|
console.log(`\n$ ${cmd}`);
|
|
32
44
|
try {
|
|
33
|
-
|
|
45
|
+
execSync(cmd, { cwd, encoding: "utf8", stdio: ["pipe", "inherit", "inherit"] });
|
|
46
|
+
return { code: 0, out: "" };
|
|
47
|
+
} catch (e) {
|
|
48
|
+
return { code: e.status ?? 1, out: String(e.stdout ?? "") };
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Quiet variant: captures stdout so the gate box can be printed LAST —
|
|
53
|
+
// a recording should end on the CONFIRMED_CHEAT box, not on narration.
|
|
54
|
+
const runQuiet = (cmd, cwd) => {
|
|
55
|
+
console.log(`\n$ ${cmd}`);
|
|
56
|
+
try {
|
|
57
|
+
const out = execSync(cmd, { cwd, encoding: "utf8", stdio: ["pipe", "pipe", "inherit"] });
|
|
34
58
|
return { code: 0, out };
|
|
35
59
|
} catch (e) {
|
|
36
60
|
return { code: e.status ?? 1, out: String(e.stdout ?? "") };
|
|
@@ -47,13 +71,20 @@ function main() {
|
|
|
47
71
|
}
|
|
48
72
|
|
|
49
73
|
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "pitstop-cheat-demo-"));
|
|
50
|
-
fs.cpSync(src, tmp, {
|
|
74
|
+
fs.cpSync(src, tmp, {
|
|
75
|
+
recursive: true,
|
|
76
|
+
filter: (p) => fast || !/node_modules$/.test(p),
|
|
77
|
+
});
|
|
51
78
|
|
|
52
79
|
say("PITSTOP CHEAT-CATCH DEMO — the agent finally has a referee");
|
|
53
80
|
console.log(`demo repo: ${tmp}`);
|
|
54
81
|
|
|
55
82
|
say("ACT 1 — baseline: a real bug, a failing test, an honest scan");
|
|
56
|
-
|
|
83
|
+
if (!fast || !fs.existsSync(path.join(tmp, "node_modules"))) {
|
|
84
|
+
run("npm install --no-audit --no-fund", tmp);
|
|
85
|
+
} else {
|
|
86
|
+
console.log("(node_modules reused — npm install skipped)");
|
|
87
|
+
}
|
|
57
88
|
run("git init -q && git config user.email pitstop@demo.local && git config user.name \"OpenPitStop Demo\" && git add -A && git commit -q -m baseline", tmp);
|
|
58
89
|
const scan = run(`${CLI} scan`, tmp);
|
|
59
90
|
if (!/1 failed|failed 1|Tests\s*:.*fail/i.test(scan.out)) {
|
|
@@ -73,20 +104,30 @@ function main() {
|
|
|
73
104
|
'fit("splits a bill evenly to the cent"',
|
|
74
105
|
);
|
|
75
106
|
fs.writeFileSync(testFile, testCode, "utf8");
|
|
76
|
-
const act2 =
|
|
107
|
+
const act2 = runQuiet(`${CLI} gate`, tmp);
|
|
77
108
|
console.log("\nOpenPitStop's verdict: jest now runs ONLY the focused tests — the failing one is");
|
|
78
109
|
console.log("hidden, the suite is 'green', the bug is still there. SUSPICIOUS, needs a human.");
|
|
110
|
+
console.log(act2.out);
|
|
79
111
|
if (act2.code !== 1) {
|
|
80
112
|
console.log(`\nWARNING: expected gate exit 1 (SUSPICIOUS), got ${act2.code}`);
|
|
81
113
|
process.exitCode = 1;
|
|
82
114
|
}
|
|
115
|
+
run("git checkout -q -- test/money.test.js", tmp);
|
|
83
116
|
|
|
84
117
|
say("ACT 3 — the desperate 'fix': delete the failing test (CONFIRMED_CHEAT)");
|
|
85
118
|
run("git rm -q -f test/money.test.js", tmp);
|
|
86
|
-
const gate =
|
|
87
|
-
console.log(
|
|
119
|
+
const gate = runQuiet(`${CLI} gate`, tmp);
|
|
120
|
+
console.log(
|
|
121
|
+
`\ngate exit code: ${gate.code} — ` +
|
|
122
|
+
(gate.code === 2 ? "CONFIRMED_CHEAT. The commit is blocked." : `expected 2, got ${gate.code}`),
|
|
123
|
+
);
|
|
124
|
+
console.log(gate.out);
|
|
88
125
|
if (gate.code !== 2) process.exitCode = 1;
|
|
89
126
|
|
|
127
|
+
if (noPitch) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
90
131
|
say("THE PITCH");
|
|
91
132
|
console.log(
|
|
92
133
|
"Agents fix code; they don't know when to stop, and they'll tell you they're done regardless.\n" +
|
|
@@ -99,4 +140,4 @@ function main() {
|
|
|
99
140
|
);
|
|
100
141
|
}
|
|
101
142
|
|
|
102
|
-
main();
|
|
143
|
+
main();
|