@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/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pablozrrrr/jevguard",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "OpenCode plugin that reviews a completed agent turn against a repository semantic rule using Jev.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./index.js"
|
|
10
|
+
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"jevguard": "cli/main.js"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"index.js",
|
|
16
|
+
"cli/main.js",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE",
|
|
19
|
+
"skills/jevguard-rules/SKILL.md",
|
|
20
|
+
"skills/jevguard-rules/validate-rules.js"
|
|
21
|
+
],
|
|
22
|
+
"engines": {
|
|
23
|
+
"bun": ">=1.1.0",
|
|
24
|
+
"opencode": ">=1.18.31 <2"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/pablozr/JevGuard.git",
|
|
29
|
+
"directory": "packages/plugin"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/pablozr/JevGuard#readme",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/pablozr/JevGuard/issues"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"opencode",
|
|
37
|
+
"opencode-plugin",
|
|
38
|
+
"jev",
|
|
39
|
+
"semantic",
|
|
40
|
+
"policy",
|
|
41
|
+
"typesafe"
|
|
42
|
+
],
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public",
|
|
45
|
+
"registry": "https://registry.npmjs.org"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@inquirer/password": "^5.2.2",
|
|
49
|
+
"@napi-rs/keyring": "2.1.0",
|
|
50
|
+
"@typesafe-ai/sdk": "0.6.0",
|
|
51
|
+
"yaml": "2.9.1"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: jevguard-rules
|
|
3
|
+
description: Use when the user wants to create, add, edit, remove, weaken, or repair a JevGuard policy rule in `.jev/rules.md`, or asks what JevGuard checks. Interviews only for missing rule facts, validates the full candidate with the bundled parser, and requires explicit final confirmation before replacing the file. Do not use for `.jev/config.yaml`, credentials, or running a review.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: opencode >=1.18.31 <2
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# JevGuard rules
|
|
9
|
+
|
|
10
|
+
Author and repair the repository policy that JevGuard reads from `.jev/rules.md`.
|
|
11
|
+
The user decides the policy; this skill interviews for the missing facts, drafts a
|
|
12
|
+
complete rule document, and validates it with the same parser JevGuard uses before
|
|
13
|
+
anything is written.
|
|
14
|
+
|
|
15
|
+
## Non-negotiables
|
|
16
|
+
|
|
17
|
+
- Never read, print, or copy a secret value or a secret file. Do not open `.env`,
|
|
18
|
+
credential, key, or token files as rule material.
|
|
19
|
+
- Never edit `.jev/config.yaml`. This skill only reads and writes `.jev/rules.md`.
|
|
20
|
+
- Never run the public `jevguard` CLI and never call Jev/TypeSafe inference. The only
|
|
21
|
+
tool you invoke is the bundled validator next to this `SKILL.md`.
|
|
22
|
+
- Preserve every valid existing rule block unless the user explicitly asks to replace,
|
|
23
|
+
remove, or weaken it. Refuse to silently drop a policy.
|
|
24
|
+
- Never write `.jev/rules.md` without a valid parser result and an explicit final
|
|
25
|
+
confirmation from the user.
|
|
26
|
+
|
|
27
|
+
## Workflow
|
|
28
|
+
|
|
29
|
+
### 1. Inspect the real policy
|
|
30
|
+
|
|
31
|
+
Read the actual `.jev/rules.md` in the repository. Then validate exactly that file with
|
|
32
|
+
the bundled helper from this skill's base directory:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
bun "<skill-base-dir>/validate-rules.js" .jev/rules.md
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
If Bun is unavailable, run the same file with `node`. The helper prints only a JSON
|
|
39
|
+
summary: `status`, rule counts, rule IDs, and parser error codes. It never prints rule
|
|
40
|
+
text or file contents. If the file does not exist, treat the policy as empty and say so.
|
|
41
|
+
|
|
42
|
+
Report the summary to the user: which IDs are valid, which blocks are invalid, and
|
|
43
|
+
which error codes apply.
|
|
44
|
+
|
|
45
|
+
### 2. Interview only for missing facts
|
|
46
|
+
|
|
47
|
+
Ask, one focused question at a time, only for the facts the user has not already given.
|
|
48
|
+
Do not re-ask what an existing valid block already states. The complete rule needs:
|
|
49
|
+
|
|
50
|
+
1. **Protected boundary** — what must stay true in the codebase.
|
|
51
|
+
2. **Concrete violation** — the specific change that breaches that boundary.
|
|
52
|
+
3. **Allowed exception** — what is explicitly permitted, or `none`.
|
|
53
|
+
4. **Severity** — `error` or `warning`.
|
|
54
|
+
5. **Scope** — an optional repo-relative POSIX glob such as `src/**`, or no scope.
|
|
55
|
+
6. **Rule ID** — matching `[A-Za-z0-9][A-Za-z0-9._-]*`, unique in the document.
|
|
56
|
+
|
|
57
|
+
### 3. Complete the candidate
|
|
58
|
+
|
|
59
|
+
Draft the full `.jev/rules.md`, keeping every existing valid block. New and changed
|
|
60
|
+
blocks follow the document grammar:
|
|
61
|
+
|
|
62
|
+
```md
|
|
63
|
+
## ARCH-001
|
|
64
|
+
|
|
65
|
+
severity: error
|
|
66
|
+
scope: src/**
|
|
67
|
+
|
|
68
|
+
### Rule
|
|
69
|
+
|
|
70
|
+
<non-empty normative policy>
|
|
71
|
+
|
|
72
|
+
### Violation
|
|
73
|
+
|
|
74
|
+
<non-empty breaching condition>
|
|
75
|
+
|
|
76
|
+
### Allowed
|
|
77
|
+
|
|
78
|
+
<non-empty exception, or omit the section>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Before writing, explicitly call out any change that weakens, removes, or repairs
|
|
82
|
+
policy: deleted rules, new exceptions, lowered severity, narrowed scope, or a changed
|
|
83
|
+
violation. State exactly what is lost. Never soften a rule without saying so.
|
|
84
|
+
|
|
85
|
+
### 4. Require exact final confirmation
|
|
86
|
+
|
|
87
|
+
Show the complete candidate document and the intended file path. Ask for explicit
|
|
88
|
+
confirmation of that exact content. A vague "ok" does not count; require confirmation
|
|
89
|
+
that names the final document. If the user changes any fact, go back to step 3.
|
|
90
|
+
|
|
91
|
+
### 5. Stage the candidate in a unique temp sibling
|
|
92
|
+
|
|
93
|
+
Create one sibling temp file for this execution and write the confirmed candidate to
|
|
94
|
+
it. The name must include a fresh random identifier generated now, so two runs can
|
|
95
|
+
never collide, for example:
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
.jev/rules.md.jevguard-<random-id>.tmp
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
where `<random-id>` is a random identifier you generate for this execution (for
|
|
102
|
+
example eight hex characters). Do not reuse a fixed temp filename.
|
|
103
|
+
|
|
104
|
+
Create the temp file exclusively: it must not already exist. If the path exists,
|
|
105
|
+
refuses to create, or is a symlink, do not open, follow, or overwrite it; pick a new
|
|
106
|
+
random identifier and try again, and never write through a symlink. Record the exact
|
|
107
|
+
absolute temp path as owned by this execution and treat every later validation and
|
|
108
|
+
deletion as applying only to that recorded path.
|
|
109
|
+
|
|
110
|
+
Validate the exact temp file with the bundled helper:
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
bun "<skill-base-dir>/validate-rules.js" .jev/rules.md.jevguard-<random-id>.tmp
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
If the helper reports `invalid` or `error`, report the safe error codes, remove only
|
|
117
|
+
your own recorded temp file, and leave `.jev/rules.md` untouched.
|
|
118
|
+
|
|
119
|
+
### 6. Hold a version-tied conditional primitive across compare and replace
|
|
120
|
+
|
|
121
|
+
Before replacing, obtain a primitive that atomically ties the observed target version
|
|
122
|
+
to the replacement. Use either:
|
|
123
|
+
|
|
124
|
+
- a compare-and-swap that replaces `.jev/rules.md` only while it still matches the
|
|
125
|
+
exact version observed in step 1; or
|
|
126
|
+
- an exclusive lock on the target that you hold from the byte-for-byte re-read below
|
|
127
|
+
through the replacement, so no other writer can interleave.
|
|
128
|
+
|
|
129
|
+
While that primitive is held, re-read `.jev/rules.md` and compare it byte-for-byte
|
|
130
|
+
with the exact version you observed in step 1. This comparison is the race control. If
|
|
131
|
+
the bytes differ, abort before replacement, remove only your own recorded temp file,
|
|
132
|
+
and restart from step 1; never overwrite the concurrent edit. Do not release the lock
|
|
133
|
+
or discard the compare-and-swap token between this comparison and the replacement.
|
|
134
|
+
|
|
135
|
+
### 7. Replace conditionally, or stop without writing
|
|
136
|
+
|
|
137
|
+
With the primitive from step 6 still held, replace `.jev/rules.md` through it, then
|
|
138
|
+
release the lock. Read the file back, validate it once more with the helper, and
|
|
139
|
+
delete only your own recorded temp file. This final re-read is verification of the
|
|
140
|
+
written result, not race control. If it does not match the confirmed candidate, stop
|
|
141
|
+
and report; do not claim success.
|
|
142
|
+
|
|
143
|
+
An ordinary atomic rename is not sufficient by itself: if it can overwrite the
|
|
144
|
+
destination without checking the observed version, it can still clobber a concurrent
|
|
145
|
+
edit. Only use a rename when it has no-replace or version-conditional semantics, or
|
|
146
|
+
when it runs while you hold the exclusive lock from compare through replace.
|
|
147
|
+
|
|
148
|
+
If the host tools cannot provide a conditional compare-and-swap or an exclusive lock
|
|
149
|
+
held from compare through replace, do not write `.jev/rules.md`. Never fall back to a
|
|
150
|
+
plain write after the byte-for-byte check. Stop, remove only your own recorded temp
|
|
151
|
+
file, tell the user the validated draft is ready, and ask for a supported conditional
|
|
152
|
+
write mechanism or a user-assisted replacement. Do not claim the policy was modified.
|
|
153
|
+
|
|
154
|
+
## Reporting
|
|
155
|
+
|
|
156
|
+
Report the file path, the final rule IDs and severities, the helper's safe summary, and
|
|
157
|
+
any weakening or removal the user approved. Never echo secret values, credentials, or
|
|
158
|
+
the contents of non-policy files.
|