@pablozrrrr/jevguard 0.1.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/LICENSE +21 -0
- package/README.md +417 -0
- package/cli/main.js +1813 -0
- package/index.js +2022 -0
- package/package.json +53 -0
- package/skills/jevguard-rules/SKILL.md +158 -0
- package/skills/jevguard-rules/validate-rules.js +991 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 JevGuard contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
# JevGuard
|
|
2
|
+
|
|
3
|
+
> **Semantic policy engine for coding agents.**
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
JevGuard checks the code an agent just changed against the policies that matter in
|
|
8
|
+
your repository. It uses Jev for a narrow semantic judgment per rule, then applies
|
|
9
|
+
your local deterministic gate to return `PASS`, `WARN`, or `FAIL`.
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
agent completes a turn
|
|
13
|
+
↓
|
|
14
|
+
task + attributed diff + local rules
|
|
15
|
+
↓
|
|
16
|
+
Jev per rule
|
|
17
|
+
↓
|
|
18
|
+
local policy gate per rule
|
|
19
|
+
↓
|
|
20
|
+
PASS · WARN · FAIL
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Not a code generator. Not a prose review bot. Not another static linter.
|
|
24
|
+
|
|
25
|
+
JevGuard is a semantic linter: it asks whether a specific change violated a
|
|
26
|
+
specific policy, and leaves planning, code generation, and correction with the
|
|
27
|
+
coding agent.
|
|
28
|
+
|
|
29
|
+
> [!WARNING]
|
|
30
|
+
> JevGuard is in active development. The current release targets OpenCode `1.18.31`,
|
|
31
|
+
> evaluates every rule block declared in `.jev/rules.md` plus the `SCOPE-CREEP` and
|
|
32
|
+
> `COMPLEXITY` built-ins, and runs in observe mode only: it reports results but never
|
|
33
|
+
> alters the agent context or blocks a task.
|
|
34
|
+
|
|
35
|
+
## Why JevGuard
|
|
36
|
+
|
|
37
|
+
Traditional linters are excellent at syntax, types, and patterns. They cannot
|
|
38
|
+
reliably answer repository-specific questions such as:
|
|
39
|
+
|
|
40
|
+
- Did a controller start making domain decisions?
|
|
41
|
+
- Did this business-rule change arrive without meaningful tests?
|
|
42
|
+
- Did the agent solve a small task by introducing an unnecessary abstraction?
|
|
43
|
+
- Did a change cross an architectural boundary that this codebase protects?
|
|
44
|
+
|
|
45
|
+
JevGuard makes those questions versioned, scoped, and machine-actionable.
|
|
46
|
+
|
|
47
|
+
```md
|
|
48
|
+
## ARCH-001
|
|
49
|
+
|
|
50
|
+
severity: error
|
|
51
|
+
scope: backend/**
|
|
52
|
+
|
|
53
|
+
### Rule
|
|
54
|
+
|
|
55
|
+
HTTP controllers must not contain business logic.
|
|
56
|
+
|
|
57
|
+
### Violation
|
|
58
|
+
|
|
59
|
+
A controller performs domain decisions, calculations, or state mutations directly.
|
|
60
|
+
|
|
61
|
+
### Allowed
|
|
62
|
+
|
|
63
|
+
Validation, HTTP mapping and delegation to services.
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The rule stays in the repository beside the code it governs. `Allowed` is a real
|
|
67
|
+
exception, not a suggestion. JevGuard evaluates it as part of the same rule.
|
|
68
|
+
|
|
69
|
+
## The contract
|
|
70
|
+
|
|
71
|
+
JevGuard is built around one non-negotiable idea: review the **change that belongs
|
|
72
|
+
to the turn**, not whatever happens to be in the worktree.
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
user task
|
|
76
|
+
↓
|
|
77
|
+
assistant response
|
|
78
|
+
↓
|
|
79
|
+
attributed patch
|
|
80
|
+
↓
|
|
81
|
+
applicable rules
|
|
82
|
+
↓
|
|
83
|
+
one semantic judgment per rule
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
If complete attributed evidence is unavailable, too large, invalid, or contains a
|
|
87
|
+
blocked sensitive file, JevGuard marks the affected rule `UNAVAILABLE`. It never
|
|
88
|
+
turns incomplete evidence into a reassuring verdict. Evidence problems are scoped
|
|
89
|
+
to the rules they affect: a rule whose applicable files are all safe still runs
|
|
90
|
+
even when another rule's evidence is blocked.
|
|
91
|
+
|
|
92
|
+
Some failures happen before any policy rule is evaluated. If the attributed diff
|
|
93
|
+
cannot be built, the review is a single synthetic `UNAVAILABLE` entry with no rule
|
|
94
|
+
ID, and neither lane runs. If the turn is attributed but the policy files cannot be
|
|
95
|
+
read or validated, the rule lane reports one synthetic `UNAVAILABLE` entry with no
|
|
96
|
+
rule ID — it does not invent one result per declared rule — while the built-in batch
|
|
97
|
+
still runs against the turn's attributed patch.
|
|
98
|
+
|
|
99
|
+
## How a review works
|
|
100
|
+
|
|
101
|
+
For every applicable rule, JevGuard sends Jev one focused yes/no question:
|
|
102
|
+
|
|
103
|
+
> Does this attributed change violate `ARCH-001`?
|
|
104
|
+
|
|
105
|
+
Jev returns a Noul: the probability that the answer is yes. JevGuard owns the
|
|
106
|
+
policy that translates it into an outcome.
|
|
107
|
+
|
|
108
|
+
| Rule severity | PASS | WARN | FAIL |
|
|
109
|
+
| --- | ---: | ---: | ---: |
|
|
110
|
+
| `error` | `< 40%` | `40%–69%` | `≥ 70%` |
|
|
111
|
+
| `warning` | `< 60%` | `≥ 60%` | never |
|
|
112
|
+
|
|
113
|
+
Those thresholds are per repository rule and locally configurable in
|
|
114
|
+
`.jev/config.yaml`.
|
|
115
|
+
|
|
116
|
+
JevGuard also runs two product-owned built-ins on every attributed turn,
|
|
117
|
+
`SCOPE-CREEP` and `COMPLEXITY`. Both receive the turn's complete, safe attributed
|
|
118
|
+
patch with no scope filtering, and both are answered by a **single** Jev request
|
|
119
|
+
that carries two independent questions. Each answer is validated on its own, so a
|
|
120
|
+
malformed answer fails only its own check.
|
|
121
|
+
|
|
122
|
+
`SCOPE-CREEP` asks whether the change contains material functional, behavioral,
|
|
123
|
+
architectural, dependency, configuration, documentation, or refactoring work the task
|
|
124
|
+
did not request and that is not reasonably necessary to complete it. It uses fixed
|
|
125
|
+
`error` thresholds (`40%`/`70%`), independent of `.jev/config.yaml`.
|
|
126
|
+
|
|
127
|
+
`COMPLEXITY` asks whether the change introduces material complexity disproportionate
|
|
128
|
+
to, or not reasonably necessary for, completing the task, such as unnecessary
|
|
129
|
+
abstractions, layers or indirections without proportional gain, new dependencies
|
|
130
|
+
without a clear need, excessive configuration, premature generalization, or structure
|
|
131
|
+
materially larger than the problem requires. It is advisory: it warns at `50%` and
|
|
132
|
+
can never fail.
|
|
133
|
+
|
|
134
|
+
The rule lane and the built-in batch are launched together. One shared FIFO
|
|
135
|
+
concurrency limit caps the plugin instance at two Jev requests in flight, counting the
|
|
136
|
+
built-in batch as a single request. Results join the same aggregate in a fixed order:
|
|
137
|
+
rules in source order, then `SCOPE-CREEP`, then `COMPLEXITY`.
|
|
138
|
+
|
|
139
|
+
Reviews run in the background. The idle event returns as soon as the serialized
|
|
140
|
+
attribution step is scheduled; policy reads, Jev calls, and presentation never sit on
|
|
141
|
+
the agent's critical path.
|
|
142
|
+
|
|
143
|
+
## Install
|
|
144
|
+
|
|
145
|
+
Once `@pablozrrrr/jevguard` is published to npm, the intended install is one line in
|
|
146
|
+
`opencode.json`:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{ "plugin": ["@pablozrrrr/jevguard"] }
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
OpenCode then resolves the package from the npm registry or its cache and loads it
|
|
153
|
+
on the next start. Adding the entry only loads the plugin; it does **not** put the
|
|
154
|
+
`jevguard` CLI on `PATH` (see [Install the CLI](#install-the-cli)). Restart
|
|
155
|
+
OpenCode after changing the plugin list.
|
|
156
|
+
|
|
157
|
+
> [!IMPORTANT]
|
|
158
|
+
> `@pablozrrrr/jevguard` is **not published to npm yet**. The one-line entry above is
|
|
159
|
+
> future behavior and will not resolve until the package is released. Before
|
|
160
|
+
> publication, load the plugin as a local artifact plugin instead.
|
|
161
|
+
|
|
162
|
+
### Build the local artifact
|
|
163
|
+
|
|
164
|
+
The artifact ships the plugin as a **locally packed tarball** that bundles the
|
|
165
|
+
private `@jevguard/core` and `@jevguard/opencode-adapter` workspace code, so a
|
|
166
|
+
clean consumer installs one tarball and never resolves a workspace link or a
|
|
167
|
+
private registry package. It also packages the `jevguard-rules` skill and its
|
|
168
|
+
private rule validator under `skills/jevguard-rules/`.
|
|
169
|
+
|
|
170
|
+
Build the tarball from this repository:
|
|
171
|
+
|
|
172
|
+
```sh
|
|
173
|
+
corepack enable
|
|
174
|
+
pnpm install
|
|
175
|
+
pnpm artifact:build
|
|
176
|
+
pnpm artifact:pack
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
`pnpm artifact:pack` writes `artifacts/pablozrrrr-jevguard-<version>.tgz`. Both
|
|
180
|
+
`packages/plugin/dist/` and `artifacts/` are build output and are not committed.
|
|
181
|
+
|
|
182
|
+
The packed manifest depends only on public runtime packages
|
|
183
|
+
(`@inquirer/password`, `@napi-rs/keyring`, `@typesafe-ai/sdk`, `yaml`). Installing
|
|
184
|
+
the tarball therefore needs npm registry access for those packages; the artifact
|
|
185
|
+
does not vendor them and does not promise an offline install.
|
|
186
|
+
|
|
187
|
+
### Load the local plugin before publication
|
|
188
|
+
|
|
189
|
+
OpenCode `1.18.31` resolves a **bare** `opencode.json` `plugin` entry from the npm
|
|
190
|
+
registry or its cache, not from the consumer's `node_modules`. Until the package is
|
|
191
|
+
published, install the tarball into the project's `.opencode` directory and load it
|
|
192
|
+
through a local plugin shim:
|
|
193
|
+
|
|
194
|
+
```sh
|
|
195
|
+
cd /path/to/consumer/.opencode
|
|
196
|
+
bun add /path/to/pablozrrrr-jevguard-<version>.tgz
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
// .opencode/plugins/jevguard.ts
|
|
201
|
+
export { JevGuardPlugin } from "@pablozrrrr/jevguard";
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
OpenCode loads `.opencode/plugins/` with its bundled Bun runtime. The shim runs as
|
|
205
|
+
a local plugin module and resolves `@pablozrrrr/jevguard` from
|
|
206
|
+
`.opencode/node_modules`. Do **not** add `@pablozrrrr/jevguard` to the `opencode.json`
|
|
207
|
+
`plugin` list before publication; that bare entry does not resolve locally.
|
|
208
|
+
|
|
209
|
+
### Author rules with the bundled skill
|
|
210
|
+
|
|
211
|
+
The package ships a `jevguard-rules` OpenCode skill beside the plugin. On startup
|
|
212
|
+
the plugin's `config` hook appends the installed skill directory to the host's
|
|
213
|
+
`skills.paths`, so the skill is discovered without a manual `opencode.json` entry.
|
|
214
|
+
Skill discovery is read at OpenCode startup: restart OpenCode after installing or
|
|
215
|
+
updating the package so the skill appears.
|
|
216
|
+
|
|
217
|
+
Policy content is different. `.jev/rules.md` and `.jev/config.yaml` are read once
|
|
218
|
+
per attributed turn, so editing rule text takes effect on the next reviewed turn
|
|
219
|
+
without restarting OpenCode. The skill validates a candidate with the same parser
|
|
220
|
+
JevGuard uses, requires explicit final confirmation, and replaces `.jev/rules.md`
|
|
221
|
+
only after the candidate passes; it never edits `.jev/config.yaml` and never calls
|
|
222
|
+
Jev.
|
|
223
|
+
|
|
224
|
+
### Install the CLI
|
|
225
|
+
|
|
226
|
+
Loading the plugin does not expose the `jevguard` binary on `PATH`. Once the
|
|
227
|
+
package is published, run the login command without a global install:
|
|
228
|
+
|
|
229
|
+
```sh
|
|
230
|
+
bunx --package @pablozrrrr/jevguard jevguard login
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Or install the package globally so `jevguard` is on `PATH`:
|
|
234
|
+
|
|
235
|
+
```sh
|
|
236
|
+
bun install --global @pablozrrrr/jevguard
|
|
237
|
+
jevguard login
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Until the package is published, install the local tarball globally instead:
|
|
241
|
+
|
|
242
|
+
```sh
|
|
243
|
+
bun install --global /path/to/pablozrrrr-jevguard-<version>.tgz
|
|
244
|
+
jevguard login
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Known limitations:
|
|
248
|
+
|
|
249
|
+
- `@pablozrrrr/jevguard` has no registry release yet, so the one-line `opencode.json`
|
|
250
|
+
plugin entry does not resolve until the package is published.
|
|
251
|
+
- Target host is OpenCode `1.18.31`. Exact `1.18.31` runtime smoke is still
|
|
252
|
+
pending; a local `1.18.28` run worked.
|
|
253
|
+
- The plugin and CLI run on Bun, and the packed `jevguard` bin keeps a Bun
|
|
254
|
+
shebang. Install and run the artifact with the Bun runtime.
|
|
255
|
+
|
|
256
|
+
## Connect Jev
|
|
257
|
+
|
|
258
|
+
For local use, connect once with the installed command:
|
|
259
|
+
|
|
260
|
+
```sh
|
|
261
|
+
jevguard login
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Loading the plugin does not put `jevguard` on `PATH`. If it is not installed
|
|
265
|
+
globally, run the one-line login instead:
|
|
266
|
+
|
|
267
|
+
```sh
|
|
268
|
+
bunx --package @pablozrrrr/jevguard jevguard login
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
JevGuard stores the key in your operating system's credential store instead of a
|
|
272
|
+
repository file or shell history. In CI, provide `TYPESAFE_API_KEY` through the
|
|
273
|
+
platform secret manager. See the [security model](./docs/security.md) for details.
|
|
274
|
+
|
|
275
|
+
```text
|
|
276
|
+
JevGuard FAIL
|
|
277
|
+
pass 1 · warn 1 · fail 1 · skipped 0 · unavailable 0
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
One toast per turn shows the aggregate outcome and the outcome counts; the
|
|
281
|
+
structured log carries every rule's result, its raw violation probability or typed
|
|
282
|
+
reason, and its scoped paths. The counts include every entry, including the single
|
|
283
|
+
synthetic entry a review-level failure produces.
|
|
284
|
+
|
|
285
|
+
`PASS`, `WARN`, and `FAIL` are per-rule semantic outcomes. `SKIPPED` means that
|
|
286
|
+
rule had no applicable change to evaluate. `UNAVAILABLE` means JevGuard could not
|
|
287
|
+
safely or completely evaluate that rule.
|
|
288
|
+
|
|
289
|
+
## Implemented behavior
|
|
290
|
+
|
|
291
|
+
The current release implements the full local, observe-only path:
|
|
292
|
+
|
|
293
|
+
- OpenCode V1 plugin loads.
|
|
294
|
+
- A completed assistant response is detected.
|
|
295
|
+
- The direct parent user task and assistant-attributed diff are acquired.
|
|
296
|
+
- Every `## <RULE-ID>` block in `.jev/rules.md` is parsed in source order. Each
|
|
297
|
+
block is validated independently, so one invalid block does not suppress its
|
|
298
|
+
valid siblings, and every occurrence of a duplicated ID is invalid.
|
|
299
|
+
- Each valid rule is processed independently. It asks Jev at most once, and only
|
|
300
|
+
when the gate config is valid, the rule is applicable, and its scoped evidence is
|
|
301
|
+
complete and safe; it produces one typed violation probability or an operational
|
|
302
|
+
outcome.
|
|
303
|
+
- A failure before rule evaluation — no attributed diff, unreadable policy files, or
|
|
304
|
+
a missing `.jev/rules.md` — is reported by the rule lane as one synthetic
|
|
305
|
+
`UNAVAILABLE` entry with no rule ID, not one result per declared rule. When the
|
|
306
|
+
turn itself is attributed, the built-in batch still runs.
|
|
307
|
+
- The product-owned `SCOPE-CREEP` built-in runs on every attributed turn over the
|
|
308
|
+
turn's complete, safe attributed patch, with fixed `error` thresholds
|
|
309
|
+
(`0.65`/`0.90`) and no scope filtering. It can produce `PASS`, `WARN`, or `FAIL`.
|
|
310
|
+
- The product-owned `COMPLEXITY` built-in runs on every attributed turn over the same
|
|
311
|
+
complete, safe attributed patch. It uses a fixed advisory threshold of `0.50`,
|
|
312
|
+
independent of `.jev/config.yaml`, and can produce `PASS` or `WARN` but never
|
|
313
|
+
`FAIL`.
|
|
314
|
+
- Both built-ins are sent as one batch request with two independent named answers.
|
|
315
|
+
One malformed or missing answer fails only its own check; the valid sibling still
|
|
316
|
+
gates. A failed or malformed batch envelope makes both checks `UNAVAILABLE`.
|
|
317
|
+
- The built-in batch runs concurrently with the sequential rule lane. One shared FIFO
|
|
318
|
+
concurrency limit allows at most two Jev requests in flight across the plugin
|
|
319
|
+
instance, counting the batch as one request. With no attributed patch a built-in is
|
|
320
|
+
`SKIPPED`; blocked or oversized evidence is `UNAVAILABLE`; a rule, policy-load, or
|
|
321
|
+
config failure never suppresses the batch, and one built-in's answer never
|
|
322
|
+
suppresses the other.
|
|
323
|
+
- Reviews run in the background. The idle event resolves as soon as the serialized
|
|
324
|
+
attribution step is scheduled, so policy reads, Jev calls, and presentation do not
|
|
325
|
+
block the agent.
|
|
326
|
+
- The local gate maps each rule to `PASS`, `WARN`, or `FAIL`; a rule with no
|
|
327
|
+
applicable scope is `SKIPPED`, and a rule that cannot be safely evaluated is
|
|
328
|
+
`UNAVAILABLE`.
|
|
329
|
+
- One aggregate TUI toast and one structured log entry report the turn. The log
|
|
330
|
+
carries every entry's outcome, raw probability, or reason, including the built-in
|
|
331
|
+
results and the synthetic review-level entry when there is one. The fixed result
|
|
332
|
+
order is rules in source order, then `SCOPE-CREEP`, then `COMPLEXITY`.
|
|
333
|
+
|
|
334
|
+
No feedback is injected into the agent session. No remediation is attempted. No
|
|
335
|
+
task is blocked.
|
|
336
|
+
|
|
337
|
+
## Roadmap
|
|
338
|
+
|
|
339
|
+
The multi-rule, scope-creep, and complexity slices are implemented. Planned work
|
|
340
|
+
beyond them:
|
|
341
|
+
|
|
342
|
+
```text
|
|
343
|
+
V0.3 Remaining built-in semantic check: test adequacy
|
|
344
|
+
↓
|
|
345
|
+
V0.4 jev-init: evidence-based policy bootstrap
|
|
346
|
+
↓
|
|
347
|
+
V0.5 On-demand evidence and explanations
|
|
348
|
+
↓
|
|
349
|
+
V0.6 Opt-in, bounded auto-remediation
|
|
350
|
+
↓
|
|
351
|
+
V0.7 Observe / enforce / remediate modes
|
|
352
|
+
↓
|
|
353
|
+
V0.8 Rule packs
|
|
354
|
+
↓
|
|
355
|
+
V0.9 Local feedback and calibration
|
|
356
|
+
↓
|
|
357
|
+
V1 Claude Code and Codex adapters
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
CI and pull-request policy review come after V1, using the same versioned rules.
|
|
361
|
+
|
|
362
|
+
## Architecture
|
|
363
|
+
|
|
364
|
+
JevGuard is a pnpm TypeScript monorepo. The core has no dependency on OpenCode or
|
|
365
|
+
its runtime, which keeps the evaluation model portable to future adapters.
|
|
366
|
+
|
|
367
|
+
```text
|
|
368
|
+
packages/
|
|
369
|
+
├── core/ domain, policy, evaluation, gate
|
|
370
|
+
├── opencode-adapter/ OpenCode attribution and presentation
|
|
371
|
+
├── plugin/ OpenCode composition root and CLI
|
|
372
|
+
└── testkit/ fixtures and contract helpers
|
|
373
|
+
|
|
374
|
+
plugin → opencode-adapter → core
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
## Status
|
|
378
|
+
|
|
379
|
+
The multi-rule, multi-built-in, observe-only review is implemented. It loads in
|
|
380
|
+
OpenCode, attributes one completed turn, parses every rule block in `.jev/rules.md`,
|
|
381
|
+
asks Jev once per applicable rule and once per built-in batch, runs the `SCOPE-CREEP`
|
|
382
|
+
and `COMPLEXITY` built-ins over the complete attributed patch behind one shared
|
|
383
|
+
concurrency limit, applies the local gate to each, and presents one aggregate result
|
|
384
|
+
as a transient TUI toast and a structured log entry.
|
|
385
|
+
|
|
386
|
+
The local, private tarball (`pnpm artifact:build`, `pnpm artifact:pack`) packages
|
|
387
|
+
that slice so a clean consumer can install it without workspace links.
|
|
388
|
+
|
|
389
|
+
OpenCode sees only transient toasts and structured logs. JevGuard does not inject
|
|
390
|
+
anything into the agent context, does not add session messages, and does not block
|
|
391
|
+
a task. Real-host validation against exact OpenCode `1.18.31` is still pending.
|
|
392
|
+
|
|
393
|
+
## Development
|
|
394
|
+
|
|
395
|
+
Requirements: Node.js `>=22.13.0`, pnpm `10.33.2` (via Corepack), and the Bun
|
|
396
|
+
runtime for the CLI and OpenCode plugin loading.
|
|
397
|
+
|
|
398
|
+
```sh
|
|
399
|
+
corepack enable
|
|
400
|
+
pnpm install
|
|
401
|
+
pnpm typecheck
|
|
402
|
+
pnpm test
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
Use `pnpm check` to run format, lint, typecheck, and tests in sequence. See
|
|
406
|
+
[CONTRIBUTING.md](./CONTRIBUTING.md) for the full contribution workflow.
|
|
407
|
+
|
|
408
|
+
## Documentation
|
|
409
|
+
|
|
410
|
+
- [Configuration reference](./docs/configuration.md)
|
|
411
|
+
- [Security model](./docs/security.md)
|
|
412
|
+
- [Contributing](./CONTRIBUTING.md)
|
|
413
|
+
- [Agent instructions](./AGENTS.md)
|
|
414
|
+
|
|
415
|
+
## License
|
|
416
|
+
|
|
417
|
+
MIT — see [LICENSE](./LICENSE).
|