greprag 5.38.0 → 5.40.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/dist/commands/discover.d.ts +1 -1
- package/dist/commands/discover.js +6 -5
- package/dist/commands/discover.js.map +1 -1
- package/dist/commands/fix.d.ts +28 -0
- package/dist/commands/fix.js +455 -37
- package/dist/commands/fix.js.map +1 -1
- package/dist/commands/init.js +18 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mechanic.d.ts +64 -0
- package/dist/commands/mechanic.js +374 -0
- package/dist/commands/mechanic.js.map +1 -0
- package/dist/fix-trigger.d.ts +43 -0
- package/dist/fix-trigger.js +270 -0
- package/dist/fix-trigger.js.map +1 -0
- package/dist/guard.d.ts +92 -0
- package/dist/guard.js +404 -0
- package/dist/guard.js.map +1 -0
- package/dist/hook.js +117 -70
- package/dist/hook.js.map +1 -1
- package/dist/index.js +66 -46
- package/dist/index.js.map +1 -1
- package/dist/secret-scrubber.d.ts +48 -0
- package/dist/secret-scrubber.js +368 -0
- package/dist/secret-scrubber.js.map +1 -0
- package/package.json +1 -1
- package/skill/greprag/SKILL.md +6 -3
- package/skill/greprag/docs/corpus.md +15 -0
- package/skill/greprag/docs/discover.md +1 -1
- package/skill/greprag/docs/email.md +46 -0
- package/skill/greprag/docs/fix.md +86 -0
- package/skill/greprag/docs/inbox-watch.md +5 -4
- package/skill/greprag/docs/inbox.md +10 -8
- package/skill/greprag/docs/setup.md +1 -1
- package/skill/mechanic/SKILL.md +22 -2
- package/skill/templates/chip-spawn.md +30 -8
- package/skill/templates/workshop-chip.md +43 -0
- package/skill/greprag/docs/lore.md +0 -70
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** fix-trigger — repair-trigger condition interpreter (CLI MIRROR).
|
|
3
|
+
*
|
|
4
|
+
* MIRROR of packages/core/src/fix-trigger.ts (the canonical source — the SAME
|
|
5
|
+
* module the server validates repair rows with). The CLI ships as a
|
|
6
|
+
* zero-dependency `tsc` artifact — greprag-hook cannot import @greprag/core
|
|
7
|
+
* at runtime (core carries `pg`) — so, exactly like src/secret-scrubber.ts,
|
|
8
|
+
* the pure interpreter is mirrored here. KEEP IN SYNC with core; everything
|
|
9
|
+
* below the Grammar marker is byte-identical, and the sync guard in
|
|
10
|
+
* tests/test-guard-dispatch.cjs fails the build on drift.
|
|
11
|
+
*
|
|
12
|
+
* docs/mechanic-repairs.md D3/D5/D8; contracts: docs/mechanic-engine-contracts.md.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.FIX_TRIGGER_OPS = void 0;
|
|
16
|
+
exports.normalizePathSegments = normalizePathSegments;
|
|
17
|
+
exports.compileSafeRegex = compileSafeRegex;
|
|
18
|
+
exports.evaluateCondition = evaluateCondition;
|
|
19
|
+
exports.validateCondition = validateCondition;
|
|
20
|
+
/** The closed operator set. */
|
|
21
|
+
exports.FIX_TRIGGER_OPS = [
|
|
22
|
+
'contains', 'not_contains', 'equals', 'regex',
|
|
23
|
+
'path_under', 'path_equals', 'starts_with', 'gt', 'lt',
|
|
24
|
+
];
|
|
25
|
+
const MAX_DEPTH = 16;
|
|
26
|
+
const MAX_REGEX_LENGTH = 200;
|
|
27
|
+
const ALLOWED_REGEX_FLAGS = /^[imsu]*$/;
|
|
28
|
+
/** Heuristic linear-time guard: reject a quantified group that itself contains
|
|
29
|
+
* a quantifier — the (a+)+ / (a*){2,} catastrophic-backtracking shape. Coarse
|
|
30
|
+
* (rejects some safe patterns) but never admits the known-bad shape. */
|
|
31
|
+
const NESTED_QUANTIFIER = /\((?:[^()\\]|\\.)*(?:[*+]|\{\d+(?:,\d*)?\})(?:[^()\\]|\\.)*\)\s*(?:[*+?]|\{\d+(?:,\d*)?\})/;
|
|
32
|
+
// ---------- Helpers ----------------------------------------------------------
|
|
33
|
+
/** Dot-path lookup into tool_input. Absent anywhere → undefined. */
|
|
34
|
+
function lookupField(input, field) {
|
|
35
|
+
let cur = input;
|
|
36
|
+
for (const seg of field.split('.')) {
|
|
37
|
+
if (cur === null || typeof cur !== 'object')
|
|
38
|
+
return undefined;
|
|
39
|
+
cur = cur[seg];
|
|
40
|
+
}
|
|
41
|
+
return cur;
|
|
42
|
+
}
|
|
43
|
+
function asString(v) {
|
|
44
|
+
if (typeof v === 'string')
|
|
45
|
+
return v;
|
|
46
|
+
if (typeof v === 'number' || typeof v === 'boolean')
|
|
47
|
+
return String(v);
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
/** Normalize a path to lowercase forward-slash segments with '.'/'..' resolved
|
|
51
|
+
* (no fs access — pure string work). Drive letters keep their colon segment. */
|
|
52
|
+
function normalizePathSegments(p) {
|
|
53
|
+
const raw = p.replace(/\\/g, '/').toLowerCase().split('/');
|
|
54
|
+
const out = [];
|
|
55
|
+
for (const seg of raw) {
|
|
56
|
+
if (seg === '' || seg === '.')
|
|
57
|
+
continue;
|
|
58
|
+
if (seg === '..') {
|
|
59
|
+
out.pop();
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
out.push(seg);
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
function isAbsoluteLike(p) {
|
|
67
|
+
return /^([a-zA-Z]:[\\/]|[\\/])/.test(p);
|
|
68
|
+
}
|
|
69
|
+
/** path_under: absolute value → normalized segment-prefix test; relative value
|
|
70
|
+
* → its segments appear contiguously anywhere in the path ("under any
|
|
71
|
+
* node_modules dir"). Normalization happens on both sides — no `../` escape. */
|
|
72
|
+
function pathUnder(pathValue, underValue) {
|
|
73
|
+
const pathSegs = normalizePathSegments(pathValue);
|
|
74
|
+
const underSegs = normalizePathSegments(underValue);
|
|
75
|
+
if (underSegs.length === 0)
|
|
76
|
+
return false;
|
|
77
|
+
if (isAbsoluteLike(underValue)) {
|
|
78
|
+
if (underSegs.length > pathSegs.length)
|
|
79
|
+
return false;
|
|
80
|
+
return underSegs.every((s, i) => pathSegs[i] === s);
|
|
81
|
+
}
|
|
82
|
+
outer: for (let i = 0; i + underSegs.length <= pathSegs.length; i++) {
|
|
83
|
+
for (let j = 0; j < underSegs.length; j++) {
|
|
84
|
+
if (pathSegs[i + j] !== underSegs[j])
|
|
85
|
+
continue outer;
|
|
86
|
+
}
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
/** Compile a regex under the safety rails; null when rejected. */
|
|
92
|
+
function compileSafeRegex(pattern, flags, log) {
|
|
93
|
+
if (pattern.length > MAX_REGEX_LENGTH) {
|
|
94
|
+
log?.('fix-trigger: regex rejected (length cap)', { length: pattern.length });
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
const f = flags ?? '';
|
|
98
|
+
if (!ALLOWED_REGEX_FLAGS.test(f)) {
|
|
99
|
+
log?.('fix-trigger: regex rejected (flags)', { flags: f });
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
if (NESTED_QUANTIFIER.test(pattern)) {
|
|
103
|
+
log?.('fix-trigger: regex rejected (nested quantifier)', { pattern });
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
return new RegExp(pattern, f);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
log?.('fix-trigger: regex rejected (syntax)', { pattern });
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// ---------- Evaluation -------------------------------------------------------
|
|
115
|
+
function evalClause(clause, input, log) {
|
|
116
|
+
const raw = lookupField(input, clause.field);
|
|
117
|
+
if (raw === undefined || raw === null)
|
|
118
|
+
return false; // absent field = false
|
|
119
|
+
switch (clause.op) {
|
|
120
|
+
case 'contains': {
|
|
121
|
+
const s = asString(raw);
|
|
122
|
+
const v = asString(clause.value);
|
|
123
|
+
return s !== null && v !== null && s.includes(v);
|
|
124
|
+
}
|
|
125
|
+
case 'not_contains': {
|
|
126
|
+
const s = asString(raw);
|
|
127
|
+
const v = asString(clause.value);
|
|
128
|
+
return s !== null && v !== null && !s.includes(v);
|
|
129
|
+
}
|
|
130
|
+
case 'equals': {
|
|
131
|
+
const s = asString(raw);
|
|
132
|
+
const v = asString(clause.value);
|
|
133
|
+
return s !== null && v !== null && s === v;
|
|
134
|
+
}
|
|
135
|
+
case 'starts_with': {
|
|
136
|
+
const s = asString(raw);
|
|
137
|
+
const v = asString(clause.value);
|
|
138
|
+
return s !== null && v !== null && s.startsWith(v);
|
|
139
|
+
}
|
|
140
|
+
case 'regex': {
|
|
141
|
+
const s = asString(raw);
|
|
142
|
+
const v = asString(clause.value);
|
|
143
|
+
if (s === null || v === null)
|
|
144
|
+
return false;
|
|
145
|
+
const re = compileSafeRegex(v, clause.flags, log);
|
|
146
|
+
return re !== null && re.test(s);
|
|
147
|
+
}
|
|
148
|
+
case 'path_under': {
|
|
149
|
+
const s = asString(raw);
|
|
150
|
+
const v = asString(clause.value);
|
|
151
|
+
return s !== null && v !== null && pathUnder(s, v);
|
|
152
|
+
}
|
|
153
|
+
case 'path_equals': {
|
|
154
|
+
const s = asString(raw);
|
|
155
|
+
const v = asString(clause.value);
|
|
156
|
+
if (s === null || v === null)
|
|
157
|
+
return false;
|
|
158
|
+
return normalizePathSegments(s).join('/') === normalizePathSegments(v).join('/');
|
|
159
|
+
}
|
|
160
|
+
case 'gt':
|
|
161
|
+
case 'lt': {
|
|
162
|
+
const n = typeof raw === 'number' ? raw : Number(asString(raw));
|
|
163
|
+
const v = typeof clause.value === 'number' ? clause.value : Number(asString(clause.value));
|
|
164
|
+
if (!Number.isFinite(n) || !Number.isFinite(v))
|
|
165
|
+
return false;
|
|
166
|
+
return clause.op === 'gt' ? n > v : n < v;
|
|
167
|
+
}
|
|
168
|
+
default:
|
|
169
|
+
log?.('fix-trigger: unknown operator (clause = false)', { op: clause.op });
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/** Tri-state inner walk: `invalid` means "malformed/over-deep — never fire".
|
|
174
|
+
* Invalid must NOT be inverted by `not` (a broken subtree can't become a
|
|
175
|
+
* reason to fire), so it propagates as invalid through every combinator. */
|
|
176
|
+
function evalNode(condition, toolInput, log, depth) {
|
|
177
|
+
if (condition === true)
|
|
178
|
+
return true;
|
|
179
|
+
if (depth > MAX_DEPTH) {
|
|
180
|
+
log?.('fix-trigger: condition too deep (= false)', { depth });
|
|
181
|
+
return 'invalid';
|
|
182
|
+
}
|
|
183
|
+
if (condition === null || typeof condition !== 'object' || Array.isArray(condition)) {
|
|
184
|
+
log?.('fix-trigger: malformed condition (= false)');
|
|
185
|
+
return 'invalid';
|
|
186
|
+
}
|
|
187
|
+
const c = condition;
|
|
188
|
+
if (Array.isArray(c.all)) {
|
|
189
|
+
if (c.all.length === 0)
|
|
190
|
+
return false;
|
|
191
|
+
let result = true;
|
|
192
|
+
for (const sub of c.all) {
|
|
193
|
+
const r = evalNode(sub, toolInput, log, depth + 1);
|
|
194
|
+
if (r === 'invalid')
|
|
195
|
+
return 'invalid';
|
|
196
|
+
result = result && r;
|
|
197
|
+
}
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
if (Array.isArray(c.any)) {
|
|
201
|
+
let sawInvalid = false;
|
|
202
|
+
for (const sub of c.any) {
|
|
203
|
+
const r = evalNode(sub, toolInput, log, depth + 1);
|
|
204
|
+
if (r === 'invalid') {
|
|
205
|
+
sawInvalid = true;
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
if (r)
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
return sawInvalid ? 'invalid' : false;
|
|
212
|
+
}
|
|
213
|
+
if ('not' in c) {
|
|
214
|
+
const r = evalNode(c.not, toolInput, log, depth + 1);
|
|
215
|
+
return r === 'invalid' ? 'invalid' : !r;
|
|
216
|
+
}
|
|
217
|
+
if (typeof c.field === 'string' && typeof c.op === 'string') {
|
|
218
|
+
return evalClause(c, toolInput, log);
|
|
219
|
+
}
|
|
220
|
+
log?.('fix-trigger: unrecognized condition shape (= false)');
|
|
221
|
+
return 'invalid';
|
|
222
|
+
}
|
|
223
|
+
/** Evaluate a condition against one event's tool_input. Pure, never throws:
|
|
224
|
+
* every malformed shape evaluates false (and logs via the optional logger). */
|
|
225
|
+
function evaluateCondition(condition, toolInput, log, depth = 0) {
|
|
226
|
+
return evalNode(condition, toolInput, log, depth) === true;
|
|
227
|
+
}
|
|
228
|
+
/** Authoring-time validation: is this a well-formed condition the interpreter
|
|
229
|
+
* will honor? Returns the list of problems (empty = valid). Used server-side
|
|
230
|
+
* before a repair row is stored, so a row can't be born unevaluable. */
|
|
231
|
+
function validateCondition(condition, depth = 0) {
|
|
232
|
+
if (condition === true)
|
|
233
|
+
return [];
|
|
234
|
+
if (depth > MAX_DEPTH)
|
|
235
|
+
return [`condition nesting exceeds ${MAX_DEPTH}`];
|
|
236
|
+
if (condition === null || typeof condition !== 'object' || Array.isArray(condition)) {
|
|
237
|
+
return ['condition must be true, a field clause, or all/any/not'];
|
|
238
|
+
}
|
|
239
|
+
const c = condition;
|
|
240
|
+
if (Array.isArray(c.all)) {
|
|
241
|
+
if (c.all.length === 0)
|
|
242
|
+
return ['all: must be non-empty'];
|
|
243
|
+
return c.all.flatMap(sub => validateCondition(sub, depth + 1));
|
|
244
|
+
}
|
|
245
|
+
if (Array.isArray(c.any)) {
|
|
246
|
+
if (c.any.length === 0)
|
|
247
|
+
return ['any: must be non-empty'];
|
|
248
|
+
return c.any.flatMap(sub => validateCondition(sub, depth + 1));
|
|
249
|
+
}
|
|
250
|
+
if ('not' in c)
|
|
251
|
+
return validateCondition(c.not, depth + 1);
|
|
252
|
+
if (typeof c.field !== 'string' || c.field.length === 0)
|
|
253
|
+
return ['clause missing field'];
|
|
254
|
+
if (typeof c.op !== 'string')
|
|
255
|
+
return ['clause missing op'];
|
|
256
|
+
if (!exports.FIX_TRIGGER_OPS.includes(c.op)) {
|
|
257
|
+
return [`unknown op '${c.op}'`];
|
|
258
|
+
}
|
|
259
|
+
if (c.op === 'regex') {
|
|
260
|
+
const v = typeof c.value === 'string' ? c.value : '';
|
|
261
|
+
if (compileSafeRegex(v, typeof c.flags === 'string' ? c.flags : undefined) === null) {
|
|
262
|
+
return [`regex rejected: '${v}'`];
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
else if (c.value === undefined) {
|
|
266
|
+
return [`op '${c.op}' requires a value`];
|
|
267
|
+
}
|
|
268
|
+
return [];
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=fix-trigger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fix-trigger.js","sourceRoot":"","sources":["../src/fix-trigger.ts"],"names":[],"mappings":"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"}
|
package/dist/guard.d.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/** guard — the PreToolUse repair dispatcher (Chip B, docs/mechanic-repairs.md
|
|
2
|
+
* D1/D2/D5/D8; contracts: docs/mechanic-engine-contracts.md).
|
|
3
|
+
*
|
|
4
|
+
* The ad-blocker model (D5): rules live server-side; each session pulls its
|
|
5
|
+
* matchset at SessionStart into a local cache; every PreToolUse check runs
|
|
6
|
+
* locally in microseconds; fire tallies sync back async via a detached child
|
|
7
|
+
* process and NEVER block the tool call. Total guard posture: local-only on
|
|
8
|
+
* the critical path, any error → fail-open (emit nothing, exit 0).
|
|
9
|
+
*
|
|
10
|
+
* Latch journal placement (documented per contract): latches live INSIDE the
|
|
11
|
+
* matchset cache file under the `latchState` key — one file to read on the
|
|
12
|
+
* hot path, and a refetch preserves it (fetchAndCacheMatchset merges the old
|
|
13
|
+
* latchState into the fresh server body).
|
|
14
|
+
*
|
|
15
|
+
* Cadence `cooldown:N` is interpreted as N MINUTES since lastFired (the local
|
|
16
|
+
* journal stores timestamps, not turn counters; the server-side row keeps the
|
|
17
|
+
* authoritative turn-based view).
|
|
18
|
+
*/
|
|
19
|
+
export declare function killSwitchPath(): string;
|
|
20
|
+
export declare function matchsetCachePath(projectId: string): string;
|
|
21
|
+
export declare function tallySpoolPath(projectId: string): string;
|
|
22
|
+
interface RepairTrigger {
|
|
23
|
+
event?: string;
|
|
24
|
+
matcher?: string;
|
|
25
|
+
condition?: unknown;
|
|
26
|
+
action?: string;
|
|
27
|
+
mode?: string;
|
|
28
|
+
}
|
|
29
|
+
interface RepairObj {
|
|
30
|
+
verb?: string;
|
|
31
|
+
status?: string;
|
|
32
|
+
trigger?: RepairTrigger;
|
|
33
|
+
cadence?: string;
|
|
34
|
+
resetScope?: string;
|
|
35
|
+
failMode?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface MatchsetRepair {
|
|
38
|
+
id: string;
|
|
39
|
+
nodeId: string;
|
|
40
|
+
text: string;
|
|
41
|
+
scope?: string;
|
|
42
|
+
trust?: string;
|
|
43
|
+
repair: RepairObj;
|
|
44
|
+
}
|
|
45
|
+
export interface MatchsetCacheFile {
|
|
46
|
+
triggersVersion: string;
|
|
47
|
+
repairs: MatchsetRepair[];
|
|
48
|
+
/** When the cache was last written from the server. */
|
|
49
|
+
fetchedAt?: string;
|
|
50
|
+
/** Local latch journal: nodeId → latch key (sessionId or "project") → ISO. */
|
|
51
|
+
latchState?: Record<string, Record<string, string>>;
|
|
52
|
+
}
|
|
53
|
+
export interface GuardInput {
|
|
54
|
+
hook_event_name?: string;
|
|
55
|
+
tool_name?: string;
|
|
56
|
+
tool_input?: Record<string, unknown>;
|
|
57
|
+
session_id?: string;
|
|
58
|
+
cwd?: string;
|
|
59
|
+
}
|
|
60
|
+
export interface GuardOutput {
|
|
61
|
+
hookSpecificOutput: {
|
|
62
|
+
hookEventName: string;
|
|
63
|
+
additionalContext?: string;
|
|
64
|
+
permissionDecision?: string;
|
|
65
|
+
permissionDecisionReason?: string;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/** D8 transform denylist (sensitive fields) — kept for the local refusal leg.
|
|
69
|
+
* v1 refuses ALL transforms locally regardless; the list documents the rail
|
|
70
|
+
* the server enforces at authoring time. */
|
|
71
|
+
export declare const TRANSFORM_SENSITIVE_FIELDS: string[];
|
|
72
|
+
/** D8 injection envelope — repair text always lands wrapped as a standing note
|
|
73
|
+
* (data, not a user instruction). */
|
|
74
|
+
export declare function wrapStandingNote(text: string): string;
|
|
75
|
+
export declare function readMatchsetCache(projectId: string): MatchsetCacheFile | null;
|
|
76
|
+
/** Run the dispatcher over one PreToolUse event. Pure given the cache contents
|
|
77
|
+
* read from disk; mutates only local state files (cache latchState + spool).
|
|
78
|
+
* Returns the hook output to emit, or null for silence. NO network — tallies
|
|
79
|
+
* flush via a detached child (spawnTallyFlush). */
|
|
80
|
+
export declare function runGuard(input: GuardInput, projectId: string): GuardOutput | null;
|
|
81
|
+
/** Flush every tally spool in the state dir to the server. Runs in the
|
|
82
|
+
* detached child (guard-flush) — hard 5s timeout per POST; failure keeps the
|
|
83
|
+
* spool for the next flush. */
|
|
84
|
+
export declare function flushTallySpools(apiUrl: string, apiKey: string): Promise<void>;
|
|
85
|
+
/** GET the matchset and write the cache, preserving the local latch journal.
|
|
86
|
+
* Hard 3s timeout; any failure leaves the existing cache untouched. */
|
|
87
|
+
export declare function fetchAndCacheMatchset(apiUrl: string, apiKey: string, projectId: string): Promise<string | null>;
|
|
88
|
+
/** UserPromptSubmit freshness leg: when the cache is stale (>2 min since last
|
|
89
|
+
* server contact), spawn a detached `guard-refresh` child that re-fetches and
|
|
90
|
+
* rewrites the cache iff triggersVersion changed. Never blocks the turn. */
|
|
91
|
+
export declare function maybeSpawnGuardRefresh(cwd: string, projectId: string): void;
|
|
92
|
+
export {};
|