pi-warden 0.26.0 → 0.28.4
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/CHANGELOG.md +70 -0
- package/README.md +56 -176
- package/dist/config.d.ts +18 -0
- package/dist/config.js +48 -0
- package/dist/extension.d.ts +1 -1
- package/dist/extension.js +148 -41
- package/dist/extension.js.bak +148 -41
- package/dist/guard.d.ts +5 -0
- package/dist/guard.js +5 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.js +4 -3
- package/dist/learning.d.ts +51 -5
- package/dist/learning.js +219 -29
- package/dist/output.d.ts +31 -1
- package/dist/output.js +80 -1
- package/dist/panel.d.ts +29 -0
- package/dist/panel.js +257 -10
- package/dist/saver.d.ts +2 -0
- package/dist/saver.js +4 -0
- package/dist/shape.js +2 -1
- package/dist/trace.d.ts +2 -0
- package/dist/widget.d.ts +96 -0
- package/dist/widget.js +259 -1
- package/package.json +1 -1
package/dist/widget.js
CHANGED
|
@@ -15,6 +15,7 @@ const carriesFlag = (body) => body.some(segment => FINDING.test(segment) || FLAG
|
|
|
15
15
|
/** How far a verdict is from the editor; a worse verdict sits closer to where the eye already is. */
|
|
16
16
|
const SEVERITY = { warning: 1, error: 2 };
|
|
17
17
|
export const DEFAULT_TEMPLATES = {
|
|
18
|
+
// --- Data style (current): pipe-separated tokens, label · value pairs ---
|
|
18
19
|
action: "warden · {tool} · irreversible {irreversible} · off-task {offTask} · {scope} · slop: {slop} · patterns: {patterns} · {flags} · {level}",
|
|
19
20
|
stuck: "warden · stuck · {failures} failures · same strategy {sameStrategy} · change {approachChange} · progress {progress} · {flags} · {status}",
|
|
20
21
|
done: "warden · done-check · {changes} changes · {checksPassed}/{checks} checks passed · claims done {claimsDone} · claims verified {claimsVerified} · checks apply {checksApply} · {outcome} · {status}",
|
|
@@ -25,8 +26,265 @@ export const DEFAULT_TEMPLATES = {
|
|
|
25
26
|
rules: "warden · rules · {tool} {path} · {asked} rules · {violations} · {status}",
|
|
26
27
|
subagent: "warden · subagent · {agent} · {kind} · {wake} · {status}",
|
|
27
28
|
};
|
|
29
|
+
/** Sentence-style templates: natural language, no " · " separators between semantic groups. */
|
|
30
|
+
export const SENTENCE_TEMPLATES = {
|
|
31
|
+
// --- Action: 24 variants covering level × context combinations ---
|
|
32
|
+
action: {
|
|
33
|
+
// ALLOW variants
|
|
34
|
+
allow_default: "warden allowed {tool} action — {scope}",
|
|
35
|
+
allow_safe: "warden allowed {tool} action — low risk",
|
|
36
|
+
allow_read_only: "warden allowed {tool} action — read-only operation",
|
|
37
|
+
allow_with_context: "warden allowed {tool} action — {scope}, irreversibility {irreversible}",
|
|
38
|
+
allow_off_task: "warden allowed {tool} action — off-task but below threshold ({offTask})",
|
|
39
|
+
allow_intent_mismatch: "warden allowed {tool} action — plan mismatch ({intent}) but not blocking",
|
|
40
|
+
allow_slop: "warden allowed {tool} action — slop detected ({slop})",
|
|
41
|
+
allow_patterns: "warden allowed {tool} action — patterns matched ({patterns})",
|
|
42
|
+
allow_approved: "warden allowed {tool} action — approved by user",
|
|
43
|
+
allow_typesafe_error: "warden allowed {tool} action — TypeSafe unavailable, pattern checks only",
|
|
44
|
+
// WARN variants
|
|
45
|
+
warn_off_task: "warden warned about {tool} action — off-task risk ({offTask})",
|
|
46
|
+
warn_irreversible: "warden warned about {tool} action — high irreversibility ({irreversible})",
|
|
47
|
+
warn_intent: "warden warned about {tool} action — differs from stated plan",
|
|
48
|
+
warn_slop: "warden warned about {tool} action — code slop detected ({slop})",
|
|
49
|
+
warn_patterns: "warden warned about {tool} action — security patterns matched ({patterns})",
|
|
50
|
+
warn_visible: "warden warned about {tool} action — visible outside working tree",
|
|
51
|
+
// HOLD variants
|
|
52
|
+
hold_irreversible: "warden held {tool} action — irreversibility {irreversible} exceeds threshold",
|
|
53
|
+
hold_dangerous: "warden held {tool} action — destructive pattern detected ({patterns})",
|
|
54
|
+
hold_deny: "warden blocked {tool} action — deny rule matched ({patterns})",
|
|
55
|
+
// Fallback
|
|
56
|
+
default: "warden {level}ed {tool} action",
|
|
57
|
+
},
|
|
58
|
+
// --- Stuck: 8 variants ---
|
|
59
|
+
stuck: {
|
|
60
|
+
stuck_repeat: "warden detected stuck loop — {failures} failures, same strategy ({sameStrategy})",
|
|
61
|
+
stuck_churn: "warden detected stuck loop — {failures} failures, churning approaches",
|
|
62
|
+
stuck_no_progress: "warden detected stuck loop — {failures} failures, no progress ({progress})",
|
|
63
|
+
stuck_repeat_successful: "warden detected repeated success — {failures} identical results, consider if the task is done",
|
|
64
|
+
stuck_typesafe_error: "warden stuck check unavailable — TypeSafe error",
|
|
65
|
+
stuck_recovering: "warden detected stuck loop — {failures} failures, now recovering",
|
|
66
|
+
ok: "warden checked stuck — no loop detected ({failures} failures, approach change {approachChange})",
|
|
67
|
+
default: "warden {status} — {failures} failures",
|
|
68
|
+
},
|
|
69
|
+
// --- Done: 10 variants ---
|
|
70
|
+
done: {
|
|
71
|
+
unverified: "warden flagged done claim — {checksPassed}/{checks} checks passed, {changes} changes, not verified",
|
|
72
|
+
false_claim: "warden flagged false done claim — {checksPassed}/{checks} checks failed",
|
|
73
|
+
ok: "warden confirmed done — {checksPassed}/{checks} checks passed, {changes} changes",
|
|
74
|
+
ok_all_passed: "warden confirmed done — all {checks} checks passed",
|
|
75
|
+
partial: "warden flagged done — {checksPassed}/{checks} checks passed, needs attention",
|
|
76
|
+
no_checks: "warden flagged done claim — no verification checks run",
|
|
77
|
+
typesafe_error: "warden done check unavailable — TypeSafe error",
|
|
78
|
+
unverified_nudged: "warden flagged done claim — agent asked to verify ({checksPassed}/{checks} passed)",
|
|
79
|
+
false_claim_nudged: "warden flagged false claim — agent asked to recheck",
|
|
80
|
+
default: "warden done check — {outcome}",
|
|
81
|
+
},
|
|
82
|
+
// --- Prose: 8 variants ---
|
|
83
|
+
prose: {
|
|
84
|
+
nudged: "warden nudged prose — {status} in recent replies",
|
|
85
|
+
wordy: "warden flagged prose — wordy ({wordy})",
|
|
86
|
+
cliches: "warden flagged prose — clichés detected ({cliches})",
|
|
87
|
+
jargon: "warden flagged prose — jargon detected ({jargon})",
|
|
88
|
+
multiple: "warden flagged prose — {status}",
|
|
89
|
+
ok: "warden checked prose — all clear",
|
|
90
|
+
typesafe_error: "warden prose check unavailable — TypeSafe error",
|
|
91
|
+
default: "warden prose — {status}",
|
|
92
|
+
},
|
|
93
|
+
// --- Security: 6 variants ---
|
|
94
|
+
security: {
|
|
95
|
+
injection: "warden flagged security — injection risk in {tool} output",
|
|
96
|
+
exfiltration: "warden flagged security — possible credentials in {tool} output",
|
|
97
|
+
both: "warden flagged security — injection and exfiltration risk in {tool} output",
|
|
98
|
+
suspicious: "warden flagged security — suspicious content in {tool} output",
|
|
99
|
+
ok: "warden checked {tool} output — no security issues",
|
|
100
|
+
default: "warden security — {tool}",
|
|
101
|
+
},
|
|
102
|
+
// --- Context: 5 variants ---
|
|
103
|
+
context: {
|
|
104
|
+
compressed: "warden compressed {tool} output — kept {retention}, saved {bytesSaved} bytes",
|
|
105
|
+
recalled: "warden recalled full {tool} output — agent needed the original",
|
|
106
|
+
kept: "warden kept {tool} output — {retention}",
|
|
107
|
+
large: "warden compressed {tool} output — {bytesSaved} bytes saved",
|
|
108
|
+
default: "warden context — {tool}, {retention}",
|
|
109
|
+
},
|
|
110
|
+
// --- Runaway: 4 variants ---
|
|
111
|
+
runaway: {
|
|
112
|
+
stopped: "warden stopped runaway {kind} — repeated {count}× ({chars} chars)",
|
|
113
|
+
stopped_recovering: "warden stopped runaway {kind} — repeated {count}×, agent recovering",
|
|
114
|
+
detected: "warden detected runaway {kind} — {count}× repetition",
|
|
115
|
+
default: "warden runaway — {kind}",
|
|
116
|
+
},
|
|
117
|
+
// --- Rules: 6 variants ---
|
|
118
|
+
rules: {
|
|
119
|
+
violations: "warden flagged rules — {violations} in {tool} {path}",
|
|
120
|
+
violation_single: "warden flagged rule — {violations}",
|
|
121
|
+
none: "warden checked rules — no violations in {tool} {path}",
|
|
122
|
+
skipped: "warden rules — skipped ({reasons})",
|
|
123
|
+
typesafe_error: "warden rules check unavailable — TypeSafe error",
|
|
124
|
+
default: "warden rules — {tool}",
|
|
125
|
+
},
|
|
126
|
+
// --- Subagent: 4 variants ---
|
|
127
|
+
subagent: {
|
|
128
|
+
wake: "warden woke for subagent report — {agent}, {kind}",
|
|
129
|
+
silent: "warden ignored subagent report — {agent}, {kind}",
|
|
130
|
+
appended: "warden appended subagent report — {agent}",
|
|
131
|
+
default: "warden subagent — {agent}",
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
/** Pick the best sentence template for a verdict. Falls back to the data-style template. */
|
|
135
|
+
export function pickSentenceTemplate(guard, tokens) {
|
|
136
|
+
const variants = SENTENCE_TEMPLATES[guard];
|
|
137
|
+
if (!variants)
|
|
138
|
+
return DEFAULT_TEMPLATES[guard] ?? "";
|
|
139
|
+
const level = tokens.level ?? tokens.status ?? "";
|
|
140
|
+
const tool = tokens.tool ?? "";
|
|
141
|
+
const has = (key) => tokens[key] && tokens[key] !== "none" && tokens[key] !== "0.00";
|
|
142
|
+
// Guard-specific selection logic
|
|
143
|
+
if (guard === "action") {
|
|
144
|
+
if (tokens.flags?.includes("user approved"))
|
|
145
|
+
return variants.allow_approved;
|
|
146
|
+
if (tokens.flags?.includes("typesafe error"))
|
|
147
|
+
return variants.allow_typesafe_error;
|
|
148
|
+
if (level === "allow" || level === "ok") {
|
|
149
|
+
if (has("patterns"))
|
|
150
|
+
return variants.allow_patterns;
|
|
151
|
+
if (tokens.slop && tokens.slop !== "none")
|
|
152
|
+
return variants.allow_slop;
|
|
153
|
+
if (tokens.flags?.includes("off task"))
|
|
154
|
+
return variants.allow_off_task;
|
|
155
|
+
if (tokens.flags?.includes("off plan"))
|
|
156
|
+
return variants.allow_intent_mismatch;
|
|
157
|
+
if (tokens.flags?.includes("read-only"))
|
|
158
|
+
return variants.allow_read_only;
|
|
159
|
+
if (tokens.irreversible && Number(tokens.irreversible) < 0.3)
|
|
160
|
+
return variants.allow_safe;
|
|
161
|
+
if (tokens.scope)
|
|
162
|
+
return variants.allow_with_context;
|
|
163
|
+
return variants.allow_default;
|
|
164
|
+
}
|
|
165
|
+
if (level === "warn") {
|
|
166
|
+
if (has("slop") && tokens.slop !== "none")
|
|
167
|
+
return variants.warn_slop;
|
|
168
|
+
if (has("patterns"))
|
|
169
|
+
return variants.warn_patterns;
|
|
170
|
+
if (tokens.intent && Number(tokens.intent) > 0.5)
|
|
171
|
+
return variants.warn_intent;
|
|
172
|
+
if (tokens.visible && Number(tokens.visible) > 0.5)
|
|
173
|
+
return variants.warn_visible;
|
|
174
|
+
if (tokens.offTask && Number(tokens.offTask) > 0.5)
|
|
175
|
+
return variants.warn_off_task;
|
|
176
|
+
if (tokens.irreversible && Number(tokens.irreversible) > 0.5)
|
|
177
|
+
return variants.warn_irreversible;
|
|
178
|
+
return variants.warn_irreversible;
|
|
179
|
+
}
|
|
180
|
+
if (level === "confirm" || level === "deny") {
|
|
181
|
+
if (level === "deny")
|
|
182
|
+
return variants.hold_deny;
|
|
183
|
+
if (has("patterns"))
|
|
184
|
+
return variants.hold_dangerous;
|
|
185
|
+
return variants.hold_irreversible;
|
|
186
|
+
}
|
|
187
|
+
return variants.default;
|
|
188
|
+
}
|
|
189
|
+
if (guard === "stuck") {
|
|
190
|
+
if (level === "stuck" || level === "error") {
|
|
191
|
+
if (tokens.flags?.includes("successful repeat"))
|
|
192
|
+
return variants.stuck_repeat_successful;
|
|
193
|
+
if (tokens.flags?.includes("churn"))
|
|
194
|
+
return variants.stuck_churn;
|
|
195
|
+
if (tokens.flags?.includes("typesafe error"))
|
|
196
|
+
return variants.stuck_typesafe_error;
|
|
197
|
+
if (tokens.flags?.includes("exact repeat"))
|
|
198
|
+
return variants.stuck_repeat;
|
|
199
|
+
if (tokens.progress && Number(tokens.progress) < 0.2)
|
|
200
|
+
return variants.stuck_no_progress;
|
|
201
|
+
return variants.stuck_repeat;
|
|
202
|
+
}
|
|
203
|
+
if (level === "ok")
|
|
204
|
+
return variants.ok;
|
|
205
|
+
return variants.default;
|
|
206
|
+
}
|
|
207
|
+
if (guard === "done") {
|
|
208
|
+
if (level === "false claim")
|
|
209
|
+
return variants.false_claim;
|
|
210
|
+
if (level === "unverified") {
|
|
211
|
+
if (tokens.flags?.includes("typesafe error"))
|
|
212
|
+
return variants.typesafe_error;
|
|
213
|
+
if (tokens.flags?.includes("nudged"))
|
|
214
|
+
return variants.unverified_nudged;
|
|
215
|
+
return variants.unverified;
|
|
216
|
+
}
|
|
217
|
+
if (level === "ok") {
|
|
218
|
+
if (tokens.checks && tokens.checksPassed && tokens.checks === tokens.checksPassed)
|
|
219
|
+
return variants.ok_all_passed;
|
|
220
|
+
return variants.ok;
|
|
221
|
+
}
|
|
222
|
+
return variants.default;
|
|
223
|
+
}
|
|
224
|
+
if (guard === "prose") {
|
|
225
|
+
if (level === "nudged")
|
|
226
|
+
return variants.nudged;
|
|
227
|
+
if (level === "ok")
|
|
228
|
+
return variants.ok;
|
|
229
|
+
if (tokens.flags?.includes("typesafe error"))
|
|
230
|
+
return variants.typesafe_error;
|
|
231
|
+
if (has("wordy") && has("cliches") && has("jargon"))
|
|
232
|
+
return variants.multiple;
|
|
233
|
+
if (has("wordy"))
|
|
234
|
+
return variants.wordy;
|
|
235
|
+
if (has("cliches"))
|
|
236
|
+
return variants.cliches;
|
|
237
|
+
if (has("jargon"))
|
|
238
|
+
return variants.jargon;
|
|
239
|
+
return variants.default;
|
|
240
|
+
}
|
|
241
|
+
if (guard === "security") {
|
|
242
|
+
if (has("injection") && has("exfiltration"))
|
|
243
|
+
return variants.both;
|
|
244
|
+
if (has("injection"))
|
|
245
|
+
return variants.injection;
|
|
246
|
+
if (has("exfiltration"))
|
|
247
|
+
return variants.exfiltration;
|
|
248
|
+
if (level === "ok")
|
|
249
|
+
return variants.ok;
|
|
250
|
+
return variants.default;
|
|
251
|
+
}
|
|
252
|
+
if (guard === "context") {
|
|
253
|
+
if (tokens.bytesSaved && Number(tokens.bytesSaved) > 0)
|
|
254
|
+
return variants.compressed;
|
|
255
|
+
if (tokens.retention === "all")
|
|
256
|
+
return variants.kept;
|
|
257
|
+
return variants.default;
|
|
258
|
+
}
|
|
259
|
+
if (guard === "runaway") {
|
|
260
|
+
if (level === "stopped, recovering")
|
|
261
|
+
return variants.stopped_recovering;
|
|
262
|
+
if (level === "stopped")
|
|
263
|
+
return variants.stopped;
|
|
264
|
+
return variants.default;
|
|
265
|
+
}
|
|
266
|
+
if (guard === "rules") {
|
|
267
|
+
if (level === "violation")
|
|
268
|
+
return variants.violations;
|
|
269
|
+
if (level === "skipped")
|
|
270
|
+
return variants.skipped;
|
|
271
|
+
if (level === "ok")
|
|
272
|
+
return variants.none;
|
|
273
|
+
return variants.default;
|
|
274
|
+
}
|
|
275
|
+
if (guard === "subagent") {
|
|
276
|
+
if (tokens.wake === "true")
|
|
277
|
+
return variants.wake;
|
|
278
|
+
if (level === "appended silently")
|
|
279
|
+
return variants.appended;
|
|
280
|
+
if (level === "silent")
|
|
281
|
+
return variants.silent;
|
|
282
|
+
return variants.default;
|
|
283
|
+
}
|
|
284
|
+
return DEFAULT_TEMPLATES[guard] ?? "";
|
|
285
|
+
}
|
|
28
286
|
export function defaultWidgetConfig() {
|
|
29
|
-
return { enabled: true, placement: "aboveEditor", shortcut: "ctrl+shift+w", panelWidth: "40%", ...DEFAULT_TEMPLATES };
|
|
287
|
+
return { enabled: true, placement: "aboveEditor", barMode: "live", shortcut: "ctrl+shift+w", panelWidth: "40%", ...DEFAULT_TEMPLATES };
|
|
30
288
|
}
|
|
31
289
|
const SEPARATOR = " · ";
|
|
32
290
|
const TOKEN = /\{([a-zA-Z]+)\}/g;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-warden",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.4",
|
|
4
4
|
"description": "Makes the Pi agent follow your project's rules. Jev judges every write against your pi-warden.md and quotes the broken rule back to the agent, names slop, breaks stuck loops, calls out unverified done claims, compresses large tool output, and holds the rare destructive command. Built on pi-typesafe.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|