@slope-dev/slope 1.13.0 → 1.13.1
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/adapters.d.ts +12 -0
- package/dist/adapters.d.ts.map +1 -0
- package/dist/adapters.js +15 -0
- package/dist/adapters.js.map +1 -0
- package/dist/cli/commands/guard.d.ts.map +1 -1
- package/dist/cli/commands/guard.js +2 -0
- package/dist/cli/commands/guard.js.map +1 -1
- package/dist/cli/commands/hook.d.ts +4 -0
- package/dist/cli/commands/hook.d.ts.map +1 -1
- package/dist/cli/commands/hook.js +57 -83
- package/dist/cli/commands/hook.js.map +1 -1
- package/dist/cli/commands/init.d.ts +10 -3
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +78 -9
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/roadmap.d.ts.map +1 -1
- package/dist/cli/commands/roadmap.js +94 -1
- package/dist/cli/commands/roadmap.js.map +1 -1
- package/dist/cli/guards/branch-before-commit.d.ts +7 -0
- package/dist/cli/guards/branch-before-commit.d.ts.map +1 -0
- package/dist/cli/guards/branch-before-commit.js +43 -0
- package/dist/cli/guards/branch-before-commit.js.map +1 -0
- package/dist/cli/guards/stop-check.d.ts +4 -0
- package/dist/cli/guards/stop-check.d.ts.map +1 -1
- package/dist/cli/guards/stop-check.js +50 -16
- package/dist/cli/guards/stop-check.js.map +1 -1
- package/dist/core/adapters/claude-code.d.ts +25 -0
- package/dist/core/adapters/claude-code.d.ts.map +1 -0
- package/dist/core/adapters/claude-code.js +133 -0
- package/dist/core/adapters/claude-code.js.map +1 -0
- package/dist/core/adapters/cursor.d.ts +35 -0
- package/dist/core/adapters/cursor.d.ts.map +1 -0
- package/dist/core/adapters/cursor.js +138 -0
- package/dist/core/adapters/cursor.js.map +1 -0
- package/dist/core/adapters/generic.d.ts +26 -0
- package/dist/core/adapters/generic.d.ts.map +1 -0
- package/dist/core/adapters/generic.js +137 -0
- package/dist/core/adapters/generic.js.map +1 -0
- package/dist/core/adapters/windsurf.d.ts +34 -0
- package/dist/core/adapters/windsurf.d.ts.map +1 -0
- package/dist/core/adapters/windsurf.js +165 -0
- package/dist/core/adapters/windsurf.js.map +1 -0
- package/dist/core/config.d.ts +1 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js.map +1 -1
- package/dist/core/guard.d.ts +10 -3
- package/dist/core/guard.d.ts.map +1 -1
- package/dist/core/guard.js +33 -59
- package/dist/core/guard.js.map +1 -1
- package/dist/core/harness.d.ts +55 -0
- package/dist/core/harness.d.ts.map +1 -0
- package/dist/core/harness.js +88 -0
- package/dist/core/harness.js.map +1 -0
- package/dist/core/index.d.ts +7 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +7 -0
- package/dist/core/index.js.map +1 -1
- package/package.json +5 -1
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// SLOPE WindsurfAdapter — adapts guard framework to Windsurf's Cascade hook system.
|
|
2
|
+
// Windsurf uses exit-code-based blocking: 0 = allow, 2 = block.
|
|
3
|
+
// The adapter itself is JSON-in/JSON-out; the dispatcher script translates to exit codes.
|
|
4
|
+
//
|
|
5
|
+
// Limitation: Windsurf cannot inject additionalContext into the agent's context.
|
|
6
|
+
// Guards can block but not add guidance. No on-stop event support.
|
|
7
|
+
import { existsSync, writeFileSync, readFileSync, mkdirSync } from 'node:fs';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
import { registerAdapter, resolveToolMatcher } from '../harness.js';
|
|
10
|
+
/** Windsurf tool name mappings */
|
|
11
|
+
const WINDSURF_TOOLS = {
|
|
12
|
+
read_file: 'read_file',
|
|
13
|
+
write_file: 'create_file|edit_file',
|
|
14
|
+
search_files: 'find_files',
|
|
15
|
+
search_content: 'search',
|
|
16
|
+
execute_command: 'run_command',
|
|
17
|
+
create_subagent: 'create_subagent',
|
|
18
|
+
exit_plan: 'exit_plan',
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Map SLOPE hook events to Windsurf hook events.
|
|
22
|
+
* Stop is intentionally omitted — Windsurf has no session-end hook.
|
|
23
|
+
* PreCompact is intentionally omitted — Windsurf has no pre-compaction hook.
|
|
24
|
+
*/
|
|
25
|
+
const HOOK_EVENT_MAP = {
|
|
26
|
+
PreToolUse: 'pre-tool-use',
|
|
27
|
+
PostToolUse: 'post-tool-use',
|
|
28
|
+
};
|
|
29
|
+
/** Windsurf adapter — formats guard output for Windsurf's exit-code-based hook system. */
|
|
30
|
+
export class WindsurfAdapter {
|
|
31
|
+
id = 'windsurf';
|
|
32
|
+
displayName = 'Windsurf';
|
|
33
|
+
toolNames = WINDSURF_TOOLS;
|
|
34
|
+
formatPreToolOutput(result) {
|
|
35
|
+
if (result.decision === 'deny' || result.blockReason) {
|
|
36
|
+
return {
|
|
37
|
+
action: 'deny',
|
|
38
|
+
...(result.blockReason && { message: result.blockReason }),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
// 'ask' and context-only fall through to 'allow' — Windsurf can't inject context or prompt
|
|
42
|
+
return { action: 'allow' };
|
|
43
|
+
}
|
|
44
|
+
formatPostToolOutput(result) {
|
|
45
|
+
if (result.blockReason) {
|
|
46
|
+
return {
|
|
47
|
+
action: 'deny',
|
|
48
|
+
message: result.blockReason,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return { action: 'allow' };
|
|
52
|
+
}
|
|
53
|
+
formatStopOutput(result) {
|
|
54
|
+
// Windsurf doesn't support stop hooks, but format consistently
|
|
55
|
+
if (result.blockReason) {
|
|
56
|
+
return {
|
|
57
|
+
action: 'deny',
|
|
58
|
+
message: result.blockReason,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return { action: 'allow' };
|
|
62
|
+
}
|
|
63
|
+
generateHooksConfig(guards, guardScriptPath) {
|
|
64
|
+
const hooks = [];
|
|
65
|
+
for (const g of guards) {
|
|
66
|
+
const windsurfEvent = HOOK_EVENT_MAP[g.hookEvent];
|
|
67
|
+
if (!windsurfEvent)
|
|
68
|
+
continue; // Skip unsupported hook events (e.g., Stop)
|
|
69
|
+
const matcher = resolveToolMatcher(this, 'toolCategories' in g ? g.toolCategories : undefined) ?? g.matcher;
|
|
70
|
+
const entry = {
|
|
71
|
+
event: windsurfEvent,
|
|
72
|
+
command: `${guardScriptPath} ${g.name}`,
|
|
73
|
+
timeout: 10000,
|
|
74
|
+
description: `SLOPE: ${g.description}`,
|
|
75
|
+
};
|
|
76
|
+
if (matcher)
|
|
77
|
+
entry.matcher = matcher;
|
|
78
|
+
hooks.push(entry);
|
|
79
|
+
}
|
|
80
|
+
return { hooks };
|
|
81
|
+
}
|
|
82
|
+
installGuards(cwd, guards) {
|
|
83
|
+
const hooksDir = join(cwd, '.windsurf', 'hooks');
|
|
84
|
+
mkdirSync(hooksDir, { recursive: true });
|
|
85
|
+
// Create the exit-code dispatcher script
|
|
86
|
+
// This wraps `slope guard`, reads JSON output, and translates to exit codes
|
|
87
|
+
const dispatcherPath = join(hooksDir, 'slope-guard.sh');
|
|
88
|
+
if (!existsSync(dispatcherPath)) {
|
|
89
|
+
const script = [
|
|
90
|
+
'#!/usr/bin/env bash',
|
|
91
|
+
'# SLOPE guard dispatcher for Windsurf — translates JSON to exit codes',
|
|
92
|
+
'# Auto-generated by slope hook add --level=full --harness=windsurf',
|
|
93
|
+
'#',
|
|
94
|
+
'# Windsurf exit-code protocol:',
|
|
95
|
+
'# exit 0 = allow (tool proceeds)',
|
|
96
|
+
'# exit 2 = block (tool denied)',
|
|
97
|
+
'# other = error (logged, tool proceeds)',
|
|
98
|
+
'',
|
|
99
|
+
'# === SLOPE MANAGED (do not edit above this line) ===',
|
|
100
|
+
'OUTPUT=$(slope guard "$@" 2>"${SLOPE_GUARD_LOG:-/dev/null}")',
|
|
101
|
+
'if [ $? -ne 0 ]; then',
|
|
102
|
+
' exit 0 # Guard errored — allow tool to proceed',
|
|
103
|
+
'fi',
|
|
104
|
+
'# Parse action from JSON (handles both compact and prettified output)',
|
|
105
|
+
'ACTION=$(echo "$OUTPUT" | grep -o \'"action"[[:space:]]*:[[:space:]]*"[^"]*"\' | head -1 | cut -d\'"\' -f4)',
|
|
106
|
+
'',
|
|
107
|
+
'if [ "$ACTION" = "deny" ]; then',
|
|
108
|
+
' exit 2',
|
|
109
|
+
'fi',
|
|
110
|
+
'exit 0',
|
|
111
|
+
'# === SLOPE END ===',
|
|
112
|
+
'',
|
|
113
|
+
].join('\n');
|
|
114
|
+
writeFileSync(dispatcherPath, script, { mode: 0o755 });
|
|
115
|
+
console.log(` Created ${dispatcherPath}`);
|
|
116
|
+
}
|
|
117
|
+
// Generate hooks config and merge into .windsurf/hooks.json
|
|
118
|
+
const guardScript = '.windsurf/hooks/slope-guard.sh';
|
|
119
|
+
const hooksConfig = this.generateHooksConfig(guards, guardScript);
|
|
120
|
+
const configPath = join(cwd, '.windsurf', 'hooks.json');
|
|
121
|
+
let existing = { hooks: [] };
|
|
122
|
+
if (existsSync(configPath)) {
|
|
123
|
+
try {
|
|
124
|
+
existing = JSON.parse(readFileSync(configPath, 'utf8'));
|
|
125
|
+
if (!Array.isArray(existing.hooks))
|
|
126
|
+
existing.hooks = [];
|
|
127
|
+
}
|
|
128
|
+
catch { /* start fresh */ }
|
|
129
|
+
}
|
|
130
|
+
// Merge — avoid duplicates by checking command + event
|
|
131
|
+
for (const entry of hooksConfig.hooks) {
|
|
132
|
+
const isDuplicate = existing.hooks.some(e => e.command === entry.command && e.event === entry.event);
|
|
133
|
+
if (!isDuplicate) {
|
|
134
|
+
existing.hooks.push(entry);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
writeFileSync(configPath, JSON.stringify(existing, null, 2) + '\n');
|
|
138
|
+
console.log(` Updated ${configPath} with guard hooks`);
|
|
139
|
+
// Generate guards manifest for reference
|
|
140
|
+
const manifestPath = join(hooksDir, 'guards-manifest.json');
|
|
141
|
+
const manifest = guards
|
|
142
|
+
.filter(g => HOOK_EVENT_MAP[g.hookEvent])
|
|
143
|
+
.map(g => {
|
|
144
|
+
const matcher = resolveToolMatcher(this, 'toolCategories' in g ? g.toolCategories : undefined) ?? g.matcher;
|
|
145
|
+
return {
|
|
146
|
+
name: g.name,
|
|
147
|
+
description: g.description,
|
|
148
|
+
hookEvent: g.hookEvent,
|
|
149
|
+
...(matcher && { matcher }),
|
|
150
|
+
level: g.level,
|
|
151
|
+
command: `${guardScript} ${g.name}`,
|
|
152
|
+
};
|
|
153
|
+
});
|
|
154
|
+
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
|
|
155
|
+
console.log(` Created ${manifestPath}`);
|
|
156
|
+
}
|
|
157
|
+
detect(cwd) {
|
|
158
|
+
return existsSync(join(cwd, '.windsurf'));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/** Singleton instance */
|
|
162
|
+
export const windsurfAdapter = new WindsurfAdapter();
|
|
163
|
+
// Auto-register on import
|
|
164
|
+
registerAdapter(windsurfAdapter);
|
|
165
|
+
//# sourceMappingURL=windsurf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windsurf.js","sourceRoot":"","sources":["../../../src/core/adapters/windsurf.ts"],"names":[],"mappings":"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"}
|
package/dist/core/config.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE;QACT,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;QAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE;QACT,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;QAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;KACpC,CAAC;IACF,aAAa,CAAC,EAAE;QACd,UAAU,CAAC,EAAE,gBAAgB,CAAC;KAC/B,CAAC;IACF,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,SAAS,CAAC,EAAE;QACV,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE;QACT,gBAAgB,EAAE,MAAM,CAAC;QACzB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAqBD,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAsB,GAAG,WAAW,CAWnE;AAED,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAQhE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM,CAEhH"}
|
package/dist/core/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAyDjC,MAAM,cAAc,GAAgB;IAClC,YAAY,EAAE,aAAa;IAC3B,gBAAgB,EAAE,eAAe;IACjC,SAAS,EAAE,CAAC;IACZ,gBAAgB,EAAE,2BAA2B;IAC7C,YAAY,EAAE,sBAAsB;IACpC,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,oBAAoB;IAChC,WAAW,EAAE,2BAA2B;IACxC,SAAS,EAAE,mBAAmB;IAC9B,UAAU,EAAE,oBAAoB;IAChC,eAAe,EAAE,0BAA0B;IAC3C,eAAe,EAAE,oBAAoB;IACrC,QAAQ,EAAE,MAAM;CACjB,CAAC;AAEF,MAAM,UAAU,GAAG,QAAQ,CAAC;AAC5B,MAAM,WAAW,GAAG,aAAa,CAAC;AAElC,MAAM,UAAU,UAAU,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACpD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IACtD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;QACzD,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,GAAG,EAAE,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACtD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAClC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IAC1C,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC1E,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAmB,EAAE,YAAoB,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IACtG,OAAO,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;AACjC,CAAC"}
|
package/dist/core/guard.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ToolCategory } from './harness.js';
|
|
1
2
|
/** Input from Claude Code PreToolUse/PostToolUse hooks (JSON on stdin) */
|
|
2
3
|
export interface HookInput {
|
|
3
4
|
session_id: string;
|
|
@@ -44,14 +45,16 @@ export interface GuardResult {
|
|
|
44
45
|
blockReason?: string;
|
|
45
46
|
}
|
|
46
47
|
/** Known guard names */
|
|
47
|
-
export type GuardName = 'explore' | 'hazard' | 'commit-nudge' | 'scope-drift' | 'compaction' | 'stop-check' | 'subagent-gate' | 'push-nudge' | 'workflow-gate' | 'review-tier' | 'version-check' | 'stale-flows' | 'next-action' | 'pr-review' | 'transcript';
|
|
48
|
+
export type GuardName = 'explore' | 'hazard' | 'commit-nudge' | 'scope-drift' | 'compaction' | 'stop-check' | 'subagent-gate' | 'push-nudge' | 'workflow-gate' | 'review-tier' | 'version-check' | 'stale-flows' | 'next-action' | 'pr-review' | 'transcript' | 'branch-before-commit';
|
|
48
49
|
/** Guard registration entry */
|
|
49
50
|
export interface GuardDefinition {
|
|
50
51
|
name: GuardName;
|
|
51
52
|
description: string;
|
|
52
53
|
/** Which hook event this guard fires on */
|
|
53
54
|
hookEvent: 'PreToolUse' | 'PostToolUse' | 'Stop' | 'PreCompact';
|
|
54
|
-
/**
|
|
55
|
+
/** Harness-agnostic tool categories this guard matches (adapter resolves to tool names) */
|
|
56
|
+
toolCategories?: ToolCategory[];
|
|
57
|
+
/** Regex matcher for tool name (PreToolUse/PostToolUse only) — computed from toolCategories via adapter */
|
|
55
58
|
matcher?: string;
|
|
56
59
|
/** Which --level installs this guard */
|
|
57
60
|
level: 'scoring' | 'full';
|
|
@@ -80,6 +83,8 @@ export interface GuidanceConfig {
|
|
|
80
83
|
pushCommitThreshold?: number;
|
|
81
84
|
/** Directory for compaction handoff files (default '.slope/handoffs') */
|
|
82
85
|
handoffsDir?: string;
|
|
86
|
+
/** Commit message patterns allowed on main/master (branch-before-commit guard) */
|
|
87
|
+
allowMainCommitPatterns?: string[];
|
|
83
88
|
}
|
|
84
89
|
/** All guard definitions */
|
|
85
90
|
export declare const GUARD_DEFINITIONS: GuardDefinition[];
|
|
@@ -89,6 +94,8 @@ export interface CustomGuardDefinition {
|
|
|
89
94
|
description: string;
|
|
90
95
|
hookEvent: 'PreToolUse' | 'PostToolUse' | 'Stop' | 'PreCompact';
|
|
91
96
|
matcher?: string;
|
|
97
|
+
/** Harness-agnostic tool categories this guard applies to */
|
|
98
|
+
toolCategories?: ToolCategory[];
|
|
92
99
|
level: 'scoring' | 'full';
|
|
93
100
|
command: string;
|
|
94
101
|
}
|
|
@@ -110,7 +117,7 @@ export declare function formatPostToolUseOutput(result: GuardResult): PostToolUs
|
|
|
110
117
|
export declare function formatStopOutput(result: GuardResult): StopOutput;
|
|
111
118
|
/**
|
|
112
119
|
* Generate Claude Code settings.json hooks configuration for installed guards.
|
|
113
|
-
*
|
|
120
|
+
* Delegates to ClaudeCodeAdapter.generateHooksConfig().
|
|
114
121
|
*/
|
|
115
122
|
export declare function generateClaudeCodeHooksConfig(guards: AnyGuardDefinition[], guardScriptPath: string): Record<string, Array<{
|
|
116
123
|
matcher?: string;
|
package/dist/core/guard.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/core/guard.ts"],"names":[],"mappings":"AAGA,0EAA0E;AAC1E,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,kCAAkC;AAClC,MAAM,WAAW,gBAAgB;IAC/B,kBAAkB,EAAE;QAClB,aAAa,EAAE,YAAY,CAAC;QAC5B,kBAAkB,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;QAC9C,wBAAwB,CAAC,EAAE,MAAM,CAAC;QAClC,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACxC,CAAC;CACH;AAED,mCAAmC;AACnC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE;QACnB,aAAa,EAAE,aAAa,CAAC;QAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAC;CACH;AAED,4BAA4B;AAC5B,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;IACpC,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAwB;AACxB,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,QAAQ,GACR,cAAc,GACd,aAAa,GACb,YAAY,GACZ,YAAY,GACZ,eAAe,GACf,YAAY,GACZ,eAAe,GACf,aAAa,GACb,eAAe,GACf,aAAa,GACb,aAAa,GACb,WAAW,GACX,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/core/guard.ts"],"names":[],"mappings":"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"}
|
package/dist/core/guard.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
// SLOPE Guard Framework
|
|
2
2
|
// Types and utilities for agent guidance hooks.
|
|
3
|
+
import { getAdapter } from './harness.js';
|
|
3
4
|
/** All guard definitions */
|
|
4
5
|
export const GUARD_DEFINITIONS = [
|
|
5
6
|
{
|
|
6
7
|
name: 'explore',
|
|
7
8
|
description: 'Suggest checking codebase index before deep exploration',
|
|
8
9
|
hookEvent: 'PreToolUse',
|
|
10
|
+
toolCategories: ['read_file', 'search_files', 'search_content'],
|
|
9
11
|
matcher: 'Read|Glob|Grep',
|
|
10
12
|
level: 'full',
|
|
11
13
|
},
|
|
@@ -13,6 +15,7 @@ export const GUARD_DEFINITIONS = [
|
|
|
13
15
|
name: 'hazard',
|
|
14
16
|
description: 'Warn about known issues in file areas being edited',
|
|
15
17
|
hookEvent: 'PreToolUse',
|
|
18
|
+
toolCategories: ['write_file'],
|
|
16
19
|
matcher: 'Edit|Write',
|
|
17
20
|
level: 'full',
|
|
18
21
|
},
|
|
@@ -20,6 +23,7 @@ export const GUARD_DEFINITIONS = [
|
|
|
20
23
|
name: 'commit-nudge',
|
|
21
24
|
description: 'Nudge to commit/push after prolonged editing',
|
|
22
25
|
hookEvent: 'PostToolUse',
|
|
26
|
+
toolCategories: ['write_file'],
|
|
23
27
|
matcher: 'Edit|Write',
|
|
24
28
|
level: 'full',
|
|
25
29
|
},
|
|
@@ -27,6 +31,7 @@ export const GUARD_DEFINITIONS = [
|
|
|
27
31
|
name: 'scope-drift',
|
|
28
32
|
description: 'Warn when editing files outside claimed ticket scope',
|
|
29
33
|
hookEvent: 'PreToolUse',
|
|
34
|
+
toolCategories: ['write_file'],
|
|
30
35
|
matcher: 'Edit|Write',
|
|
31
36
|
level: 'full',
|
|
32
37
|
},
|
|
@@ -46,6 +51,7 @@ export const GUARD_DEFINITIONS = [
|
|
|
46
51
|
name: 'subagent-gate',
|
|
47
52
|
description: 'Force haiku model and cap max_turns on Explore/Plan subagents',
|
|
48
53
|
hookEvent: 'PreToolUse',
|
|
54
|
+
toolCategories: ['create_subagent'],
|
|
49
55
|
matcher: 'Task',
|
|
50
56
|
level: 'full',
|
|
51
57
|
},
|
|
@@ -53,6 +59,7 @@ export const GUARD_DEFINITIONS = [
|
|
|
53
59
|
name: 'push-nudge',
|
|
54
60
|
description: 'Nudge to push after git commits when unpushed count or time is high',
|
|
55
61
|
hookEvent: 'PostToolUse',
|
|
62
|
+
toolCategories: ['execute_command'],
|
|
56
63
|
matcher: 'Bash',
|
|
57
64
|
level: 'full',
|
|
58
65
|
},
|
|
@@ -60,6 +67,7 @@ export const GUARD_DEFINITIONS = [
|
|
|
60
67
|
name: 'workflow-gate',
|
|
61
68
|
description: 'Block ExitPlanMode until review rounds are complete',
|
|
62
69
|
hookEvent: 'PreToolUse',
|
|
70
|
+
toolCategories: ['exit_plan'],
|
|
63
71
|
matcher: 'ExitPlanMode',
|
|
64
72
|
level: 'full',
|
|
65
73
|
},
|
|
@@ -67,6 +75,7 @@ export const GUARD_DEFINITIONS = [
|
|
|
67
75
|
name: 'review-tier',
|
|
68
76
|
description: 'Recommend review tier based on plan scope',
|
|
69
77
|
hookEvent: 'PreToolUse',
|
|
78
|
+
toolCategories: ['exit_plan'],
|
|
70
79
|
matcher: 'ExitPlanMode',
|
|
71
80
|
level: 'full',
|
|
72
81
|
},
|
|
@@ -74,6 +83,7 @@ export const GUARD_DEFINITIONS = [
|
|
|
74
83
|
name: 'version-check',
|
|
75
84
|
description: 'Block push to main when package versions have not been bumped',
|
|
76
85
|
hookEvent: 'PreToolUse',
|
|
86
|
+
toolCategories: ['execute_command'],
|
|
77
87
|
matcher: 'Bash',
|
|
78
88
|
level: 'full',
|
|
79
89
|
},
|
|
@@ -81,6 +91,7 @@ export const GUARD_DEFINITIONS = [
|
|
|
81
91
|
name: 'stale-flows',
|
|
82
92
|
description: 'Warn when editing files belonging to a stale flow definition',
|
|
83
93
|
hookEvent: 'PreToolUse',
|
|
94
|
+
toolCategories: ['write_file'],
|
|
84
95
|
matcher: 'Edit|Write',
|
|
85
96
|
level: 'full',
|
|
86
97
|
},
|
|
@@ -94,6 +105,7 @@ export const GUARD_DEFINITIONS = [
|
|
|
94
105
|
name: 'pr-review',
|
|
95
106
|
description: 'Prompt for review workflow after PR creation',
|
|
96
107
|
hookEvent: 'PostToolUse',
|
|
108
|
+
toolCategories: ['execute_command'],
|
|
97
109
|
matcher: 'Bash',
|
|
98
110
|
level: 'full',
|
|
99
111
|
},
|
|
@@ -101,7 +113,15 @@ export const GUARD_DEFINITIONS = [
|
|
|
101
113
|
name: 'transcript',
|
|
102
114
|
description: 'Append tool call metadata to session transcript',
|
|
103
115
|
hookEvent: 'PostToolUse',
|
|
104
|
-
// no matcher → fires on all tools
|
|
116
|
+
// no toolCategories, no matcher → fires on all tools
|
|
117
|
+
level: 'full',
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: 'branch-before-commit',
|
|
121
|
+
description: 'Block git commit on main/master — create a feature branch first',
|
|
122
|
+
hookEvent: 'PreToolUse',
|
|
123
|
+
toolCategories: ['execute_command'],
|
|
124
|
+
matcher: 'Bash',
|
|
105
125
|
level: 'full',
|
|
106
126
|
},
|
|
107
127
|
];
|
|
@@ -124,76 +144,30 @@ export function getCustomGuard(name) {
|
|
|
124
144
|
export function clearCustomGuards() {
|
|
125
145
|
customGuards.length = 0;
|
|
126
146
|
}
|
|
127
|
-
// --- Formatters ---
|
|
147
|
+
// --- Formatters (delegates to ClaudeCodeAdapter via registry lookup) ---
|
|
148
|
+
function getClaudeCodeAdapter() {
|
|
149
|
+
const adapter = getAdapter('claude-code');
|
|
150
|
+
if (!adapter)
|
|
151
|
+
throw new Error('ClaudeCodeAdapter not registered — ensure adapters/claude-code.js is imported');
|
|
152
|
+
return adapter;
|
|
153
|
+
}
|
|
128
154
|
/** Format a GuardResult as PreToolUse JSON output */
|
|
129
155
|
export function formatPreToolUseOutput(result) {
|
|
130
|
-
return
|
|
131
|
-
hookSpecificOutput: {
|
|
132
|
-
hookEventName: 'PreToolUse',
|
|
133
|
-
...(result.decision && { permissionDecision: result.decision }),
|
|
134
|
-
...(result.blockReason && { permissionDecisionReason: result.blockReason }),
|
|
135
|
-
...(result.context && { additionalContext: result.context }),
|
|
136
|
-
},
|
|
137
|
-
};
|
|
156
|
+
return getClaudeCodeAdapter().formatPreToolOutput(result);
|
|
138
157
|
}
|
|
139
158
|
/** Format a GuardResult as PostToolUse JSON output */
|
|
140
159
|
export function formatPostToolUseOutput(result) {
|
|
141
|
-
|
|
142
|
-
return {
|
|
143
|
-
decision: 'block',
|
|
144
|
-
reason: result.blockReason,
|
|
145
|
-
hookSpecificOutput: {
|
|
146
|
-
hookEventName: 'PostToolUse',
|
|
147
|
-
...(result.context && { additionalContext: result.context }),
|
|
148
|
-
},
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
if (result.context) {
|
|
152
|
-
return {
|
|
153
|
-
hookSpecificOutput: {
|
|
154
|
-
hookEventName: 'PostToolUse',
|
|
155
|
-
additionalContext: result.context,
|
|
156
|
-
},
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
return {};
|
|
160
|
+
return getClaudeCodeAdapter().formatPostToolOutput(result);
|
|
160
161
|
}
|
|
161
162
|
/** Format a GuardResult as Stop JSON output */
|
|
162
163
|
export function formatStopOutput(result) {
|
|
163
|
-
|
|
164
|
-
return { decision: 'block', reason: result.blockReason };
|
|
165
|
-
}
|
|
166
|
-
return {};
|
|
164
|
+
return getClaudeCodeAdapter().formatStopOutput(result);
|
|
167
165
|
}
|
|
168
166
|
/**
|
|
169
167
|
* Generate Claude Code settings.json hooks configuration for installed guards.
|
|
170
|
-
*
|
|
168
|
+
* Delegates to ClaudeCodeAdapter.generateHooksConfig().
|
|
171
169
|
*/
|
|
172
170
|
export function generateClaudeCodeHooksConfig(guards, guardScriptPath) {
|
|
173
|
-
|
|
174
|
-
// Group guards by hookEvent + matcher
|
|
175
|
-
const groups = new Map();
|
|
176
|
-
for (const g of guards) {
|
|
177
|
-
const key = `${g.hookEvent}::${g.matcher ?? ''}`;
|
|
178
|
-
const list = groups.get(key) || [];
|
|
179
|
-
list.push(g);
|
|
180
|
-
groups.set(key, list);
|
|
181
|
-
}
|
|
182
|
-
for (const [key, defs] of groups) {
|
|
183
|
-
const [hookEvent, matcher] = key.split('::');
|
|
184
|
-
if (!config[hookEvent])
|
|
185
|
-
config[hookEvent] = [];
|
|
186
|
-
const hooks = defs.map(d => ({
|
|
187
|
-
type: 'command',
|
|
188
|
-
command: `${guardScriptPath} ${d.name}`,
|
|
189
|
-
timeout: 10,
|
|
190
|
-
statusMessage: `SLOPE: ${d.description}`,
|
|
191
|
-
}));
|
|
192
|
-
const entry = { hooks };
|
|
193
|
-
if (matcher)
|
|
194
|
-
entry.matcher = matcher;
|
|
195
|
-
config[hookEvent].push(entry);
|
|
196
|
-
}
|
|
197
|
-
return config;
|
|
171
|
+
return getClaudeCodeAdapter().generateHooksConfig(guards, guardScriptPath);
|
|
198
172
|
}
|
|
199
173
|
//# sourceMappingURL=guard.js.map
|
package/dist/core/guard.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/core/guard.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,gDAAgD;
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/core/guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { GuardResult, AnyGuardDefinition } from './guard.js';
|
|
2
|
+
/** Known AI coding harness identifiers (extensible via string for third-party adapters) */
|
|
3
|
+
export type HarnessId = 'claude-code' | 'cursor' | 'cline' | 'windsurf' | 'continue' | 'aider' | 'generic' | (string & {});
|
|
4
|
+
/** Tool categories that guards can match against (harness-agnostic) */
|
|
5
|
+
export type ToolCategory = 'read_file' | 'write_file' | 'search_files' | 'search_content' | 'execute_command' | 'create_subagent' | 'exit_plan';
|
|
6
|
+
/** All tool categories for iteration */
|
|
7
|
+
export declare const TOOL_CATEGORIES: ToolCategory[];
|
|
8
|
+
/** Maps tool categories to harness-specific tool name patterns */
|
|
9
|
+
export type ToolNameMap = Record<ToolCategory, string>;
|
|
10
|
+
/** Interface that all harness adapters must implement */
|
|
11
|
+
export interface HarnessAdapter {
|
|
12
|
+
/** Unique identifier for this harness */
|
|
13
|
+
id: HarnessId;
|
|
14
|
+
/** Human-readable display name */
|
|
15
|
+
displayName: string;
|
|
16
|
+
/** Maps tool categories to harness-specific tool names */
|
|
17
|
+
toolNames: ToolNameMap;
|
|
18
|
+
/** Format a GuardResult for PreToolUse hook output */
|
|
19
|
+
formatPreToolOutput(result: GuardResult): unknown;
|
|
20
|
+
/** Format a GuardResult for PostToolUse hook output */
|
|
21
|
+
formatPostToolOutput(result: GuardResult): unknown;
|
|
22
|
+
/** Format a GuardResult for Stop hook output */
|
|
23
|
+
formatStopOutput(result: GuardResult): unknown;
|
|
24
|
+
/** Generate hooks configuration for this harness */
|
|
25
|
+
generateHooksConfig(guards: AnyGuardDefinition[], guardScriptPath: string): unknown;
|
|
26
|
+
/** Install guard hooks into the project for this harness */
|
|
27
|
+
installGuards(cwd: string, guards: AnyGuardDefinition[]): void;
|
|
28
|
+
/** Detect whether this harness is active in the given directory */
|
|
29
|
+
detect(cwd: string): boolean;
|
|
30
|
+
}
|
|
31
|
+
/** Claude Code tool name mappings */
|
|
32
|
+
export declare const CLAUDE_CODE_TOOLS: ToolNameMap;
|
|
33
|
+
/** Detection order for adapters. First match wins. Generic is always last (fallback). */
|
|
34
|
+
export declare const ADAPTER_PRIORITY: HarnessId[];
|
|
35
|
+
/** Register a harness adapter. Idempotent — overwrites if id already registered. */
|
|
36
|
+
export declare function registerAdapter(adapter: HarnessAdapter): void;
|
|
37
|
+
/** Get a registered adapter by id. Returns undefined if not found. */
|
|
38
|
+
export declare function getAdapter(id: HarnessId): HarnessAdapter | undefined;
|
|
39
|
+
/** List all registered adapter ids. */
|
|
40
|
+
export declare function listAdapters(): HarnessId[];
|
|
41
|
+
/**
|
|
42
|
+
* Detect which harness is active in the given directory.
|
|
43
|
+
* Iterates ADAPTER_PRIORITY in order; first match wins.
|
|
44
|
+
* Falls back to generic if registered and no other adapter matches.
|
|
45
|
+
* Adapters not in ADAPTER_PRIORITY are checked after priority list (before generic).
|
|
46
|
+
*/
|
|
47
|
+
export declare function detectAdapter(cwd: string): HarnessAdapter | undefined;
|
|
48
|
+
/** Clear all registered adapters (for testing). */
|
|
49
|
+
export declare function clearAdapters(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Resolve tool categories to a matcher string for a specific harness.
|
|
52
|
+
* If categories is undefined, returns undefined (match all tools).
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveToolMatcher(adapter: HarnessAdapter, categories: ToolCategory[] | undefined): string | undefined;
|
|
55
|
+
//# sourceMappingURL=harness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../src/core/harness.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIlE,2FAA2F;AAC3F,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAE3H,uEAAuE;AACvE,MAAM,MAAM,YAAY,GACpB,WAAW,GACX,YAAY,GACZ,cAAc,GACd,gBAAgB,GAChB,iBAAiB,GACjB,iBAAiB,GACjB,WAAW,CAAC;AAEhB,wCAAwC;AACxC,eAAO,MAAM,eAAe,EAAE,YAAY,EAQzC,CAAC;AAEF,kEAAkE;AAClE,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;AAEvD,yDAAyD;AACzD,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,EAAE,EAAE,SAAS,CAAC;IACd,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,SAAS,EAAE,WAAW,CAAC;IACvB,sDAAsD;IACtD,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC;IAClD,uDAAuD;IACvD,oBAAoB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC;IACnD,gDAAgD;IAChD,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC;IAC/C,oDAAoD;IACpD,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,EAAE,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC;IACpF,4DAA4D;IAC5D,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAAC;IAC/D,mEAAmE;IACnE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC9B;AAID,qCAAqC;AACrC,eAAO,MAAM,iBAAiB,EAAE,WAQ/B,CAAC;AAIF,yFAAyF;AACzF,eAAO,MAAM,gBAAgB,EAAE,SAAS,EAAqD,CAAC;AAM9F,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAE7D;AAED,sEAAsE;AACtE,wBAAgB,UAAU,CAAC,EAAE,EAAE,SAAS,GAAG,cAAc,GAAG,SAAS,CAEpE;AAED,uCAAuC;AACvC,wBAAgB,YAAY,IAAI,SAAS,EAAE,CAE1C;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAerE;AAED,mDAAmD;AACnD,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAUtH"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// SLOPE Harness Adapter Framework
|
|
2
|
+
// Abstracts guard/hook integration from Claude Code to support multiple AI coding harnesses.
|
|
3
|
+
/** All tool categories for iteration */
|
|
4
|
+
export const TOOL_CATEGORIES = [
|
|
5
|
+
'read_file',
|
|
6
|
+
'write_file',
|
|
7
|
+
'search_files',
|
|
8
|
+
'search_content',
|
|
9
|
+
'execute_command',
|
|
10
|
+
'create_subagent',
|
|
11
|
+
'exit_plan',
|
|
12
|
+
];
|
|
13
|
+
// --- Claude Code Tool Name Map ---
|
|
14
|
+
/** Claude Code tool name mappings */
|
|
15
|
+
export const CLAUDE_CODE_TOOLS = {
|
|
16
|
+
read_file: 'Read',
|
|
17
|
+
write_file: 'Edit|Write',
|
|
18
|
+
search_files: 'Glob',
|
|
19
|
+
search_content: 'Grep',
|
|
20
|
+
execute_command: 'Bash',
|
|
21
|
+
create_subagent: 'Task',
|
|
22
|
+
exit_plan: 'ExitPlanMode',
|
|
23
|
+
};
|
|
24
|
+
// --- Adapter Priority ---
|
|
25
|
+
/** Detection order for adapters. First match wins. Generic is always last (fallback). */
|
|
26
|
+
export const ADAPTER_PRIORITY = ['claude-code', 'cursor', 'windsurf', 'generic'];
|
|
27
|
+
// --- Adapter Registry ---
|
|
28
|
+
const adapters = new Map();
|
|
29
|
+
/** Register a harness adapter. Idempotent — overwrites if id already registered. */
|
|
30
|
+
export function registerAdapter(adapter) {
|
|
31
|
+
adapters.set(adapter.id, adapter);
|
|
32
|
+
}
|
|
33
|
+
/** Get a registered adapter by id. Returns undefined if not found. */
|
|
34
|
+
export function getAdapter(id) {
|
|
35
|
+
return adapters.get(id);
|
|
36
|
+
}
|
|
37
|
+
/** List all registered adapter ids. */
|
|
38
|
+
export function listAdapters() {
|
|
39
|
+
return [...adapters.keys()];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Detect which harness is active in the given directory.
|
|
43
|
+
* Iterates ADAPTER_PRIORITY in order; first match wins.
|
|
44
|
+
* Falls back to generic if registered and no other adapter matches.
|
|
45
|
+
* Adapters not in ADAPTER_PRIORITY are checked after priority list (before generic).
|
|
46
|
+
*/
|
|
47
|
+
export function detectAdapter(cwd) {
|
|
48
|
+
// Check priority-ordered adapters first (skip generic — it's the fallback)
|
|
49
|
+
for (const id of ADAPTER_PRIORITY) {
|
|
50
|
+
if (id === 'generic')
|
|
51
|
+
continue;
|
|
52
|
+
const adapter = adapters.get(id);
|
|
53
|
+
if (adapter?.detect(cwd))
|
|
54
|
+
return adapter;
|
|
55
|
+
}
|
|
56
|
+
// Check any registered adapters not in the priority list (third-party)
|
|
57
|
+
for (const adapter of adapters.values()) {
|
|
58
|
+
if (adapter.id === 'generic')
|
|
59
|
+
continue;
|
|
60
|
+
if (ADAPTER_PRIORITY.includes(adapter.id))
|
|
61
|
+
continue;
|
|
62
|
+
if (adapter.detect(cwd))
|
|
63
|
+
return adapter;
|
|
64
|
+
}
|
|
65
|
+
// Fall back to generic if registered
|
|
66
|
+
return adapters.get('generic');
|
|
67
|
+
}
|
|
68
|
+
/** Clear all registered adapters (for testing). */
|
|
69
|
+
export function clearAdapters() {
|
|
70
|
+
adapters.clear();
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Resolve tool categories to a matcher string for a specific harness.
|
|
74
|
+
* If categories is undefined, returns undefined (match all tools).
|
|
75
|
+
*/
|
|
76
|
+
export function resolveToolMatcher(adapter, categories) {
|
|
77
|
+
if (!categories)
|
|
78
|
+
return undefined;
|
|
79
|
+
const names = new Set();
|
|
80
|
+
for (const cat of categories) {
|
|
81
|
+
// Split pipe-separated names (e.g., 'Edit|Write') and add each
|
|
82
|
+
for (const name of adapter.toolNames[cat].split('|')) {
|
|
83
|
+
names.add(name);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return [...names].join('|');
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=harness.js.map
|