@pablozrrrr/jevguard 0.1.0 → 0.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 +129 -43
- package/cli/main.js +345 -25
- package/index.js +524 -60
- package/package.json +5 -3
- package/skills/jev-init/SKILL.md +252 -0
- package/skills/jev-init/validate-init.js +1526 -0
- package/skills/jevguard-rules/SKILL.md +17 -1
- package/skills/jevguard-rules/validate-rules.js +254 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pablozrrrr/jevguard",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "OpenCode plugin that reviews a completed agent turn against a repository semantic rule using Jev.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -17,11 +17,13 @@
|
|
|
17
17
|
"README.md",
|
|
18
18
|
"LICENSE",
|
|
19
19
|
"skills/jevguard-rules/SKILL.md",
|
|
20
|
-
"skills/jevguard-rules/validate-rules.js"
|
|
20
|
+
"skills/jevguard-rules/validate-rules.js",
|
|
21
|
+
"skills/jev-init/SKILL.md",
|
|
22
|
+
"skills/jev-init/validate-init.js"
|
|
21
23
|
],
|
|
22
24
|
"engines": {
|
|
23
25
|
"bun": ">=1.1.0",
|
|
24
|
-
"opencode": ">=1.18.
|
|
26
|
+
"opencode": ">=1.18.32 <2"
|
|
25
27
|
},
|
|
26
28
|
"repository": {
|
|
27
29
|
"type": "git",
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: jev-init
|
|
3
|
+
description: Use when a repository has no JevGuard policy yet and the user wants to bootstrap `.jev/rules.md` and `.jev/config.yaml` from explicit constraints and strong local evidence. Bounded, read-only inventory; stops if either file already exists; previews both files and requires explicit confirmation before writing. Do not use to edit an existing policy, for credentials, or to run a review.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: opencode >=1.18.32 <2
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# JevGuard init
|
|
9
|
+
|
|
10
|
+
Bootstrap the first repository policy that JevGuard reads from `.jev/rules.md` and
|
|
11
|
+
`.jev/config.yaml`. The user states the constraints they want enforced; this skill
|
|
12
|
+
reads a **bounded** inventory of the repository to ground those constraints and to
|
|
13
|
+
infer only strongly evidenced local conventions, drafts both files with explicit
|
|
14
|
+
provenance, validates the exact candidates with the same parser JevGuard uses, and
|
|
15
|
+
writes nothing until the user confirms both files by name.
|
|
16
|
+
|
|
17
|
+
Initialization runs exactly once per repository. After it writes a policy, all later
|
|
18
|
+
rule authoring belongs to the `jevguard-rules` skill.
|
|
19
|
+
|
|
20
|
+
## Non-negotiables
|
|
21
|
+
|
|
22
|
+
- **Never overwrite an existing policy.** Check `.jev/rules.md` and `.jev/config.yaml`
|
|
23
|
+
first. If either exists, stop, change nothing, and direct the user to the
|
|
24
|
+
`jevguard-rules` skill for any rule change. This skill only creates a policy where
|
|
25
|
+
none exists.
|
|
26
|
+
- **Never read, print, or copy a secret value, secret file, or secret store.** Do not
|
|
27
|
+
read environment variables, `.env` or `.env.*` files, credential, key, token, or
|
|
28
|
+
keychain/credential-store files, or `.git/config`. Do not run a command that would
|
|
29
|
+
expose them.
|
|
30
|
+
- **Never run the public `jevguard` CLI and never call Jev/TypeSafe inference.** This
|
|
31
|
+
skill makes no Jev call. The only program it invokes is the bundled validator next to
|
|
32
|
+
this `SKILL.md`.
|
|
33
|
+
- **Never invent architecture.** Record a rule as `inferred` only when local evidence
|
|
34
|
+
strongly corroborates it. When evidence is weak or speculative, omit the rule
|
|
35
|
+
instead of guessing.
|
|
36
|
+
- **Never persist conversation text.** A `user` provenance entry records only
|
|
37
|
+
`source: user` and, when useful, repository-relative evidence paths. It never
|
|
38
|
+
contains the user's words, the prompt, or any chat content.
|
|
39
|
+
- **Never overwrite an existing policy file.** Create `.jev/rules.md` and
|
|
40
|
+
`.jev/config.yaml` only with an exclusive-create primitive (`wx`/`O_EXCL`) that
|
|
41
|
+
refuses an existing path, and roll back only the file(s) this run created if either
|
|
42
|
+
target cannot be created. If the host cannot provide that primitive, write neither
|
|
43
|
+
file and present the validated drafts instead.
|
|
44
|
+
- **Never write either file before an explicit, both-files-by-name confirmation** and a
|
|
45
|
+
valid validator result on the exact staged candidates.
|
|
46
|
+
|
|
47
|
+
## Workflow
|
|
48
|
+
|
|
49
|
+
### 1. Confirm this is greenfield
|
|
50
|
+
|
|
51
|
+
Read whether `.jev/rules.md` and `.jev/config.yaml` exist. If either exists, stop
|
|
52
|
+
immediately: report which file is present, state that initialization is complete or
|
|
53
|
+
has already started, and tell the user to use the `jevguard-rules` skill to author,
|
|
54
|
+
add, edit, or repair rules. Do not read, draft, stage, or write anything in that case.
|
|
55
|
+
|
|
56
|
+
### 2. Elicit the user's constraints
|
|
57
|
+
|
|
58
|
+
If the invocation does not already state the constraints the user wants enforced, ask
|
|
59
|
+
exactly one focused question: what policies should JevGuard enforce in this
|
|
60
|
+
repository? An explicit `none` is a valid answer: then there are no acceptable rules,
|
|
61
|
+
and step 9 writes nothing.
|
|
62
|
+
|
|
63
|
+
Record every constraint the user gives as an explicit, `user`-sourced rule. Keep the
|
|
64
|
+
user's stated intent; do not translate it into a broader rule than they asked for. Ask
|
|
65
|
+
only for facts that are genuinely missing, one question at a time.
|
|
66
|
+
|
|
67
|
+
### 3. Read a bounded inventory
|
|
68
|
+
|
|
69
|
+
Read only enough to ground the user's constraints and to corroborate concrete local
|
|
70
|
+
conventions. The inventory is bounded to:
|
|
71
|
+
|
|
72
|
+
- agent and contributor instructions such as `AGENTS.md` and `CONTRIBUTING.md`;
|
|
73
|
+
- the README and files under `docs/`;
|
|
74
|
+
- the project structure (directory and file names);
|
|
75
|
+
- language, build, test, format, and lint configuration (for example `package.json`,
|
|
76
|
+
`tsconfig.json`, a formatter or linter config);
|
|
77
|
+
- representative source files **only** when they corroborate one concrete candidate
|
|
78
|
+
rule that the user asked for or that strong instructions already support.
|
|
79
|
+
|
|
80
|
+
Stop as soon as the constraints are grounded. Do not read the whole repository, do not
|
|
81
|
+
read generated or vendor directories, and do not read any path excluded above. When a
|
|
82
|
+
file could contain a secret, do not open it.
|
|
83
|
+
|
|
84
|
+
### 4. Derive rules and provenance
|
|
85
|
+
|
|
86
|
+
Every rule you keep gets exactly one provenance entry. A rule is kept only when it
|
|
87
|
+
passes one of these bars:
|
|
88
|
+
|
|
89
|
+
- **`source: user`** — the user stated the constraint. This is the only source that may
|
|
90
|
+
use `severity: error`; still prefer `warning` unless the user asked for `error`.
|
|
91
|
+
- **`source: inferred`** — a strongly evidenced local convention. Record it only with
|
|
92
|
+
**strong corroboration**: a normative document or instruction (an `AGENTS.md`,
|
|
93
|
+
`CONTRIBUTING.md`, or a policy doc) **plus** independent evidence from source code,
|
|
94
|
+
configuration, or project structure that agrees. An inferred rule must be
|
|
95
|
+
`severity: warning` and cite **at least two** safe evidence paths. The bundled
|
|
96
|
+
validator mechanically enforces the `warning` severity and the two-path minimum, but
|
|
97
|
+
it cannot prove that the corroboration is genuinely normative or independent; that
|
|
98
|
+
semantic bar stays yours.
|
|
99
|
+
|
|
100
|
+
A single README sentence, an isolated code sample, personal preference, or an
|
|
101
|
+
aspiration the repository does not already follow is **not** strong evidence. Exclude
|
|
102
|
+
speculative rules and say which candidates you dropped and why.
|
|
103
|
+
|
|
104
|
+
Each rule block keeps the document grammar; `severity` and `scope` remain the only
|
|
105
|
+
accepted metadata. Provenance is **never** written inside a rule block.
|
|
106
|
+
|
|
107
|
+
### 5. Write the provenance preamble before the rules
|
|
108
|
+
|
|
109
|
+
Provenance lives in one fenced YAML manifest at the very top of `.jev/rules.md`,
|
|
110
|
+
before the first `##` rule heading. The rules parser ignores everything before the
|
|
111
|
+
first rule heading, so the manifest never becomes policy.
|
|
112
|
+
|
|
113
|
+
````md
|
|
114
|
+
```yaml
|
|
115
|
+
rules:
|
|
116
|
+
ARCH-001:
|
|
117
|
+
source: user
|
|
118
|
+
LANG-002:
|
|
119
|
+
source: inferred
|
|
120
|
+
evidence:
|
|
121
|
+
- AGENTS.md
|
|
122
|
+
- package.json
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## ARCH-001
|
|
126
|
+
|
|
127
|
+
severity: error
|
|
128
|
+
|
|
129
|
+
### Rule
|
|
130
|
+
|
|
131
|
+
...
|
|
132
|
+
````
|
|
133
|
+
|
|
134
|
+
The manifest shape is exact:
|
|
135
|
+
|
|
136
|
+
- the top level is one `rules` mapping and nothing else;
|
|
137
|
+
- each key is a rule ID that also appears as a valid `##` rule heading;
|
|
138
|
+
- every valid rule has exactly one entry and every entry maps to a valid rule;
|
|
139
|
+
- `source` is exactly `user` or `inferred`;
|
|
140
|
+
- `evidence` is optional for `user` and **required with at least two safe paths for
|
|
141
|
+
`inferred`**; the validator rejects an `inferred` entry with fewer than two safe
|
|
142
|
+
paths, an inferred rule that did not parse as `warning`, and any `.git`, absolute,
|
|
143
|
+
traversal, or denied-secret path;
|
|
144
|
+
- each evidence path is a repository-relative POSIX path (no leading `/`, no `\`, no
|
|
145
|
+
`..`, no drive letter, no URL) and is never a secret path.
|
|
146
|
+
|
|
147
|
+
If a candidate rule is dropped, it appears in neither the rules nor the manifest.
|
|
148
|
+
|
|
149
|
+
### 6. Generate the default configuration
|
|
150
|
+
|
|
151
|
+
Write the canonical V0.1 defaults to `.jev/config.yaml`, thresholds first and then the
|
|
152
|
+
remediation section, exactly:
|
|
153
|
+
|
|
154
|
+
```yaml
|
|
155
|
+
version: 1
|
|
156
|
+
|
|
157
|
+
thresholds:
|
|
158
|
+
error:
|
|
159
|
+
warn: 0.40
|
|
160
|
+
fail: 0.70
|
|
161
|
+
warning:
|
|
162
|
+
warn: 0.60
|
|
163
|
+
|
|
164
|
+
remediation:
|
|
165
|
+
auto_propose: true
|
|
166
|
+
propose_on:
|
|
167
|
+
- FAIL
|
|
168
|
+
model: opencode/gpt-5.6-luna
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Do not invent thresholds, add keys, or change the model. The default configuration is
|
|
172
|
+
valid and uses the documented defaults.
|
|
173
|
+
|
|
174
|
+
### 7. Preview both files and require explicit confirmation
|
|
175
|
+
|
|
176
|
+
Show the user the complete candidate `.jev/rules.md` — including the provenance
|
|
177
|
+
preamble — and the complete candidate `.jev/config.yaml`, each with its intended exact
|
|
178
|
+
path. For every rule, state its `source` and, when inferring, the evidence that
|
|
179
|
+
corroborates it. List any candidate you dropped.
|
|
180
|
+
|
|
181
|
+
Ask for explicit confirmation that names **both** exact files, for example
|
|
182
|
+
`.jev/rules.md` and `.jev/config.yaml`. A vague `ok` does not count. If the user
|
|
183
|
+
changes any constraint, source, or rule, return to step 4 and draft again.
|
|
184
|
+
|
|
185
|
+
### 8. Stage the confirmed candidates exclusively, then validate
|
|
186
|
+
|
|
187
|
+
Only after that confirmation, create the two staging files in `.jev/` with a fresh
|
|
188
|
+
random identifier generated now, for example
|
|
189
|
+
`.jev/rules.md.jev-init-<random-id>.tmp` and
|
|
190
|
+
`.jev/config.yaml.jev-init-<random-id>.tmp`. The host's ordinary file tool cannot
|
|
191
|
+
guarantee exclusive create, so stage through a tiny temporary script that:
|
|
192
|
+
|
|
193
|
+
- creates `.jev` if it does not exist;
|
|
194
|
+
- opens each staging path with an exclusive-create flag (`wx`, or `O_CREAT | O_EXCL`)
|
|
195
|
+
so an existing file or symlink makes the open fail instead of being followed or
|
|
196
|
+
overwritten;
|
|
197
|
+
- writes the exact confirmed candidate bytes;
|
|
198
|
+
- exits non-zero without touching any other path if either open fails.
|
|
199
|
+
|
|
200
|
+
Do not pass a fixed or reused name. Record the two absolute staging paths as owned by
|
|
201
|
+
this execution; all later validation and deletion apply only to those paths. If you
|
|
202
|
+
cannot run a script with an exclusive-create primitive, stop before writing anything
|
|
203
|
+
and present the drafts to the user instead.
|
|
204
|
+
|
|
205
|
+
Validate exactly those staged candidates with the bundled helper from this skill's
|
|
206
|
+
base directory:
|
|
207
|
+
|
|
208
|
+
```sh
|
|
209
|
+
bun "<skill-base-dir>/validate-init.js" ".jev/rules.md.jev-init-<random-id>.tmp" ".jev/config.yaml.jev-init-<random-id>.tmp"
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The helper prints only JSON: `status`, the valid rule IDs, and deterministic codes. It
|
|
213
|
+
never prints rule text, config values, evidence contents, file contents, or
|
|
214
|
+
credentials. If it reports `invalid` or `error`, report the safe codes, remove only
|
|
215
|
+
your own recorded staging files, and leave the repository policy untouched.
|
|
216
|
+
|
|
217
|
+
### 9. Commit both files exclusively, or write nothing
|
|
218
|
+
|
|
219
|
+
Commit only when the exact staged candidates validated as `valid` and there is at least
|
|
220
|
+
one acceptable rule. Immediately before committing, re-check that neither
|
|
221
|
+
`.jev/rules.md` nor `.jev/config.yaml` exists. Then run a tiny temporary script that:
|
|
222
|
+
|
|
223
|
+
- creates `.jev` if it does not exist;
|
|
224
|
+
- opens each target with an exclusive-create flag (`wx`, or `O_CREAT | O_EXCL`), so a
|
|
225
|
+
path that appeared since the re-check makes the open fail rather than being
|
|
226
|
+
overwritten or followed through a symlink;
|
|
227
|
+
- writes the exact validated staged bytes;
|
|
228
|
+
- if either open or write fails, closes what it opened, deletes only the target file(s)
|
|
229
|
+
this run created, and exits non-zero — it never overwrites, truncates, or deletes a
|
|
230
|
+
preexisting file;
|
|
231
|
+
- removes only its own staging files and the temporary script.
|
|
232
|
+
|
|
233
|
+
The script reads only its own staged files; it must not open any other repository file,
|
|
234
|
+
environment variable, or secret. If the host cannot run a script with an
|
|
235
|
+
exclusive-create primitive, write neither target, remove only your own staging files,
|
|
236
|
+
present the validated drafts, and do not claim success.
|
|
237
|
+
|
|
238
|
+
If there are no acceptable rules, write nothing: create neither target, remove only
|
|
239
|
+
your own staging files, and report that no policy was bootstrapped. Never write a
|
|
240
|
+
speculative rule, and never write a configuration without the rules it belongs to.
|
|
241
|
+
|
|
242
|
+
After committing, read both files back and validate them once more with the helper. If
|
|
243
|
+
the result is not `valid`, stop and report rather than claiming success.
|
|
244
|
+
|
|
245
|
+
## Reporting
|
|
246
|
+
|
|
247
|
+
Report both written paths, every final rule ID with its `source` and severity, the
|
|
248
|
+
helper's safe codes, and any candidate rule you excluded as speculative or
|
|
249
|
+
weakly evidenced. Never echo secret values, credentials, environment values, or the
|
|
250
|
+
contents of non-policy files. Never claim a policy was written when the validator did
|
|
251
|
+
not return `valid`, the exclusive commit did not succeed, or the user did not confirm
|
|
252
|
+
both files by name.
|