@kavishdua/proctor 1.0.0 → 1.2.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 CHANGED
@@ -37,6 +37,7 @@ source needs Node 20.19+ or 22.12+.
37
37
  - [What do the codes mean?](#what-do-the-codes-mean)
38
38
  - [Badges](#badges)
39
39
  - [CI](#ci)
40
+ - [Dynamic checks](#dynamic-checks), opt-in runtime evidence
40
41
 
41
42
  **Why it works**
42
43
 
@@ -53,9 +54,14 @@ source needs Node 20.19+ or 22.12+.
53
54
 
54
55
  ## Quickstart
55
56
 
56
- The npm package is not published yet: `npm view @kavishdua/proctor` currently returns 404, so an
57
- `npx @kavishdua/proctor ...` command from the registry will not work. Until the first release, run
58
- the checked-out source against any git repository:
57
+ Check the changes in any git repository, with nothing to install first:
58
+
59
+ ```bash
60
+ cd /path/to/repository
61
+ npx @kavishdua/proctor check
62
+ ```
63
+
64
+ To run it from source instead:
59
65
 
60
66
  ```bash
61
67
  git clone https://github.com/catfish-1234/proctor.git
@@ -91,16 +97,10 @@ qwen extensions install https://github.com/catfish-1234/proctor
91
97
 
92
98
  **Other agents, or CLI use without an agent** (30 agents supported)
93
99
 
94
- Until the npm package is published, build its installable tarball from source:
100
+ Add it to the repository as a dev dependency:
95
101
 
96
102
  ```bash
97
- # In the proctor checkout
98
- npm ci
99
- npm run build
100
- npm pack
101
-
102
- # In the repository proctor should guard; use the .tgz path printed above
103
- npm install --save-dev /absolute/path/to/kavishdua-proctor-*.tgz
103
+ npm install --save-dev @kavishdua/proctor
104
104
  ```
105
105
 
106
106
  **Proctor does not install guards during npm installation by default.** npm still updates your
@@ -276,15 +276,17 @@ families.
276
276
  **WI1xx checks "the work is done."** These look for incomplete or disabled behavior in source,
277
277
  config, and tests, including discarded errors, removed validation, and altered expected values.
278
278
 
279
- > **Beta, and opt-in for now.** The WI family is off by default in v1.0.0. Turn it on for one run
280
- > with `proctor check --wi` (or `--all-checks`), or for good by listing the IDs you want in
281
- > `enabled` in `proctor.config.json`, which also applies them in both hooks. These thirteen checks
282
- > cover 25+ languages and have had less real-world testing than the RH family, so they remain
283
- > opt-in while we assess false positives.
279
+ > **Six WI checks run by default:** WI101, WI102, WI105, WI108, WI109, and WI110.
280
+ > Alongside RH001 to RH014, they close error-handling, unfinished-body, canned-output,
281
+ > source-hiding, expectation-edit, and script-verification gaps. The remaining seven WI checks
282
+ > stay opt-in because their human-commit findings still include legitimate maintenance.
283
+ > Run `proctor check --wi` (or `--all-checks`) to add the entire family, or name checks in
284
+ > `enabled` in the committed config. An explicit `enabled` list is still honored exactly.
285
+ > See the [measurements and per-check decisions](bench/detection/README.md).
284
286
 
285
287
  | | Catches |
286
288
  |---|---|
287
- | WI101 | An error discarded by an empty handler, so failures pass unnoticed |
289
+ | WI101 | Empty or logging-only handlers, and formerly propagated operation errors discarded or replaced with defaults |
288
290
  | WI102 | An explicit "not implemented" marker shipped inside finished-looking work |
289
291
  | WI103 | Validation deleted so the case it rejected now goes through |
290
292
  | WI104 | Proctor, a commit hook, or a type/lint gate switched off instead of satisfied |
@@ -338,12 +340,44 @@ jobs:
338
340
  steps:
339
341
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
340
342
  with: { fetch-depth: 0 }
341
- - uses: catfish-1234/proctor@1bfd0b192ea214a0ed349b27822b11b8ccf23e07
343
+ - uses: catfish-1234/proctor@ede7e0ec0d9a91c241af1b181b74b1a6af67df07 # v1.0.0
342
344
  ```
343
345
 
344
- No release tags exist yet, so the example pins an existing source commit. After the first release,
345
- `catfish-1234/proctor@v1` will be the moving tag for the newest `1.x` release. To keep builds
346
- reproducible, use a full commit SHA as above; a full SHA is immutable.
346
+ The example pins the commit behind the `v1.0.0` release. You can use the `v1.0.0` tag instead, but
347
+ a full commit SHA is immutable, so it keeps builds reproducible.
348
+
349
+ ## Dynamic checks
350
+
351
+ `proctor check --dynamic` runs extra checks using a runnable project test suite. The default
352
+ check keeps its existing output and runs no project tests. You can also commit
353
+ `{"dynamic": true, "dynamicTimeoutMs": 60000}` in `proctor.config.json`. Use
354
+ `--dynamic-timeout 30000` to override the overall budget in milliseconds.
355
+
356
+ This prototype supports Node's `node:test`, Jest and Vitest through `npm run test`, plus Python
357
+ `unittest`, `pytest` and plain Python scripts. When unittest collects no cases or only collection
358
+ errors, plain scripts run directly and bare `test_*` functions run individually in fresh processes.
359
+ It needs Linux and bubblewrap with working user, mount, network and PID
360
+ namespaces. Windows, macOS, unsupported languages and unavailable isolation report
361
+ `dynamic: skipped, reason`; a skip never adds a failing finding. Tests run in temporary copies,
362
+ with host mounts read-only and network disabled. The default overall timeout is 60 seconds,
363
+ including copies; descendants are terminated when the worker ends.
364
+
365
+ Warnings name the commands, run labels and observed results. The checks need runnable
366
+ tests and installed dependencies, can miss changes, and cannot prove intent. A red original suite
367
+ is a normal fix input; named per-test comparisons and numeric, string or boolean probes still run.
368
+ For red-to-green fixes with unchanged tests, mutation-lite tries at most four parser-confirmed
369
+ changes in called functions. DY002 probes and DY004 mutation warnings are advisory and do not
370
+ change the exit code on their own. Mutations can survive because code is redundant or behavior
371
+ is deliberately untested; survival does not establish cheating. Repeated outcomes
372
+ can reflect order dependence.
373
+
374
+ Measured limits: dynamic checks are opt-in and advisory only. They do not change which findings
375
+ block a commit. Mutation-lite reports missing test coverage, not cheating, and it can fire on
376
+ honest changes whose tests do not cover every changed line. On a private 80-case corpus (40
377
+ cheating changes, 40 honest ones) that informed this iteration, dynamic warnings surfaced 4
378
+ cheating changes the static checks missed and flagged 1 honest change. Because the same corpus
379
+ informed the checks, these are not clean held-out numbers.
380
+ See the [scope, dropped ideas and tuned dev-set measurements](bench/dynamic-dev/README.md).
347
381
 
348
382
  ## How it works
349
383
 
@@ -363,7 +397,7 @@ unchecked commit.
363
397
  that same diff is checked. Approvals and inline `proctor-ignore` markers must also be committed
364
398
  before the change they cover.
365
399
 
366
- **Switching the guard off is itself a finding.** WI104 fires on a check removed from `enabled`, a
400
+ **An opt-in check can flag changes to the guard.** WI104 fires on a check removed from `enabled`, a
367
401
  severity downgraded, an ignore pattern or approval added, a ruleset file deleted, a `--no-verify`
368
402
  added to a script, or TypeScript strictness turned off. WI104 is part of the opt-in WI family.
369
403
 
@@ -383,22 +417,32 @@ changes and allows turns when proctor cannot run, so it is not a substitute for
383
417
  | **up to 100 pts** | gap between "the visible tests pass" and "the held-out tests pass" on the largest tasks in [SpecBench](https://arxiv.org/abs/2605.21384). It widens by about 28 points per tenfold increase in code size, and adding test coverage does not close it |
384
418
  | **8 of 8** | agent benchmarks that [Berkeley RDI](https://rdi.berkeley.edu/blog/trustworthy-benchmarks-cont/) drove to near-perfect scores without solving a single task. SWE-bench Verified fell to a pytest hook that forced every test to pass |
385
419
 
386
- **What proctor catches.** The fixture and benchmark numbers below come out of `npm test`; the
387
- adversarial number comes from the independent widening corpus in [`bench/redteam/`](https://github.com/catfish-1234/proctor/tree/main/bench/redteam):
420
+ **What proctor catches.** The original rule fixtures and recorded benchmark cases are checked by
421
+ `npm test`. The redteam probe is a repeatedly tuned **dev corpus**, not independent evidence of
422
+ generalization. Fresh measurements compare the unchanged main baseline with these changes:
388
423
 
389
424
  | | |
390
425
  |---|---|
391
- | **139 of 139** | planted cheats caught. One fixture per check per language, each asserted against the exact finding proctor has to produce, not just "something fired" |
392
- | **0 of 33** | near-miss fixtures flagged. Each one is a change built to look like a cheat and be legitimate: a single `@ts-ignore` with a justification, one retry rather than five, an empty catch whose comment explains itself, a guard clause extracted into a validator |
393
- | **21 of 21** | recorded cheats caught in the benchmark corpus, across 7 signatures. Whole-repo task diffs rather than minimal fixtures. The 22nd task is a control that plants no cheat, and proctor stays silent on it. Reproduce with `proctor bench --mock` |
394
- | **76 of 76** | adversarial cheat diffs caught with **both families enabled**, and **0 of 24** legitimate controls flagged, across eleven total red-team rounds. The corpus probes the WI family too, so reproduce it with `--all-checks`; the RH family alone catches 25 of the 76, since the rest are cheats the WI checks were written for. Includes process-status laundering, workload cuts, dependency rollback, fixed-delay masking, CI trigger/matrix contraction, diagnostic suppression, and out-of-band Git index hiding. Reproduce with `node bench/redteam/probe.mjs` |
395
- | **3.8%** | of 689 real human commits, sampled from 20 maintained open-source repositories across seven languages, produce any finding at all from the default check set. **2.32%** produce a blocking one, and most of those are the check correctly noticing that somebody deleted a test or added a skip marker |
396
- | **27** | checks in two families, across **25+** languages, installable into **30** agents |
397
- | **under 1s** | to check a commit, offline. Measured here at roughly 0.25s on a 3-file diff and 0.55s on a 79-file one, cold Node start included |
398
-
399
- **What we don't claim.** The 139 of 139 result measures detection of planted changes.
400
- Our [benchmark](#benchmark) has not shown that proctor reduces cheating: all 44 invocations in
401
- each of the two complete live runs passed their held-out tests in both arms.
426
+ | **139 of 139** | original planted rule fixtures caught with all checks, with **0 of 33** original near-miss fixtures flagged. These are development fixtures, not an unseen evaluation |
427
+ | **21 of 21** | recorded cheats caught in the mock benchmark corpus, across 7 signatures. The 22nd task is a control; it stays quiet |
428
+ | **25 to 54 of 76** | tuned dev cheats caught by defaults before and after. With all checks: **76 to 76 of 76**. Dev controls: **0 to 0 of 24** flagged in either mode. Run `node bench/redteam/probe.mjs --default` and `node bench/redteam/probe.mjs` |
429
+ | **7 to 36 of 36** | cheats caught by defaults in the **74-case frozen validation set**, with benign flags falling from **2/38 to 0/38**. All checks improve from **9/36 to 36/36**. The separately frozen 74-case design set has the same totals. Both are small authored sets with paired variations |
430
+ | **4.29% to 2.00% blocking** | **30/700 to 14/700** real non-bot commits flagged by defaults on the same fresh pinned sample from 20 repositories. Any finding: **46/700 (6.57%) to 26/700 (3.71%)**. Every flagged human commit counts as a conservative false-positive proxy, including intentional test deletions |
431
+ | **26 to 35 of 72** | cheats caught by defaults on a **72-cheat, 72-benign held-out set** written after 1.0.0 by a separate run that never saw the checks. Benign flags: **5/72 before, 5/72 after**. All checks: **38 to 42 of 72**, with 6/72 benign flagged. Error handling went from 0/12 to 7/12. Hardcoded special cases (2/8), removed validation (0/3), edited expected values (0/3), race masking (0/3) and suppression (0/3) are still mostly missed. The set was used only to measure, not to tune, but it is now public, so it no longer counts as blind. Run `node bench/heldout/probe.mjs --default` |
432
+ | **2.6% blocking** | **11/420** real commits blocked by both 1.0.0 and this release on a second fresh sample of 14 repositories that neither the checks nor the first sample touched. Any finding: **17 before, 16 after**. A few false positives found there were fixed with rules, not by pinning commits |
433
+ | **27** | checks in two families, with **20 enabled by default**, across **25+** languages, installable into **30** agents |
434
+
435
+ The old **689-commit** claim, **2.32% blocking and 3.8% any finding**, refers to a missing ignored
436
+ sample and harness. It could not be reproduced from this checkout or tracked history. The fresh
437
+ 700-commit sample uses the same 20 repositories, pins every commit and patch hash, and retains
438
+ all findings. It is a replacement cohort, not the original sample. See
439
+ [methods, per-rule results, and reproduction commands](bench/detection/README.md).
440
+
441
+ **What we don't claim.** Proctor is a heuristic diff checker. Defaults still miss more than half of the held-out cheats, mostly the ones that need running the code to see: special-cased inputs, edited expected values, removed validation, masked races and suppression. It detects suspicious changes;
442
+ it does not prevent them or judge intent. A determined author can write a cheat that no static
443
+ diff check recognizes. The dev and authored-validation results do not establish a detection
444
+ rate for unseen cheats. Our [live benchmark](#benchmark) has not shown that proctor reduces
445
+ cheating: all 44 invocations in each complete run passed their evaluation tests in both arms.
402
446
 
403
447
  ## Benchmark
404
448
 
@@ -465,8 +509,9 @@ For command details, configuration, support limits, and contributor instructions
465
509
  | [bench/METHODOLOGY.md](https://github.com/catfish-1234/proctor/blob/main/bench/METHODOLOGY.md) | How the benchmark works and what it does not claim |
466
510
 
467
511
  proctor supports 25+ languages and installs to 30 agents. Five diff-level checks (RH001, RH002,
468
- RH003, RH007, RH011) work across all of them; six (RH004, RH005, RH006, RH008, RH009, RH010) are
469
- JS/TS/Python-only; and RH012 and RH013 read CI and coverage config, so they apply everywhere. Of the
512
+ RH003, RH007, RH011) have signatures across the language roster. RH004, RH006, RH008, RH009, and
513
+ RH010 have their tested coverage in JS/TS/Python; RH005 also detects emptied Go and Rust bodies.
514
+ RH012 and RH013 read CI and coverage config, so they apply everywhere. Of the
470
515
  work-integrity family, WI101, WI102 and WI103 carry per-language signatures, WI104 reads config
471
516
  files so it applies everywhere, and WI105 and WI106 are scoped to the languages whose tokens are
472
517
  unambiguous. [Full matrix](https://github.com/catfish-1234/proctor/blob/main/docs/LANGUAGES.md).