@brokkai/slopcop 0.0.8 → 0.0.10

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
@@ -101,6 +101,25 @@ installs `slopcop.exe` to `%LOCALAPPDATA%\Programs\slopcop`, and adds that
101
101
  directory to the user `Path`. `SLOPCOP_VERSION`, `SLOPCOP_INSTALL_DIR`, and
102
102
  `SLOPCOP_NO_MODIFY_PATH` override its defaults.
103
103
 
104
+ ### Upgrade notice
105
+
106
+ Every response from the service names its newest release in the
107
+ `SlopCop-Latest-Version` header. When that is newer than the running build,
108
+ the CLI prints one line on stderr, never stdout, so `--format json` and
109
+ `sarif` stay clean:
110
+
111
+ ```text
112
+ slopcop v0.0.9 is available (you have v0.0.7). Upgrade: npm install --global @brokkai/slopcop@latest
113
+ ```
114
+
115
+ The command follows the channel the binary was installed through (npm, npx,
116
+ pip, pipx, or uv), judged by where it lives, and links back here otherwise.
117
+ The notice prints at most once a day; the time of the last one is kept in
118
+ `slopcop/update-notice` next to the config. `dev` builds, `Stop` hook runs, and
119
+ runs with `$SLOPCOP_NO_UPDATE_NOTICE` set to any non-empty value never print
120
+ it. A service that no longer accepts a version answers `client_outdated`
121
+ (HTTP 426), which exits `2`.
122
+
104
123
  ### Go
105
124
 
106
125
  ```console
@@ -229,42 +248,65 @@ add`: a first check adds a repository. When the workspace would then pay for
229
248
  it (it already has an active repository and is charged), the service refuses
230
249
  the check with `repository_add_unconfirmed` until a person confirms: at a
231
250
  terminal `check` prints what it costs, asks `Add owner/name to "Workspace"?
232
- [y/N]`, and on a yes sends the check again; with no terminal, as for an agent
233
- or CI, it exits `2` with the service's remedy. A workspace's first repository
234
- is added without asking. Deleting repositories, archiving
235
- workspaces, members, credits and repository settings stay in the web app. The
236
- commands exit `0` on success and `2` with the service's message and remedy
237
- otherwise, as `ignore` does.
251
+ [y/N]`, and on a yes sends the check again and says `added owner/name to
252
+ "Workspace"` on stderr. With no terminal, as for an agent or CI (a pipe or the
253
+ null device is not one), nothing is asked: the check exits `4` with the
254
+ service's remedy, a line naming the command that confirms it, and, in `json`,
255
+ a `failed` report naming the code. A no at the terminal ends the same way.
256
+ Once the person has approved it, `check --add-repository --workspace
257
+ <name|id>` confirms without a terminal; the flag needs `--workspace` (the
258
+ flag itself, not `$SLOPCOP_WORKSPACE`), so an approval given for one
259
+ workspace cannot add the repository to the one the login happens to point at.
260
+ The flag changes nothing for a repository already in that workspace. A
261
+ workspace's first repository is added without asking. Deleting repositories,
262
+ archiving workspaces, members, credits and repository settings stay in the web
263
+ app. The commands exit `0` on success and `2` with the service's message and
264
+ remedy otherwise, as `ignore` does.
238
265
 
239
266
  ## Check
240
267
 
241
268
  ```console
242
269
  slopcop # check the change in the current checkout
243
270
  slopcop check --format json # same, machine-readable
244
- slopcop --root ../repo --base HEAD~1
271
+ slopcop --root ../repo --base origin/main
245
272
  ```
246
273
 
247
274
  The base commit defaults to the merge base with the branch upstream, then the
248
- merge base with `origin/HEAD`, then `HEAD`. The service must already have the
249
- base commit in its clone; a missing one comes back as the service's
250
- `base_not_found` message and remedy.
275
+ merge base with `origin/HEAD`, then `HEAD` when neither is known. When the
276
+ upstream merge base yields an empty patch, as on a branch whose commits are all
277
+ pushed, the CLI uses the merge base with `origin/HEAD` instead, so a check
278
+ right after a push still covers the branch. `--base REV` names the branch the
279
+ change started from and, like `git diff REV...HEAD`, uses the merge base of
280
+ `REV` and `HEAD`, so commits that landed on `REV` after the branch point are not
281
+ sent as reverse edits. `--base-exact REV` diffs against `REV` itself. The
282
+ service must already have the base commit in its clone; a missing one comes back as the service's
283
+ `base_not_found` message and remedy. The CLI then asks origin for its default
284
+ branch (`git ls-remote`, no prompt, 10 second limit) and adds a line when the
285
+ clone explains the failure: origin's default branch was renamed and
286
+ `origin/HEAD` still names the old one, or the base is not on origin's default
287
+ branch.
251
288
 
252
289
  Every run sends one check request, even when the working tree matches the base
253
290
  and the patch is empty. A clean result or a failure always comes from the
254
- service.
291
+ service. A report for an empty patch comes with a note on stderr that suggests
292
+ `--base`, and `json` adds `"emptyChange": true` (`sarif`:
293
+ `properties["slopcop.emptyChange"]`): a clean result then means nothing
294
+ changed was checked.
255
295
 
256
296
  Flags:
257
297
 
258
298
  | Flag | Meaning |
259
299
  | --- | --- |
260
300
  | `--root PATH` | repository to check (default `.`) |
261
- | `--base REV` | base commit or revision for the change |
301
+ | `--base REV` | branch or revision the change started from; the base is its merge base with `HEAD` |
302
+ | `--base-exact REV` | exact base commit or revision, without a merge base |
262
303
  | `--format human\|json\|sarif` | report format (default `human`) |
263
304
  | `--fail-on never\|finding\|note\|warning\|error` | exit-1 threshold for new findings (default `finding`) |
264
305
  | `--policy PATH` | repository-relative `.rqlp` file to evaluate (repeatable) |
265
306
  | `--no-policy-discovery` | skip `.slopcop/policies` rules |
266
307
  | `--timeout DURATION` | how long to wait for the result (default `10m`) |
267
308
  | `-w`, `--workspace NAME\|ID` | check in, and bill, this workspace of the account instead of the login's |
309
+ | `--add-repository` | add the repository to the workspace `--workspace` names, which then pays for it, without asking at a terminal; for after the user approved it |
268
310
  | `--verbose` | print the resolved request to stderr |
269
311
 
270
312
  ### What is sent
@@ -342,8 +384,8 @@ summary line such as `1 new finding across 1 file(s); 72 already in the code |
342
384
  Analysis complete`, and any omitted new findings or
343
385
  incomplete checks. `json` prints `status`, `baseCommit`, `summary`
344
386
  (`newFindings` and `existingFindings` count the split), `findings` (each with
345
- `new` and its `id`), `incomplete`, and `failure` when the analysis did not
346
- complete. `sarif` prints a SARIF 2.1.0 log whose results carry `baselineState`
387
+ `new` and its `id`), `incomplete`, `failure` when the analysis did not
388
+ complete, and `emptyChange` when the patch was empty. `sarif` prints a SARIF 2.1.0 log whose results carry `baselineState`
347
389
  `new` and the finding id in `properties["slopcop.findingId"]`. `--format` only
348
390
  changes the rendering, never the request, so the service answers the same check
349
391
  whichever is used.
@@ -354,6 +396,7 @@ whichever is used.
354
396
  | `1` | A new finding crossed `--fail-on` |
355
397
  | `2` | No new finding crossed `--fail-on`, but a check was incomplete; or the CLI or service failed |
356
398
  | `3` | The check was still running when `--timeout` ran out |
399
+ | `4` | The service refused the check, and only a person can clear it |
357
400
  | `130`, `143` | Interrupted before the check answered: `130` for Ctrl-C, `143` for SIGTERM |
358
401
 
359
402
  Only `clean` exits `0`: a status this CLI does not know exits `2`, so a newer
@@ -393,9 +436,23 @@ rewrite them. The remedies name no client, so the CLI adds its own command
393
436
  after some: `slopcop login` when the remedy is to sign in, the listing to
394
437
  choose from after `workspace_not_found` or `workspace_repository_not_found`,
395
438
  and `slopcop whoami` after `repository_disabled`, since the workspace that
396
- disabled it is the one this login is bound to, and `--workspace` after
397
- `owner_required`. A failed request prints no
398
- report on stdout.
439
+ disabled it is the one this login is bound to, `--workspace` after
440
+ `owner_required`, and `--add-repository --workspace "Name"`, with the
441
+ workspace the check would have added the repository to, after
442
+ `repository_add_unconfirmed`. A failed check exits `4` when only a person can
443
+ clear the refusal (`auth_required`, `auth_expired`, `account_required`,
444
+ `repo_not_indexed`, `app_not_installed`, `app_no_repo_access`,
445
+ `gitlab_not_connected`, `no_access`, `insufficient_credits`,
446
+ `repository_disabled`, `repository_add_unconfirmed`,
447
+ `workspace_repository_limit_reached`, `active_repository_limit_reached`,
448
+ `owner_required`, and `browser_required`), so a script can stop instead of
449
+ retrying, and `2` otherwise. Stderr starts with the code, as in `slopcop:
450
+ repository_add_unconfirmed: …`. `human` prints nothing on stdout; `json`
451
+ prints `{"status": "failed", "code": …, "message": …, "remedy": …,
452
+ "retryable": …}`, plus `installUrl` or `topUpUrl` when the service sent one;
453
+ `sarif` prints a run with `slopcop.status` `failed`, whose invocation is
454
+ unsuccessful and carries an `error` notification whose descriptor id is the
455
+ code.
399
456
 
400
457
  ## API
401
458
 
@@ -412,11 +469,11 @@ The CLI calls `POST <service>/v1/check` with a bearer token:
412
469
  }
413
470
  ```
414
471
 
415
- `addRepository` is sent only after a person confirms adding the repository. The
416
- service rejects any other field. With `--workspace`, every request, the
417
- check's, the ignore's and the account routes', carries the workspace's id in
418
- the `SlopCop-Workspace` header; a name is first looked up with
419
- `GET <service>/v1/whoami`. The response carries `status`,
472
+ `addRepository` is sent only after a person confirms adding the repository, at
473
+ the terminal or with `--add-repository`. The service rejects any other field.
474
+ With `--workspace`, every request, the check's, the ignore's and the account
475
+ routes', carries the workspace's id in the `SlopCop-Workspace` header; a name
476
+ is first looked up with `GET <service>/v1/whoami`. The response carries `status`,
420
477
  `baseCommit`, `applied`, `summary`, `findings`, `incomplete`, and `failure`
421
478
  when the analysis did not complete. Against a service from before findings
422
479
  were marked `new`, the CLI treats every finding as new, as that service gated
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brokkai/slopcop",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "Static analysis for coding agents and CI: check a change through the hosted SlopCop API",
5
5
  "keywords": [
6
6
  "agents",