@brokkai/slopcop 0.0.5 → 0.0.7

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
@@ -138,6 +138,35 @@ Precedence:
138
138
  | Service URL | `--service`, `$SLOPCOP_SERVICE`, stored by `slopcop login`, `https://slopcop.com` |
139
139
  | Token | `$SLOPCOP_TOKEN`, stored value |
140
140
 
141
+ ## Workspace and repositories
142
+
143
+ A login runs its checks and ignores in, and bills, one workspace: the one
144
+ active in the browser when the login was approved.
145
+
146
+ ```console
147
+ slopcop whoami # account, this login's workspace, its plan, the service URL
148
+ slopcop workspace list # the account's workspaces; * marks this login's
149
+ slopcop workspace use "Acme team" # move this login (not the browser) to another, by name or id
150
+ slopcop repo list # the workspace's repositories: active, disabled, or over the limit
151
+ slopcop repo disable acme/widgets # stop checking and charging for one (owner only)
152
+ slopcop repo enable acme/widgets # turn it back on, within the workspace's active limit
153
+ ```
154
+
155
+ `whoami`, `workspace list` and `repo list` take `--format human|json`, as do
156
+ `workspace use` and `repo enable|disable` for their answer. Every active
157
+ repository after a workspace's first costs credits every 30 days; a disabled
158
+ one is not checked or charged and keeps its reports, findings and settings.
159
+ `repo enable` and `repo disable` ask you to type the repository's `owner/name`
160
+ and refuse when stdin is not a terminal: an agent or CI job runs with your
161
+ login, and the service cannot tell it from you, so changing what the workspace
162
+ pays stays a step you take yourself.
163
+ Names match without regard to case; when two workspaces share a name, or two
164
+ providers a repository name, pass the id the listing prints. There is no `repo
165
+ add`: a first check adds a repository. Deleting repositories, archiving
166
+ workspaces, members, credits and repository settings stay in the web app. The
167
+ commands exit `0` on success and `2` with the service's message and remedy
168
+ otherwise, as `ignore` does.
169
+
141
170
  ## Check
142
171
 
143
172
  ```console
@@ -163,7 +192,6 @@ Flags:
163
192
  | `--base REV` | base commit or revision for the change |
164
193
  | `--format human\|json\|sarif` | report format (default `human`) |
165
194
  | `--fail-on never\|finding\|note\|warning\|error` | exit-1 threshold for new findings (default `finding`) |
166
- | `--show-existing` | also list the findings that were already in the code |
167
195
  | `--policy PATH` | repository-relative `.rqlp` file to evaluate (repeatable) |
168
196
  | `--no-policy-discovery` | skip `.slopcop/policies` rules |
169
197
  | `--timeout DURATION` | how long to wait for the result (default `10m`) |
@@ -178,6 +206,26 @@ changes, and binary content. Git-ignored files stay out, except selected
178
206
  `.slopcop/policies` rules, which must travel because the service evaluates them
179
207
  from the patched checkout.
180
208
 
209
+ A check run by a Claude Code or Codex agent also sends which models wrote the
210
+ change, so the service can tie each finding to the model that wrote its file.
211
+ The CLI finds the agent's session from its environment and reads that
212
+ session's own record:
213
+
214
+ - **Claude Code:** `CLAUDE_CODE_SESSION_ID` names the transcript under
215
+ `~/.claude/projects` (or `$CLAUDE_CONFIG_DIR/projects`), subagents included.
216
+ Each successful Write, Edit, MultiEdit or NotebookEdit gives a model, an
217
+ effort and a file.
218
+ - **Codex:** `CODEX_THREAD_ID` names the rollout under `~/.codex/sessions` (or
219
+ `$CODEX_HOME/sessions`). Each completed file change gives the files, and its
220
+ turn gives the model and effort. A move counts as writing its destination.
221
+
222
+ It reads only those fields, never the conversation, tool input or file
223
+ contents. What it sends is the harness, its version, the session id as an
224
+ opaque identifier, and each model and effort with the repository-relative
225
+ files it wrote. A check run outside an agent session sends none of this. It
226
+ is analytics only, asserted by the client, and never decides a check.
227
+ `--verbose` prints it.
228
+
181
229
  The service owns the limits on what a check accepts. When a change is too
182
230
  large or touches too many files, the service's `payload_too_large` response is
183
231
  printed verbatim; the CLI does not impose its own limits.
@@ -191,9 +239,13 @@ Every check also runs the hosted catalog. Rules under
191
239
  A check fails only on findings the change introduced or touched: the service
192
240
  marks a finding new when it is in a file the change writes and its lines meet a
193
241
  line the change added, or the line beside one it removed. Findings that were
194
- already in the code are counted, never fail the check, and are listed only with
195
- `--show-existing`. A change that introduces nothing exits `0`, however many
196
- findings the repository already holds.
242
+ already in the code are counted (`summary.existingFindings`, and `N already in
243
+ the code` in the human summary), never fail the check, and are not listed. A
244
+ change that introduces nothing exits `0`, however many findings the repository
245
+ already holds. `--show-existing` is deprecated and hidden: the service no longer
246
+ sends those findings, so against it the flag lists nothing (a service from
247
+ before that still gets them listed), and it stays so that scripts passing it
248
+ keep running.
197
249
 
198
250
  ### Ignore a false positive
199
251
 
@@ -215,16 +267,16 @@ check outside your workspace.
215
267
  ### Output and exit codes
216
268
 
217
269
  The service answers structured data; the CLI renders it. `human` prints one
218
- block per new finding, with an `ID:` line when the service names one, then the
219
- pre-existing ones with `--show-existing`, a
220
- summary line such as `1 new finding across 1 file(s); 72 already in the code
221
- (--show-existing lists them) | Analysis complete`, and any omitted or
270
+ block per new finding, with an `ID:` line when the service names one, then a
271
+ summary line such as `1 new finding across 1 file(s); 72 already in the code |
272
+ Analysis complete`, and any omitted new findings or
222
273
  incomplete checks. `json` prints `status`, `baseCommit`, `summary`
223
274
  (`newFindings` and `existingFindings` count the split), `findings` (each with
224
275
  `new` and its `id`), `incomplete`, and `failure` when the analysis did not
225
276
  complete. `sarif` prints a SARIF 2.1.0 log whose results carry `baselineState`
226
- `new` or `unchanged` and the finding id in `properties["slopcop.findingId"]`. `--format` and `--show-existing` only change the rendering, never
227
- the request, so the service answers the same check whichever is used.
277
+ `new` and the finding id in `properties["slopcop.findingId"]`. `--format` only
278
+ changes the rendering, never the request, so the service answers the same check
279
+ whichever is used.
228
280
 
229
281
  | Exit | Meaning |
230
282
  | --- | --- |
@@ -232,13 +284,20 @@ the request, so the service answers the same check whichever is used.
232
284
  | `1` | A new finding crossed `--fail-on` |
233
285
  | `2` | No new finding crossed `--fail-on`, but a check was incomplete; or the CLI or service failed |
234
286
  | `3` | The check was still running when `--timeout` ran out |
287
+ | `130`, `143` | Interrupted before the check answered: `130` for Ctrl-C, `143` for SIGTERM |
235
288
 
236
- An inconclusive check fails the check only when it concerns a file the
237
- change writes. One about other files is listed on an `Inconclusive outside
238
- the change` line (`inconclusiveElsewhere` in `json`, a `note` notification in
239
- `sarif`) and never changes the exit code. A check that timed out counts
240
- wherever it is. The service can place an inconclusive check only once Bifrost
241
- reports which files it concerns; until then every one counts as in the change.
289
+ Only `clean` exits `0`: a status this CLI does not know exits `2`, so a newer
290
+ service can never pass a check by accident, and stderr names the status. An
291
+ interrupted check prints no report. Interrupted before it was sent, nothing
292
+ reached the service; after, a service that received it keeps running it, and
293
+ running the same check again picks up its result.
294
+
295
+ An inconclusive check, one that ran but could not prove there is nothing
296
+ more to find, never changes the exit code and is not named in any format.
297
+ Complete proof is rare in static analysis, typically at a library boundary,
298
+ so this is the norm rather than a gap. `summary.inconclusive` counts them in
299
+ `json`, as does `slopcop.inconclusive` in `sarif`. A check that timed out or
300
+ that Bifrost judged unreliable is incomplete and counts wherever it is.
242
301
 
243
302
  The service applies `--fail-on` and sets the status; the exit code follows it.
244
303
  The CLI always sends `--fail-on`, defaulting to `finding`: a check fails only
@@ -260,9 +319,12 @@ again picks up the same analysis.
260
319
  Service failures print the closed contract exactly: message, remedy, and any
261
320
  install URL. The codes, messages, and remedies are defined by the service in
262
321
  `server/src/check.rs` of `BrokkAi/bifrost-service`; the CLI does not
263
- rewrite them. The remedies name no client, so when one says to sign in the CLI
264
- adds the `slopcop login` command after it. A failed request prints no report
265
- on stdout.
322
+ rewrite them. The remedies name no client, so the CLI adds its own command
323
+ after some: `slopcop login` when the remedy is to sign in, the listing to
324
+ choose from after `workspace_not_found` or `workspace_repository_not_found`,
325
+ and `slopcop whoami` after `repository_disabled`, since the workspace that
326
+ disabled it is the one this login is bound to. A failed request prints no
327
+ report on stdout.
266
328
 
267
329
  ## API
268
330
 
@@ -293,11 +355,27 @@ token and `{"findingId": "<id>"}`, and gets back
293
355
  `{"findingId": "<id>", "status": "ignored"}`. Failures use the same closed
294
356
  contract, including `finding_not_found`.
295
357
 
358
+ The account commands use the same bearer token. `GET <service>/v1/whoami`
359
+ answers `account`, `workspace` (`id`, `name`, `kind`, `role`, `current`),
360
+ `plan` (`pro` or `free`) and `workspaces`. `POST <service>/v1/workspace` with
361
+ `{"workspaceId"}` rebinds the login. `GET <service>/v1/repositories` answers
362
+ `repositories` (`id`, `provider`, `fullName`, `enabled`, `active`) with
363
+ `activeRepositoryLimit`, `activeRepositories` and `canManageRepositories`, and
364
+ `POST <service>/v1/repositories/state` with `{"repositoryId", "enabled"}`
365
+ answers `{repositoryId, fullName, enabled, active}`. Their failure codes add
366
+ `account_required`, `workspace_not_found`, `workspace_repository_not_found`,
367
+ `owner_required` and `browser_required` (a private Bitbucket or GitLab
368
+ repository, which only the web app can change) to the check's.
369
+
296
370
  `slopcop login` uses the device flow: `POST /api/device` returns a
297
371
  `deviceCode`, `userCode`, `verificationUri`, `expiresIn`, and `interval`, and
298
372
  `POST /api/token` returns `202` while pending or `200` with a `token` once
299
- approved. The polling codes are `authorization_pending`, `slow_down`,
300
- `expired_token`, and `access_denied`.
373
+ approved. The failure codes are `slow_down`, which raises the polling interval,
374
+ `expired_token`, `access_denied`, and `device_flow_disabled`. A failure the
375
+ service marks `retryable`, such as `rate_limited` or `service_unavailable`,
376
+ keeps the code valid, and so do a dropped connection and a proxy's `429`,
377
+ `502`, `503` or `504` without a code: login waits the `Retry-After`, or the
378
+ interval if that is longer, and polls again until the code expires.
301
379
 
302
380
  ## Development
303
381
 
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.5",
3
+ "version": "0.0.7",
4
4
  "description": "Static analysis for coding agents and CI: check a change through the hosted SlopCop API",
5
5
  "keywords": [
6
6
  "agents",