@brokkai/slopcop 0.0.2 → 0.0.4

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 CHANGED
@@ -1,50 +1,102 @@
1
1
  # SlopCop
2
2
 
3
- SlopCop checks a change through the yet to be deployed hosted SlopCop check
4
- API. The CLI ships the working-tree change to the service, the service applies
5
- it to the base commit and runs the hosted policy catalog plus any repository
6
- rules selected, and the CLI prints the report. There is no local analyzer: a check never needs a
7
- Bifrost install, and the CLI never decides on its own that there is nothing to
8
- check.
9
-
10
- The command is built for agents and one-shot CI: no prompts, one request, and
11
- the analyzer's exit contract.
3
+ **Static analysis deep enough for CI, fast enough to run on every edit.**
4
+
5
+ [![CI](https://github.com/BrokkAi/slopcop/actions/workflows/ci.yml/badge.svg)](https://github.com/BrokkAi/slopcop/actions/workflows/ci.yml)
6
+ [![Release](https://img.shields.io/github/v/release/BrokkAi/slopcop)](https://github.com/BrokkAi/slopcop/releases/latest)
7
+ [![npm](https://img.shields.io/npm/v/@brokkai/slopcop)](https://www.npmjs.com/package/@brokkai/slopcop)
8
+ [![PyPI](https://img.shields.io/pypi/v/brokk-slopcop)](https://pypi.org/project/brokk-slopcop/)
9
+ [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
10
+ [![Go](https://img.shields.io/badge/Go-1.25%2B-blue.svg)](https://go.dev/)
11
+
12
+ `slopcop` sends one git patch, from the base commit to the working tree, to the
13
+ hosted check API at <https://slopcop.com>. The service applies it, runs the
14
+ hosted policy catalog plus the repository rules you selected, and returns the
15
+ report: every finding with its severity, the file and line that triggered it,
16
+ and the certainty behind it. The analysis is
17
+ [Bifrost](https://github.com/BrokkAi/bifrost), an open-source static analysis
18
+ engine rather than a language model, so a finding traces back to a rule instead
19
+ of to a guess.
20
+
21
+ There is no local analyzer and nothing to install per language: the CLI ships
22
+ the change and prints what comes back, and it never decides on its own that
23
+ there is nothing to check. The command is built for agents and one-shot CI: no
24
+ prompts, one request, and the analyzer's exit contract.
12
25
 
13
26
  ## Install
14
27
 
28
+ npm, PyPI, the release archive, and the PowerShell installer all install the
29
+ same release binary for macOS, Linux, and Windows on x64 and arm64, so
30
+ `slopcop version` reports which release it came from. The Go toolchain can
31
+ build that binary from source instead.
32
+
33
+ | Channel | Platforms | Needs |
34
+ | --- | --- | --- |
35
+ | [npm](#npm) | macOS, Linux, Windows | Node 22 or newer |
36
+ | [PyPI](#pypi) | macOS, Linux, Windows | Python 3.9 or newer |
37
+ | [Release archive](#release-archive) | macOS, Linux, Windows | nothing |
38
+ | [PowerShell installer](#powershell-installer) | Windows | PowerShell |
39
+ | [Go](#go) | built from source | Go 1.25 or newer |
40
+
41
+ ### npm
42
+
15
43
  ```console
16
- make install
44
+ npm install --global @brokkai/slopcop
45
+ slopcop --help
17
46
  ```
18
47
 
19
- or:
48
+ The tarball carries the release binary for every supported platform, so it
49
+ needs no Go toolchain. `npx @brokkai/slopcop` runs it without installing it.
50
+
51
+ ### PyPI
20
52
 
21
53
  ```console
22
- go install github.com/BrokkAi/slopcop/cmd/slopcop@latest
54
+ pip install brokk-slopcop
23
55
  ```
24
56
 
25
- Go 1.25 or newer is required to build.
57
+ `pipx install brokk-slopcop` or `uv tool install brokk-slopcop` puts it in an
58
+ environment of its own. The wheels carry the release binary, so no Go toolchain
59
+ is needed either. The package is `brokk-slopcop` because PyPI already has an
60
+ unrelated project named `slopcop`; the command it installs is still `slopcop`,
61
+ and `python -m brokk_slopcop` runs the same binary.
26
62
 
27
- On Windows, the PowerShell installer takes the latest release instead of
28
- building:
63
+ ### Release archive
64
+
65
+ Each release publishes `slopcop_v<version>_<os>_<arch>.tar.gz` (`.zip` on
66
+ Windows) holding the binary, `README.md`, and `LICENSE`, plus a `checksums.txt`
67
+ covering every archive. Download them from
68
+ <https://github.com/BrokkAi/slopcop/releases/latest> and check the sha256
69
+ before unpacking:
70
+
71
+ ```console
72
+ ver=0.0.3; os=linux; arch=amd64 # darwin/arm64 on Apple silicon
73
+ base=https://github.com/BrokkAi/slopcop/releases/download/v$ver
74
+ curl -fsSLO "$base/slopcop_v${ver}_${os}_${arch}.tar.gz"
75
+ curl -fsSLO "$base/checksums.txt"
76
+ grep "${os}_${arch}" checksums.txt | sha256sum -c - # shasum -a 256 -c - on macOS
77
+ tar -xzf "slopcop_v${ver}_${os}_${arch}.tar.gz" slopcop
78
+ sudo install -m 755 slopcop /usr/local/bin/slopcop
79
+ ```
80
+
81
+ ### PowerShell installer
29
82
 
30
83
  ```powershell
31
84
  irm https://raw.githubusercontent.com/BrokkAi/slopcop/master/install.ps1 | iex
32
85
  ```
33
86
 
34
- It verifies the release checksum, installs `slopcop.exe` to
35
- `%LOCALAPPDATA%\Programs\slopcop`, and adds that directory to the user `Path`.
36
- `SLOPCOP_VERSION`, `SLOPCOP_INSTALL_DIR`, and `SLOPCOP_NO_MODIFY_PATH` override
37
- its defaults.
87
+ It takes the latest release, verifies the archive against `checksums.txt`,
88
+ installs `slopcop.exe` to `%LOCALAPPDATA%\Programs\slopcop`, and adds that
89
+ directory to the user `Path`. `SLOPCOP_VERSION`, `SLOPCOP_INSTALL_DIR`, and
90
+ `SLOPCOP_NO_MODIFY_PATH` override its defaults.
38
91
 
39
- The npm package carries the release binary for macOS, Linux, and Windows on x64
40
- and arm64, so it needs no Go toolchain:
92
+ ### Go
41
93
 
42
94
  ```console
43
- npm install --global @brokkai/slopcop
44
- npx @brokkai/slopcop --help
95
+ go install github.com/BrokkAi/slopcop/cmd/slopcop@latest
45
96
  ```
46
97
 
47
- Node 22 or newer is required to run that package.
98
+ Go 1.25 or newer is required to build. A plain `go install` reports `dev` as
99
+ its version; in a clone, `make install` stamps the version from `git describe`.
48
100
 
49
101
  ## Enable it in an agent
50
102
 
@@ -107,10 +159,11 @@ Flags:
107
159
  | `--root PATH` | repository to check (default `.`) |
108
160
  | `--base REV` | base commit or revision for the change |
109
161
  | `--format human\|json\|sarif` | report format (default `human`) |
110
- | `--fail-on never\|finding\|note\|warning\|error` | exit-1 threshold (default `finding`) |
162
+ | `--fail-on never\|finding\|note\|warning\|error` | exit-1 threshold for new findings (default `finding`) |
163
+ | `--show-existing` | also list the findings that were already in the code |
111
164
  | `--policy PATH` | repository-relative `.rqlp` file to evaluate (repeatable) |
112
165
  | `--no-policy-discovery` | skip `.slopcop/policies` rules |
113
- | `--timeout DURATION` | one check request timeout (default `10m`) |
166
+ | `--timeout DURATION` | how long to wait for the result (default `10m`) |
114
167
  | `--verbose` | print the resolved request to stderr |
115
168
 
116
169
  ### What is sent
@@ -130,21 +183,58 @@ Every check also runs the hosted catalog. Rules under
130
183
  `.slopcop/policies/**/*.rqlp` are added automatically unless
131
184
  `--no-policy-discovery` is set.
132
185
 
186
+ ### New and pre-existing findings
187
+
188
+ A check fails only on findings the change introduced or touched: the service
189
+ marks a finding new when it is in a file the change writes and its lines meet a
190
+ line the change added, or the line beside one it removed. Findings that were
191
+ already in the code are counted, never fail the check, and are listed only with
192
+ `--show-existing`. A change that introduces nothing exits `0`, however many
193
+ findings the repository already holds.
194
+
133
195
  ### Output and exit codes
134
196
 
135
197
  The service answers structured data; the CLI renders it. `human` prints one
136
- block per finding, a summary line, and any omitted or incomplete checks. `json`
137
- prints `status`, `baseCommit`, `summary`, `findings`, `incomplete`, and
138
- `failure` when the analysis did not complete. `sarif` prints a SARIF 2.1.0
139
- log.
198
+ block per new finding, then the pre-existing ones with `--show-existing`, a
199
+ summary line such as `1 new finding across 1 file(s); 72 already in the code
200
+ (--show-existing lists them) | Analysis complete`, and any omitted or
201
+ incomplete checks. `json` prints `status`, `baseCommit`, `summary`
202
+ (`newFindings` and `existingFindings` count the split), `findings` (each with
203
+ `new`), `incomplete`, and `failure` when the analysis did not complete. `sarif`
204
+ prints a SARIF 2.1.0 log whose results carry `baselineState` `new` or
205
+ `unchanged`. `--format` and `--show-existing` only change the rendering, never
206
+ the request, so the service answers the same check whichever is used.
140
207
 
141
208
  | Exit | Meaning |
142
209
  | --- | --- |
143
- | `0` | Check completed; nothing crossed the `--fail-on` level |
144
- | `1` | A finding crossed `--fail-on` |
145
- | `2` | The check was incomplete, or the CLI or service failed |
210
+ | `0` | Check completed; no new finding crossed the `--fail-on` level |
211
+ | `1` | A new finding crossed `--fail-on` |
212
+ | `2` | No new finding crossed `--fail-on`, but a check was incomplete; or the CLI or service failed |
213
+ | `3` | The check was still running when `--timeout` ran out |
214
+
215
+ An inconclusive check fails the check only when it concerns a file the
216
+ change writes. One about other files is listed on an `Inconclusive outside
217
+ the change` line (`inconclusiveElsewhere` in `json`, a `note` notification in
218
+ `sarif`) and never changes the exit code. A check that timed out counts
219
+ wherever it is. The service can place an inconclusive check only once Bifrost
220
+ reports which files it concerns; until then every one counts as in the change.
146
221
 
147
222
  The service applies `--fail-on` and sets the status; the exit code follows it.
223
+ The CLI always sends `--fail-on`, defaulting to `finding`: a check fails only
224
+ on findings the change introduced, so any of them, a note or an unrated one
225
+ included, is worth fixing before the change lands. The service's own default
226
+ for a request without `failOn` is Bifrost's `warning`; pass `--fail-on warning`
227
+ to match it.
228
+ New findings that cross `--fail-on` exit `1` even when some check did not
229
+ complete.
230
+
231
+ While the service answers `check_running`, the CLI waits the `Retry-After` it
232
+ names and asks again until `--timeout` runs out; every ask attaches to the same
233
+ running check. If it is still running then, the CLI exits `3`, prints the
234
+ service's message and remedy on stderr, and in `json` prints
235
+ `{"status": "pending", "retryAfter": 5, "message": …, "remedy": …}` on stdout
236
+ (`sarif` prints a run with `slopcop.status` `pending`). Running the same check
237
+ again picks up the same analysis.
148
238
 
149
239
  Service failures print the closed contract exactly: message, remedy, and any
150
240
  install URL. The codes, messages, and remedies are defined by the service in
@@ -173,7 +263,9 @@ The CLI calls `POST <service>/v1/check` with a bearer token:
173
263
 
174
264
  The service rejects any other field. The response carries `status`,
175
265
  `baseCommit`, `applied`, `summary`, `findings`, `incomplete`, and `failure`
176
- when the analysis did not complete. Non-2xx responses carry `code`, `message`,
266
+ when the analysis did not complete. Against a service from before findings
267
+ were marked `new`, the CLI treats every finding as new, as that service gated
268
+ on all of them. Non-2xx responses carry `code`, `message`,
177
269
  `remedy`, `retryable`, and an optional `installUrl`.
178
270
 
179
271
  `slopcop login` uses the device flow: `POST /api/device` returns a
@@ -190,6 +282,7 @@ make vet # go vet ./...
190
282
  make build # bin/slopcop-<goos>-<goarch>
191
283
  make cross-check # linux, darwin, and windows on amd64 and arm64
192
284
  make npm-test # node --test npm/test
285
+ make wheels # pypi-dist/, one wheel per release target
193
286
  ```
194
287
 
195
288
  Releases are tag-driven. Pushing a `v*.*.*` tag runs GoReleaser, which builds
@@ -202,6 +295,12 @@ locally when GoReleaser is installed. The same tag push then packs
202
295
  [trusted publishing](docs/npm-publishing.md), so the package needs no npm
203
296
  token.
204
297
 
298
+ The same tag also packs a wheel per release target from the binaries GoReleaser
299
+ just built, installs the wheel for every platform GitHub can run, and
300
+ publishes `brokk-slopcop` to PyPI with
301
+ [trusted publishing](docs/pypi-publishing.md), so that package needs no PyPI
302
+ token either.
303
+
205
304
  Layout:
206
305
 
207
306
  | Path | Purpose |
@@ -213,6 +312,8 @@ Layout:
213
312
  | `internal/report` | human, JSON, and SARIF rendering from the structured response |
214
313
  | `internal/config` | stored service URL and token |
215
314
  | `npm` | launcher, packer, and tests of the `@brokkai/slopcop` package |
315
+ | `packaging/pypi` | wheel packer and launcher of the `brokk-slopcop` package |
216
316
  | `skills/slopcop` | the agent skill the binary embeds and installs |
217
317
  | `docs/npm-publishing.md` | npm release flow and trusted publisher setup |
318
+ | `docs/pypi-publishing.md` | PyPI release flow and trusted publisher setup |
218
319
  | `.goreleaser.yaml` | tag release build, archives, and checksums |
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,7 +1,18 @@
1
1
  {
2
2
  "name": "@brokkai/slopcop",
3
- "version": "0.0.2",
4
- "description": "Check a change through the hosted SlopCop check API",
3
+ "version": "0.0.4",
4
+ "description": "Static analysis for coding agents and CI: check a change through the hosted SlopCop API",
5
+ "keywords": [
6
+ "agents",
7
+ "ai-agent",
8
+ "ci",
9
+ "cli",
10
+ "code-review",
11
+ "coding-agent",
12
+ "git",
13
+ "sarif",
14
+ "static-analysis"
15
+ ],
5
16
  "license": "Apache-2.0",
6
17
  "repository": {
7
18
  "type": "git",