@pablozrrrr/jevguard 0.2.3 → 0.3.1
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 +240 -79
- package/cli/main.js +4155 -1720
- package/index.js +3697 -1912
- package/package.json +14 -2
- package/skills/jev-init/SKILL.md +1 -1
- package/skills/jev-init/validate-init.js +1686 -843
- package/skills/jevguard-rules/SKILL.md +1 -1
- package/skills/jevguard-rules/validate-rules.js +1563 -724
package/README.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# JevGuard
|
|
2
2
|
|
|
3
3
|
> **Semantic policy engine for coding agents.**
|
|
4
|
+
>
|
|
5
|
+
> JevGuard reviews every change an AI coding agent makes against the rules of your
|
|
6
|
+
> repository, written in plain Markdown, and reports `PASS`, `WARN`, or `FAIL` per
|
|
7
|
+
> rule. It runs in the background for OpenCode and Claude Code, never blocks the
|
|
8
|
+
> agent, and never edits your code.
|
|
4
9
|
|
|
5
10
|

|
|
6
11
|
|
|
@@ -8,6 +13,30 @@ JevGuard checks the code an agent just changed against the policies that matter
|
|
|
8
13
|
your repository. It uses Jev for a narrow semantic judgment per rule, then applies
|
|
9
14
|
your local deterministic gate to return `PASS`, `WARN`, or `FAIL`.
|
|
10
15
|
|
|
16
|
+
| Host | Package | Status |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| [OpenCode](https://opencode.ai) | `@pablozrrrr/jevguard` | Available, targets OpenCode `1.18.32` |
|
|
19
|
+
| [Claude Code](https://claude.com/claude-code) | `@pablozrrrr/jevguard-claude-code` | Available through this repository's plugin marketplace |
|
|
20
|
+
| Codex | — | Planned |
|
|
21
|
+
|
|
22
|
+
## Quick start
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
# 1. Store your Jev key in the OS credential store (shared by both hosts)
|
|
26
|
+
bunx --package @pablozrrrr/jevguard jevguard login
|
|
27
|
+
|
|
28
|
+
# 2a. OpenCode: register the plugin in opencode.json
|
|
29
|
+
bunx --package @pablozrrrr/jevguard jevguard install
|
|
30
|
+
|
|
31
|
+
# 2b. Claude Code: install from the marketplace
|
|
32
|
+
claude plugin marketplace add pablozr/JevGuard
|
|
33
|
+
claude plugin install jevguard@jevguard
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Then add your rules to `.jev/rules.md` (in OpenCode, the bundled `jev-init` skill can
|
|
37
|
+
bootstrap them) and keep working with your agent as usual. Details are in
|
|
38
|
+
[Install](#install) and the [Claude Code guide](./docs/configuration.md#claude-code).
|
|
39
|
+
|
|
11
40
|
```text
|
|
12
41
|
agent completes a turn
|
|
13
42
|
↓
|
|
@@ -27,13 +56,20 @@ specific policy, and leaves planning, code generation, and correction with the
|
|
|
27
56
|
coding agent.
|
|
28
57
|
|
|
29
58
|
> [!WARNING]
|
|
30
|
-
> JevGuard is in active development. The
|
|
31
|
-
>
|
|
32
|
-
> and `COMPLEXITY` built-ins.
|
|
33
|
-
>
|
|
34
|
-
>
|
|
35
|
-
>
|
|
36
|
-
>
|
|
59
|
+
> JevGuard is in active development. The OpenCode plugin targets OpenCode `2.2.x`
|
|
60
|
+
> (minimum `2.2.2`, `>=2.2.2 <2.3`) through the V2 plugin API and evaluates every rule
|
|
61
|
+
> block declared in `.jev/rules.md` plus the `SCOPE-CREEP` and `COMPLEXITY` built-ins.
|
|
62
|
+
> Reviews are background and observe-only: they report results but never alter the
|
|
63
|
+
> agent context or block a task. When remediation is enabled and a review has any
|
|
64
|
+
> `FAIL`, the plugin asks for a proposal in an isolated, deny-all child session; the
|
|
65
|
+
> proposal never edits code. See [OpenCode 2.2.x limitations](#opencode-22x-limitations).
|
|
66
|
+
> On Claude Code and OpenCode, a user who opts in with `mode: remediate` in their own
|
|
67
|
+
> `claude-code.yaml` or `opencode.yaml` gets a bounded chain of at most 3 visible
|
|
68
|
+
> correction messages to the agent; see
|
|
69
|
+
> [Remediation proposals](docs/configuration.md#remediation-proposals) and
|
|
70
|
+
> [OpenCode `mode: remediate`](docs/configuration.md#opencode-mode-remediate-bounded-chain).
|
|
71
|
+
> The Claude Code plugin is distributed through this repository's marketplace; see the
|
|
72
|
+
> [Claude Code guide](./docs/configuration.md#claude-code).
|
|
37
73
|
|
|
38
74
|
## Why JevGuard
|
|
39
75
|
|
|
@@ -165,9 +201,12 @@ concurrency limit caps the plugin instance at two Jev requests in flight, counti
|
|
|
165
201
|
built-in batch as a single request. Results join the same aggregate in a fixed order:
|
|
166
202
|
rules in source order, then `SCOPE-CREEP`, then `COMPLEXITY`.
|
|
167
203
|
|
|
168
|
-
Reviews run in the background. The
|
|
169
|
-
|
|
170
|
-
the
|
|
204
|
+
Reviews run in the background. The unit of review is one session execution, from
|
|
205
|
+
`session.execution.started` to `session.execution.succeeded`; the event handler returns
|
|
206
|
+
as soon as the serialized attribution step is scheduled, so policy reads, Jev calls,
|
|
207
|
+
and presentation never sit on the agent's critical path. An `interrupted` or `failed`
|
|
208
|
+
execution is not reviewed: the plugin discards it and logs `JevGuard skipped ·
|
|
209
|
+
interrupted|failed`.
|
|
171
210
|
|
|
172
211
|
## Safe auto-propose remediation
|
|
173
212
|
|
|
@@ -178,7 +217,7 @@ delivered entirely by the same server plugin.
|
|
|
178
217
|
|
|
179
218
|
When `.jev/config.yaml` enables remediation (it is enabled by default) and a review
|
|
180
219
|
contains any `FAIL`, the plugin, after presenting the review, sends one aggregate
|
|
181
|
-
proposal request to
|
|
220
|
+
proposal request to an isolated child session:
|
|
182
221
|
|
|
183
222
|
- The request aggregates every `FAIL` finding in the review — local `error` rules and
|
|
184
223
|
the `SCOPE-CREEP` built-in — together with the turn's task and its **complete, safe,
|
|
@@ -188,28 +227,33 @@ proposal request to a hidden `jevguard-proposer` subagent:
|
|
|
188
227
|
attributed file is blocked or the patch is oversized, the plugin records no proposal
|
|
189
228
|
at all — even when a rule-scoped `FAIL` exists — because there is no complete safe
|
|
190
229
|
evidence to send. It never falls back to a repository or global diff.
|
|
191
|
-
- The request is sent in an isolated child session parented to the source session.
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
230
|
+
- The request is sent in an isolated child session parented to the source session.
|
|
231
|
+
The child session is created with wildcard-deny permissions, so it cannot call a
|
|
232
|
+
tool, edit a file, or produce a patch. It returns a strategy and one manual apply
|
|
233
|
+
instruction only. No agent is registered for it.
|
|
234
|
+
- The child session always gets an explicit model: `remediation.model` from
|
|
235
|
+
`.jev/config.yaml` when set, otherwise the model of the source session. When neither
|
|
236
|
+
is known, no proposal is created and the plugin logs
|
|
237
|
+
`REMEDIATION_PROPOSAL_SKIPPED_NO_MODEL`.
|
|
238
|
+
- A proposal that does not finish within 120 seconds is interrupted and logged as
|
|
239
|
+
`REMEDIATION_PROPOSAL_TIMEOUT`.
|
|
240
|
+
- The server plugin has no toast or TUI channel on OpenCode `2.2.x`, so readiness is
|
|
241
|
+
reported through the structured log only. It carries no rule, task, diff, finding,
|
|
242
|
+
or credential.
|
|
199
243
|
|
|
200
244
|
The plugin creates at most one proposal per evaluated turn, and the child session is
|
|
201
245
|
excluded from review for the plugin lifetime, so a proposal can never recurse or
|
|
202
246
|
trigger a second one. A host, model, or toast failure is contained and never changes
|
|
203
247
|
the review. A contained proposal failure — an invalid model specifier, a child-session
|
|
204
|
-
failure,
|
|
248
|
+
failure, a prompt failure, or a timeout — writes one structured
|
|
205
249
|
`error` log entry carrying only a typed reason code, never any task, diff, finding,
|
|
206
250
|
path, or credential.
|
|
207
251
|
|
|
208
252
|
The proposer is a strategy step, not an apply step: it never edits code, and nothing
|
|
209
253
|
is applied automatically. You read the proposal, copy its manual apply instruction
|
|
210
|
-
into your normal coding agent, and apply it there. That apply is an ordinary
|
|
211
|
-
|
|
212
|
-
|
|
254
|
+
into your normal coding agent, and apply it there. That apply is an ordinary
|
|
255
|
+
execution, so the server plugin reviews it normally when it succeeds — exactly like any
|
|
256
|
+
other turn.
|
|
213
257
|
|
|
214
258
|
The proposal prompt treats the task, paths, diff, rules, and findings as untrusted
|
|
215
259
|
data, and requires a separate explicit confirmation before proposing changes to tests,
|
|
@@ -219,8 +263,14 @@ or secret is logged.
|
|
|
219
263
|
## Install
|
|
220
264
|
|
|
221
265
|
Installing `@pablozrrrr/jevguard` does **not** register it with OpenCode by itself.
|
|
222
|
-
OpenCode only loads plugins listed in `
|
|
223
|
-
|
|
266
|
+
OpenCode `2.2.x` only loads plugins listed in `plugins: [...]` in `opencode.json`.
|
|
267
|
+
|
|
268
|
+
> [!WARNING]
|
|
269
|
+
> The `jevguard install` command below still writes the OpenCode `1.x` `plugin` key.
|
|
270
|
+
> Until it is migrated, register the plugin on `2.2.x` with the manual `plugins`
|
|
271
|
+
> entry shown after it.
|
|
272
|
+
|
|
273
|
+
The installer is run from the installed CLI:
|
|
224
274
|
|
|
225
275
|
```sh
|
|
226
276
|
# global config: ~/.config/opencode/opencode.json
|
|
@@ -230,10 +280,12 @@ jevguard install
|
|
|
230
280
|
jevguard install --project
|
|
231
281
|
```
|
|
232
282
|
|
|
233
|
-
The installer asks for confirmation, edits only the `
|
|
234
|
-
idempotent. It
|
|
235
|
-
|
|
236
|
-
|
|
283
|
+
The installer asks for confirmation, edits only the `plugins` array, and is
|
|
284
|
+
idempotent. It never writes the legacy `plugin` key, but an entry already there counts
|
|
285
|
+
as installed. It only edits a `plugins` array of package strings or
|
|
286
|
+
`{ "package": "..." }` objects; any other shape is left unchanged and the installer
|
|
287
|
+
prints the manual snippet instead. `jevguard doctor` also checks that
|
|
288
|
+
`opencode --version` is in the supported range `>=2.2.2 <2.3`. If `jevguard` is not on
|
|
237
289
|
`PATH`, run it through `bunx`:
|
|
238
290
|
|
|
239
291
|
```sh
|
|
@@ -243,7 +295,7 @@ bunx --package @pablozrrrr/jevguard jevguard install
|
|
|
243
295
|
The manual alternative is one entry in `opencode.json`:
|
|
244
296
|
|
|
245
297
|
```json
|
|
246
|
-
{ "
|
|
298
|
+
{ "plugins": ["@pablozrrrr/jevguard"] }
|
|
247
299
|
```
|
|
248
300
|
|
|
249
301
|
OpenCode resolves the package from the npm registry or its cache and loads it on the
|
|
@@ -258,9 +310,9 @@ after changing the plugin list.
|
|
|
258
310
|
### Build the local artifact
|
|
259
311
|
|
|
260
312
|
The artifact ships the plugin as a **locally packed tarball** that bundles the
|
|
261
|
-
private `@jevguard/core` and `@jevguard/opencode-adapter`
|
|
262
|
-
clean consumer installs one tarball and never resolves a
|
|
263
|
-
private registry package. It also packages the `jevguard-rules` and `jev-init`
|
|
313
|
+
private `@jevguard/core`, `@jevguard/node-infra` and `@jevguard/opencode-adapter`
|
|
314
|
+
workspace code, so a clean consumer installs one tarball and never resolves a
|
|
315
|
+
workspace link or a private registry package. It also packages the `jevguard-rules` and `jev-init`
|
|
264
316
|
skills and their private validators under `skills/<name>/`.
|
|
265
317
|
|
|
266
318
|
Build the tarball from this repository:
|
|
@@ -282,12 +334,12 @@ does not vendor them and does not promise an offline install.
|
|
|
282
334
|
|
|
283
335
|
### Load the plugin
|
|
284
336
|
|
|
285
|
-
OpenCode `
|
|
337
|
+
OpenCode `2.2.x` resolves a **bare** `opencode.json` `plugins` entry from the npm
|
|
286
338
|
registry or its cache:
|
|
287
339
|
|
|
288
340
|
```json
|
|
289
341
|
{
|
|
290
|
-
"
|
|
342
|
+
"plugins": ["@pablozrrrr/jevguard"]
|
|
291
343
|
}
|
|
292
344
|
```
|
|
293
345
|
|
|
@@ -301,18 +353,36 @@ bun add /path/to/pablozrrrr-jevguard-<version>.tgz
|
|
|
301
353
|
|
|
302
354
|
```ts
|
|
303
355
|
// .opencode/plugins/jevguard.ts
|
|
304
|
-
export {
|
|
356
|
+
export { default } from "@pablozrrrr/jevguard";
|
|
305
357
|
```
|
|
306
358
|
|
|
307
359
|
OpenCode loads `.opencode/plugins/` with its bundled Bun runtime. The shim runs as
|
|
308
360
|
a local plugin module and resolves `@pablozrrrr/jevguard` from
|
|
309
|
-
`.opencode/node_modules`. Use either the bare `
|
|
361
|
+
`.opencode/node_modules`. Use either the bare `plugins` entry or the local shim, not
|
|
310
362
|
both.
|
|
311
363
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
fails — creates the proposal child session automatically.
|
|
364
|
+
The package's default export is the V2 plugin object (`{ id: "jevguard", setup }`).
|
|
365
|
+
Remediation is built into the same server plugin, so no second entrypoint or shim is
|
|
366
|
+
needed: it reviews and reports executions, and — when remediation is enabled and a
|
|
367
|
+
review fails — creates the proposal child session automatically. The bundled skills are
|
|
368
|
+
registered through the host skill editor (`skill.transform`).
|
|
369
|
+
|
|
370
|
+
### Claude Code
|
|
371
|
+
|
|
372
|
+
Inside Claude Code:
|
|
373
|
+
|
|
374
|
+
```text
|
|
375
|
+
/plugin marketplace add pablozr/JevGuard
|
|
376
|
+
/plugin install jevguard@jevguard
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
The Claude Code plugin reviews each closed unit of work in a detached background
|
|
380
|
+
worker, shows the result in the session (status line, transcript line, and a toast on
|
|
381
|
+
`FAIL`) without sending it to the model, and records it in the same local history.
|
|
382
|
+
Remediation proposals are off by default and are enabled from your user config, never
|
|
383
|
+
from the repository. It needs `node` `>=22.13.0`, `npm`, and `git` on `PATH`. See the
|
|
384
|
+
[Claude Code guide](./docs/configuration.md#claude-code) for what is reviewed, the
|
|
385
|
+
in-session display, and remediation.
|
|
316
386
|
|
|
317
387
|
### Author rules with the bundled skill
|
|
318
388
|
|
|
@@ -361,11 +431,36 @@ jevguard login
|
|
|
361
431
|
|
|
362
432
|
Known limitations:
|
|
363
433
|
|
|
364
|
-
- Target host is OpenCode `
|
|
365
|
-
|
|
434
|
+
- Target host is OpenCode `2.2.x` (minimum `2.2.2`). The plugin does not load on
|
|
435
|
+
`2.1.x` or `1.x`. A real-host smoke on `2.2.2` (2026-11-02) covered observe
|
|
436
|
+
and `remediate` (FAIL review, deny-all proposer, attempt 1/2, `RESOLVED`).
|
|
437
|
+
- OpenCode `2.2.2` does not install dependencies for a `file:` plugin spec. Use
|
|
438
|
+
the registry package; a local `file:` build needs its dependencies installed
|
|
439
|
+
next to it.
|
|
366
440
|
- The plugin and CLI run on Bun, and the packed `jevguard` bin keeps a Bun
|
|
367
441
|
shebang. Install and run the artifact with the Bun runtime.
|
|
368
442
|
|
|
443
|
+
### OpenCode 2.2.x limitations
|
|
444
|
+
|
|
445
|
+
- **Minimum version `2.2.2`.** The plugin declares `engines.opencode` `>=2.2.2 <2.3`
|
|
446
|
+
and is pinned to the `2.2.x` plugin API.
|
|
447
|
+
- **Git-ignored files are out of scope.** The execution snapshot comes from the host's
|
|
448
|
+
working-tree diff, which leaves out files ignored by Git; a write the diff cannot
|
|
449
|
+
show makes the execution `UNAVAILABLE` (`INCOMPLETE_FILE_DIFF`) instead of reviewing
|
|
450
|
+
a partial patch.
|
|
451
|
+
- **Interrupted or failed executions are not reviewed.** Their writes stay on disk and
|
|
452
|
+
count as pre-existing changes for the next execution's snapshot, so they are not
|
|
453
|
+
attributed to it.
|
|
454
|
+
- **`opencode run --standalone`.** The review runs after the execution succeeds; a
|
|
455
|
+
standalone run can exit before it finishes. JevGuard reviews reliably in the TUI or
|
|
456
|
+
with `opencode serve` plus `opencode run --server`.
|
|
457
|
+
- **Concurrent executions.** When two sessions run at once, or an execution starts
|
|
458
|
+
while the previous one is still being finished, the review is `UNAVAILABLE`
|
|
459
|
+
(`CONCURRENT_SESSIONS`, `BOUNDARY_RACE`) instead of mixing changes. Nested child
|
|
460
|
+
sessions count as part of their parent execution.
|
|
461
|
+
- **No toast or TUI routing.** The server plugin reports through structured logs
|
|
462
|
+
written to the host's stderr capture.
|
|
463
|
+
|
|
369
464
|
## Connect Jev
|
|
370
465
|
|
|
371
466
|
For local use, connect once with the installed command:
|
|
@@ -390,8 +485,8 @@ JevGuard FAIL
|
|
|
390
485
|
pass 1 · warn 1 · fail 1 · skipped 0 · unavailable 0
|
|
391
486
|
```
|
|
392
487
|
|
|
393
|
-
|
|
394
|
-
structured log carries every rule's result, its raw violation probability or typed
|
|
488
|
+
The structured log (and, on hosts with a toast channel, one toast per turn) shows
|
|
489
|
+
the aggregate outcome and the outcome counts; the structured log carries every rule's result, its raw violation probability or typed
|
|
395
490
|
reason, and its scoped paths. The counts include every entry, including the single
|
|
396
491
|
synthetic entry a review-level failure produces.
|
|
397
492
|
|
|
@@ -427,6 +522,65 @@ The report prints aggregated counts, rule IDs, check IDs, and reason codes only
|
|
|
427
522
|
never file paths, tasks, diffs, or credentials. A missing or empty history is a
|
|
428
523
|
normal empty report, not an error.
|
|
429
524
|
|
|
525
|
+
### Rule feedback
|
|
526
|
+
|
|
527
|
+
Tell JevGuard whether a `FAIL` was right. The answer is stored locally and only
|
|
528
|
+
feeds the calibration shown by `jevguard report`; it never changes a rule, a
|
|
529
|
+
threshold, or what the model returns.
|
|
530
|
+
|
|
531
|
+
```sh
|
|
532
|
+
# unanswered rule FAILs, newest first, numbered
|
|
533
|
+
jevguard feedback
|
|
534
|
+
|
|
535
|
+
# answer one: right = a real violation, wrong = a false alarm
|
|
536
|
+
jevguard feedback 1 wrong
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
Numbers stay fixed to the last listing. Built-in checks are not covered. See
|
|
540
|
+
[configuration](./docs/configuration.md)
|
|
541
|
+
for details.
|
|
542
|
+
|
|
543
|
+
## Diagnose your setup
|
|
544
|
+
|
|
545
|
+
`jevguard doctor` checks your local setup without touching the network or changing
|
|
546
|
+
anything:
|
|
547
|
+
|
|
548
|
+
```sh
|
|
549
|
+
jevguard doctor
|
|
550
|
+
jevguard doctor --json
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
It reports `OK`, `WARN` or `FAIL` for the credential source, `.jev/rules.md`,
|
|
554
|
+
`.jev/config.yaml` and the OpenCode plugin registration, each with a hint when
|
|
555
|
+
something is wrong. It never prints the API key or any part of it — only whether the
|
|
556
|
+
key comes from the OS credential store or the `TYPESAFE_API_KEY` override. It exits
|
|
557
|
+
`0` unless a check fails (warnings are fine) and `1` when one does. The project root is
|
|
558
|
+
the first parent directory of the current directory that contains `.git`, or the
|
|
559
|
+
current directory when there is none. It does not check Claude Code installs yet.
|
|
560
|
+
|
|
561
|
+
## Check rules on demand
|
|
562
|
+
|
|
563
|
+
`jevguard rules check` runs your repository rules against a diff you provide, without
|
|
564
|
+
waiting for an agent turn:
|
|
565
|
+
|
|
566
|
+
```sh
|
|
567
|
+
git diff --cached | jevguard rules check --diff - --task "Add rate limiting to login"
|
|
568
|
+
jevguard rules check --diff change.diff --rule ARCH-001 --json
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
It evaluates the repository rules over the diff with the same scope filtering,
|
|
572
|
+
evidence safety, slicing and gate thresholds as a review, but runs no built-in checks,
|
|
573
|
+
starts no remediation and writes nothing to the review history. The input must be
|
|
574
|
+
plain `git diff` output (or a plain `---`/`+++` unified diff) with `a/` and `b/`
|
|
575
|
+
prefixes; anything else is refused whole, never partly evaluated (see
|
|
576
|
+
[configuration](./docs/configuration.md#cli-diagnostics-and-on-demand-rule-checks)).
|
|
577
|
+
`--task` is optional; without it a neutral default task is sent. It prints each rule's outcome, probability, severity and
|
|
578
|
+
scoped paths, never the task or the diff. Exit codes: `0` completed with no `FAIL` and
|
|
579
|
+
no `UNAVAILABLE`; `1` at least one rule `FAIL`ed; `2` it could not check completely
|
|
580
|
+
(invalid arguments, an unreadable or unsupported diff, an unknown `--rule`, or an
|
|
581
|
+
`UNAVAILABLE` result). See [configuration](./docs/configuration.md#cli-diagnostics-and-on-demand-rule-checks)
|
|
582
|
+
for the full contract.
|
|
583
|
+
|
|
430
584
|
## Implemented behavior
|
|
431
585
|
|
|
432
586
|
The current release implements the full local review path:
|
|
@@ -466,20 +620,20 @@ The current release implements the full local review path:
|
|
|
466
620
|
attributed patch a built-in is `SKIPPED`; blocked or oversized evidence is
|
|
467
621
|
`UNAVAILABLE`; a rule, policy-load, or config failure never suppresses the batch, and
|
|
468
622
|
one built-in's answer never suppresses the other.
|
|
469
|
-
- Reviews run in the background. The
|
|
470
|
-
attribution step is scheduled, so policy reads, Jev calls,
|
|
471
|
-
block the agent.
|
|
623
|
+
- Reviews run in the background. The `session.execution.succeeded` handler returns
|
|
624
|
+
as soon as the serialized attribution step is scheduled, so policy reads, Jev calls,
|
|
625
|
+
and presentation do not block the agent.
|
|
472
626
|
- The local gate maps each rule to `PASS`, `WARN`, or `FAIL`; a rule with no
|
|
473
627
|
applicable scope is `SKIPPED`, and a rule that cannot be safely evaluated is
|
|
474
628
|
`UNAVAILABLE`.
|
|
475
|
-
- One
|
|
629
|
+
- One structured log entry reports the turn (the `2.2.x` server plugin has no toast
|
|
630
|
+
channel). The log
|
|
476
631
|
carries every entry's outcome, raw probability, or reason, including the built-in
|
|
477
632
|
results and the synthetic review-level entry when there is one. The fixed result
|
|
478
633
|
order is rules in source order, then `SCOPE-CREEP`, then `COMPLEXITY`.
|
|
479
634
|
- After presentation, when remediation is enabled and the review contains any `FAIL`,
|
|
480
|
-
at most one aggregate proposal request is sent to
|
|
481
|
-
|
|
482
|
-
toast reports that the proposal is ready. The request carries every `FAIL` finding
|
|
635
|
+
at most one aggregate proposal request is sent to an isolated, deny-all child
|
|
636
|
+
session parented to the source session, with an explicit model. The request carries every `FAIL` finding
|
|
483
637
|
(local `error` rules and the `SCOPE-CREEP` built-in), the task, and the complete,
|
|
484
638
|
safe, full attributed patch; a blocked or oversized patch records no proposal. A
|
|
485
639
|
notifier or host failure never affects the review, presentation, or later turns.
|
|
@@ -491,30 +645,25 @@ ordinary turn is reviewed normally.
|
|
|
491
645
|
|
|
492
646
|
## Roadmap
|
|
493
647
|
|
|
494
|
-
|
|
495
|
-
|
|
648
|
+
Implemented so far: multi-rule reviews, the `SCOPE-CREEP` and `COMPLEXITY`
|
|
649
|
+
built-ins, the `jev-init` policy bootstrap, local review history with feedback and
|
|
650
|
+
calibration (`jevguard report`, `jevguard feedback`), on-demand checks
|
|
651
|
+
(`jevguard rules check`, `jevguard doctor`), and the Claude Code plugin. Planned work:
|
|
496
652
|
|
|
497
653
|
```text
|
|
498
|
-
V0.3 Remaining built-in semantic check: test adequacy
|
|
499
|
-
|
|
500
|
-
V0.
|
|
501
|
-
|
|
502
|
-
V0.
|
|
503
|
-
|
|
504
|
-
V0.
|
|
505
|
-
|
|
506
|
-
V0.7 Observe / enforce / remediate modes
|
|
507
|
-
↓
|
|
508
|
-
V0.8 Rule packs
|
|
509
|
-
↓
|
|
510
|
-
V0.9 Local feedback and calibration
|
|
511
|
-
↓
|
|
512
|
-
V1 Claude Code and Codex adapters
|
|
654
|
+
V0.3 Remaining built-in semantic check: test adequacy planned
|
|
655
|
+
V0.4 jev-init: evidence-based policy bootstrap done
|
|
656
|
+
V0.5 On-demand evidence and explanations partial (rules check)
|
|
657
|
+
V0.6 Opt-in, bounded auto-remediation planned
|
|
658
|
+
V0.7 Observe / enforce / remediate modes planned
|
|
659
|
+
V0.8 Rule packs planned
|
|
660
|
+
V0.9 Local feedback and calibration done
|
|
661
|
+
V1 Claude Code and Codex adapters Claude Code done, Codex planned
|
|
513
662
|
```
|
|
514
663
|
|
|
515
664
|
The auto-propose slice is implemented: after a review with a `FAIL`, an enabled
|
|
516
|
-
configuration asks
|
|
517
|
-
|
|
665
|
+
configuration asks for a strategy in an isolated, deny-all child session, and never
|
|
666
|
+
applies a change. The `V0.6` entry remains the
|
|
518
667
|
future, unattended corrective loop; the proposer is a bounded, strategy-only step, not
|
|
519
668
|
that loop.
|
|
520
669
|
|
|
@@ -527,17 +676,24 @@ CI and pull-request policy review come after V1, using the same versioned rules.
|
|
|
527
676
|
|
|
528
677
|
## Architecture
|
|
529
678
|
|
|
530
|
-
JevGuard is a pnpm TypeScript monorepo. The core has no dependency on OpenCode
|
|
531
|
-
|
|
679
|
+
JevGuard is a pnpm TypeScript monorepo. The core has no dependency on OpenCode,
|
|
680
|
+
Claude Code, or their runtimes, which keeps the evaluation model portable across
|
|
681
|
+
host adapters.
|
|
532
682
|
|
|
533
683
|
```text
|
|
534
684
|
packages/
|
|
535
685
|
├── core/ domain, policy, evaluation, gate
|
|
686
|
+
├── claude-code-adapter/ Claude Code tool-attributed units, hook and review worker
|
|
687
|
+
├── claude-code-plugin/ Claude Code plugin composition and artifact
|
|
688
|
+
├── node-infra/ shared Node infra: credentials, Jev transport, policy, history
|
|
536
689
|
├── opencode-adapter/ OpenCode attribution and presentation
|
|
537
690
|
├── plugin/ OpenCode composition root and CLI
|
|
538
691
|
└── testkit/ fixtures and contract helpers
|
|
539
692
|
|
|
540
|
-
plugin → opencode-adapter → core
|
|
693
|
+
plugin → opencode-adapter → node-infra → core
|
|
694
|
+
plugin ────────────────────→ node-infra
|
|
695
|
+
claude-code-plugin → claude-code-adapter → node-infra → core
|
|
696
|
+
testkit ──────────────────────────────→ core
|
|
541
697
|
```
|
|
542
698
|
|
|
543
699
|
## Status
|
|
@@ -548,18 +704,23 @@ loads in OpenCode, attributes one completed turn, parses every rule block in
|
|
|
548
704
|
the `SCOPE-CREEP`
|
|
549
705
|
and `COMPLEXITY` built-ins over the complete attributed patch behind one shared
|
|
550
706
|
concurrency limit, applies the local gate to each, and presents one aggregate result
|
|
551
|
-
as a
|
|
707
|
+
as a structured log entry.
|
|
552
708
|
|
|
553
709
|
The local, private tarball (`pnpm artifact:build`, `pnpm artifact:pack`) packages
|
|
554
710
|
that slice so a clean consumer can install it without workspace links.
|
|
555
711
|
|
|
556
|
-
OpenCode sees only
|
|
557
|
-
|
|
712
|
+
OpenCode sees only structured logs and — when remediation is enabled and a review
|
|
713
|
+
has a `FAIL` — one proposal child session.
|
|
558
714
|
The review does not inject anything into the agent context, prompt the source session,
|
|
559
715
|
add session messages, or block a task. The proposal is a separate, configurable,
|
|
560
716
|
strategy-only workflow delivered by the server plugin; it never edits code and never
|
|
561
|
-
applies a change.
|
|
562
|
-
|
|
717
|
+
applies a change. A real-host smoke on OpenCode `2.2.2` passed; see
|
|
718
|
+
[OpenCode 2.2.x limitations](#opencode-22x-limitations).
|
|
719
|
+
|
|
720
|
+
The Claude Code plugin reuses the same core, policy files, gate, and local history. It
|
|
721
|
+
reviews closed units of work in a detached worker and shows results in the session
|
|
722
|
+
without sending them to the model; see the
|
|
723
|
+
[Claude Code guide](./docs/configuration.md#claude-code).
|
|
563
724
|
|
|
564
725
|
## Development
|
|
565
726
|
|