@slope-dev/slope 1.13.0 → 1.13.2

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.
Files changed (126) hide show
  1. package/README.md +118 -189
  2. package/dist/adapters.d.ts +15 -0
  3. package/dist/adapters.d.ts.map +1 -0
  4. package/dist/adapters.js +17 -0
  5. package/dist/adapters.js.map +1 -0
  6. package/dist/cli/commands/guard.d.ts +19 -0
  7. package/dist/cli/commands/guard.d.ts.map +1 -1
  8. package/dist/cli/commands/guard.js +89 -1
  9. package/dist/cli/commands/guard.js.map +1 -1
  10. package/dist/cli/commands/hook.d.ts +5 -0
  11. package/dist/cli/commands/hook.d.ts.map +1 -1
  12. package/dist/cli/commands/hook.js +59 -83
  13. package/dist/cli/commands/hook.js.map +1 -1
  14. package/dist/cli/commands/init.d.ts +13 -4
  15. package/dist/cli/commands/init.d.ts.map +1 -1
  16. package/dist/cli/commands/init.js +309 -16
  17. package/dist/cli/commands/init.js.map +1 -1
  18. package/dist/cli/commands/metaphor.d.ts +3 -0
  19. package/dist/cli/commands/metaphor.d.ts.map +1 -0
  20. package/dist/cli/commands/metaphor.js +100 -0
  21. package/dist/cli/commands/metaphor.js.map +1 -0
  22. package/dist/cli/commands/roadmap.d.ts.map +1 -1
  23. package/dist/cli/commands/roadmap.js +94 -1
  24. package/dist/cli/commands/roadmap.js.map +1 -1
  25. package/dist/cli/commands/store.d.ts +2 -0
  26. package/dist/cli/commands/store.d.ts.map +1 -0
  27. package/dist/cli/commands/store.js +204 -0
  28. package/dist/cli/commands/store.js.map +1 -0
  29. package/dist/cli/guards/branch-before-commit.d.ts +7 -0
  30. package/dist/cli/guards/branch-before-commit.d.ts.map +1 -0
  31. package/dist/cli/guards/branch-before-commit.js +43 -0
  32. package/dist/cli/guards/branch-before-commit.js.map +1 -0
  33. package/dist/cli/guards/stop-check.d.ts +4 -0
  34. package/dist/cli/guards/stop-check.d.ts.map +1 -1
  35. package/dist/cli/guards/stop-check.js +50 -16
  36. package/dist/cli/guards/stop-check.js.map +1 -1
  37. package/dist/cli/index.js +20 -1
  38. package/dist/cli/index.js.map +1 -1
  39. package/dist/cli/registry.d.ts.map +1 -1
  40. package/dist/cli/registry.js +2 -0
  41. package/dist/cli/registry.js.map +1 -1
  42. package/dist/cli/store.d.ts +9 -0
  43. package/dist/cli/store.d.ts.map +1 -1
  44. package/dist/cli/store.js +29 -0
  45. package/dist/cli/store.js.map +1 -1
  46. package/dist/cli/template-generator.d.ts +1 -1
  47. package/dist/cli/template-generator.d.ts.map +1 -1
  48. package/dist/cli/template-generator.js +5 -3
  49. package/dist/cli/template-generator.js.map +1 -1
  50. package/dist/core/adapters/claude-code.d.ts +28 -0
  51. package/dist/core/adapters/claude-code.d.ts.map +1 -0
  52. package/dist/core/adapters/claude-code.js +148 -0
  53. package/dist/core/adapters/claude-code.js.map +1 -0
  54. package/dist/core/adapters/cline.d.ts +36 -0
  55. package/dist/core/adapters/cline.d.ts.map +1 -0
  56. package/dist/core/adapters/cline.js +279 -0
  57. package/dist/core/adapters/cline.js.map +1 -0
  58. package/dist/core/adapters/cursor.d.ts +38 -0
  59. package/dist/core/adapters/cursor.d.ts.map +1 -0
  60. package/dist/core/adapters/cursor.js +143 -0
  61. package/dist/core/adapters/cursor.js.map +1 -0
  62. package/dist/core/adapters/generic.d.ts +29 -0
  63. package/dist/core/adapters/generic.d.ts.map +1 -0
  64. package/dist/core/adapters/generic.js +142 -0
  65. package/dist/core/adapters/generic.js.map +1 -0
  66. package/dist/core/adapters/windsurf.d.ts +37 -0
  67. package/dist/core/adapters/windsurf.d.ts.map +1 -0
  68. package/dist/core/adapters/windsurf.js +170 -0
  69. package/dist/core/adapters/windsurf.js.map +1 -0
  70. package/dist/core/config.d.ts +3 -0
  71. package/dist/core/config.d.ts.map +1 -1
  72. package/dist/core/config.js +9 -0
  73. package/dist/core/config.js.map +1 -1
  74. package/dist/core/guard.d.ts +10 -3
  75. package/dist/core/guard.d.ts.map +1 -1
  76. package/dist/core/guard.js +33 -59
  77. package/dist/core/guard.js.map +1 -1
  78. package/dist/core/harness.d.ts +61 -0
  79. package/dist/core/harness.d.ts.map +1 -0
  80. package/dist/core/harness.js +88 -0
  81. package/dist/core/harness.js.map +1 -0
  82. package/dist/core/index.d.ts +15 -5
  83. package/dist/core/index.d.ts.map +1 -1
  84. package/dist/core/index.js +13 -3
  85. package/dist/core/index.js.map +1 -1
  86. package/dist/core/interview.js +1 -1
  87. package/dist/core/interview.js.map +1 -1
  88. package/dist/core/metaphor.d.ts +14 -0
  89. package/dist/core/metaphor.d.ts.map +1 -1
  90. package/dist/core/metaphor.js +14 -0
  91. package/dist/core/metaphor.js.map +1 -1
  92. package/dist/core/plugins.d.ts +12 -0
  93. package/dist/core/plugins.d.ts.map +1 -1
  94. package/dist/core/plugins.js +58 -1
  95. package/dist/core/plugins.js.map +1 -1
  96. package/dist/core/roadmap.d.ts.map +1 -1
  97. package/dist/core/roadmap.js +5 -4
  98. package/dist/core/roadmap.js.map +1 -1
  99. package/dist/core/store-health.d.ts +11 -0
  100. package/dist/core/store-health.d.ts.map +1 -0
  101. package/dist/core/store-health.js +26 -0
  102. package/dist/core/store-health.js.map +1 -0
  103. package/dist/core/store.d.ts +10 -0
  104. package/dist/core/store.d.ts.map +1 -1
  105. package/dist/core/store.js.map +1 -1
  106. package/dist/mcp/index.d.ts +2 -2
  107. package/dist/mcp/index.d.ts.map +1 -1
  108. package/dist/mcp/index.js +55 -6
  109. package/dist/mcp/index.js.map +1 -1
  110. package/dist/mcp/index.test.js +7 -4
  111. package/dist/mcp/index.test.js.map +1 -1
  112. package/dist/mcp/registry.d.ts.map +1 -1
  113. package/dist/mcp/registry.js +32 -3
  114. package/dist/mcp/registry.js.map +1 -1
  115. package/dist/mcp/sandbox.d.ts.map +1 -1
  116. package/dist/mcp/sandbox.js +7 -1
  117. package/dist/mcp/sandbox.js.map +1 -1
  118. package/dist/store/index.d.ts +8 -2
  119. package/dist/store/index.d.ts.map +1 -1
  120. package/dist/store/index.js +27 -3
  121. package/dist/store/index.js.map +1 -1
  122. package/dist/store-pg/index.d.ts +3 -0
  123. package/dist/store-pg/index.d.ts.map +1 -1
  124. package/dist/store-pg/index.js +49 -1
  125. package/dist/store-pg/index.js.map +1 -1
  126. package/package.json +16 -7
@@ -0,0 +1,279 @@
1
+ // SLOPE ClineAdapter — adapts guard framework to Cline's per-event hook system.
2
+ // Cline (v3.36+) uses per-event executable scripts in .clinerules/hooks/.
3
+ // Each script receives JSON on stdin and returns JSON on stdout.
4
+ //
5
+ // Source: https://docs.cline.bot/features/hooks
6
+ // Verified against Cline v3.68.0 (2026-02-27), github.com/cline/cline
7
+ import { existsSync, writeFileSync, mkdirSync, chmodSync } from 'node:fs';
8
+ import { join } from 'node:path';
9
+ import { registerAdapter, resolveToolMatcher } from '../harness.js';
10
+ /**
11
+ * Cline tool name mappings — verified from Cline v3.68.0 system prompt.
12
+ *
13
+ * CAUTION: Cline's `search_files` is a content search (regex grep), NOT file listing.
14
+ * `list_files` is file/directory listing. This is the opposite of what the names suggest.
15
+ */
16
+ const CLINE_TOOLS = {
17
+ read_file: 'read_file',
18
+ write_file: 'write_to_file|replace_in_file',
19
+ search_files: 'list_files', // file discovery, NOT content search
20
+ search_content: 'search_files', // content grep, NOT file listing
21
+ execute_command: 'execute_command',
22
+ create_subagent: 'use_mcp_tool',
23
+ exit_plan: 'plan_mode_response',
24
+ };
25
+ /**
26
+ * Map SLOPE hook events to Cline hook event names (PascalCase, matching script filenames).
27
+ *
28
+ * TaskComplete is intentionally NOT mapped to Stop — a completed task already finished
29
+ * and can't be blocked. Only TaskCancel maps to Stop because cancellation can be intercepted.
30
+ */
31
+ const HOOK_EVENT_MAP = {
32
+ PreToolUse: 'PreToolUse',
33
+ PostToolUse: 'PostToolUse',
34
+ Stop: 'TaskCancel',
35
+ PreCompact: 'PreCompact',
36
+ };
37
+ /** Cline adapter — formats guard output for Cline's per-event script protocol. */
38
+ export class ClineAdapter {
39
+ id = 'cline';
40
+ displayName = 'Cline';
41
+ toolNames = CLINE_TOOLS;
42
+ supportedEvents = new Set(['PreToolUse', 'PostToolUse', 'Stop', 'PreCompact']);
43
+ supportsContextInjection = true;
44
+ hooksConfigPath(_cwd) {
45
+ // Cline uses directory-based hook discovery (per-event scripts), not a single config file.
46
+ // Returning null matches GenericAdapter pattern and avoids breaking readFileSync callers.
47
+ return null;
48
+ }
49
+ formatPreToolOutput(result) {
50
+ if (result.decision === 'deny' || result.blockReason) {
51
+ return {
52
+ cancel: true,
53
+ ...(result.blockReason && { errorMessage: result.blockReason }),
54
+ ...(result.context && { contextModification: result.context }),
55
+ };
56
+ }
57
+ // 'ask' maps to cancel: false — Cline has no user-confirmation prompt
58
+ return {
59
+ cancel: false,
60
+ ...(result.context && { contextModification: result.context }),
61
+ };
62
+ }
63
+ formatPostToolOutput(result) {
64
+ if (result.blockReason) {
65
+ return {
66
+ cancel: true,
67
+ errorMessage: result.blockReason,
68
+ ...(result.context && { contextModification: result.context }),
69
+ };
70
+ }
71
+ return {
72
+ cancel: false,
73
+ ...(result.context && { contextModification: result.context }),
74
+ };
75
+ }
76
+ formatStopOutput(result) {
77
+ if (result.blockReason) {
78
+ return {
79
+ cancel: true,
80
+ errorMessage: result.blockReason,
81
+ };
82
+ }
83
+ return { cancel: false };
84
+ }
85
+ /**
86
+ * Generate per-event dispatcher script content for a set of guards.
87
+ * Cline has no hooks.json — each event has a single script that must handle
88
+ * all guards for that event, including tool name filtering.
89
+ */
90
+ generateHooksConfig(guards, guardScriptPath) {
91
+ const scripts = {};
92
+ // Group guards by Cline event
93
+ const guardsByEvent = new Map();
94
+ for (const g of guards) {
95
+ const clineEvent = HOOK_EVENT_MAP[g.hookEvent];
96
+ if (!clineEvent)
97
+ continue;
98
+ let list = guardsByEvent.get(clineEvent);
99
+ if (!list) {
100
+ list = [];
101
+ guardsByEvent.set(clineEvent, list);
102
+ }
103
+ list.push(g);
104
+ }
105
+ for (const [event, eventGuards] of guardsByEvent) {
106
+ const guardCalls = eventGuards.map(g => {
107
+ const matcher = resolveToolMatcher(this, 'toolCategories' in g ? g.toolCategories : undefined);
108
+ if (matcher) {
109
+ // Filter by tool name — Cline has no built-in matcher, so we filter in the script
110
+ const tools = matcher.split('|').map(t => `"${t}"`).join(' ');
111
+ return [
112
+ `# Guard: ${g.name} — ${g.description}`,
113
+ `TOOLS=(${tools})`,
114
+ `if tool_matches "$TOOL_NAME" "\${TOOLS[@]}"; then`,
115
+ ` run_guard "${guardScriptPath}" "${g.name}"`,
116
+ `fi`,
117
+ ].join('\n');
118
+ }
119
+ // No matcher — runs for all tools
120
+ return [
121
+ `# Guard: ${g.name} — ${g.description}`,
122
+ `run_guard "${guardScriptPath}" "${g.name}"`,
123
+ ].join('\n');
124
+ });
125
+ scripts[event] = [
126
+ '#!/usr/bin/env bash',
127
+ `# SLOPE guard dispatcher for Cline ${event} event`,
128
+ '# Auto-generated by slope hook add --level=full --harness=cline',
129
+ '#',
130
+ '# Cline passes JSON on stdin. This script routes to matching SLOPE guards',
131
+ '# and returns JSON on stdout with { cancel, contextModification, errorMessage }.',
132
+ '',
133
+ '# === SLOPE MANAGED (do not edit above this line) ===',
134
+ '',
135
+ '# Read stdin once and cache it',
136
+ 'INPUT=$(cat)',
137
+ '',
138
+ '# Extract tool name from Cline stdin JSON.',
139
+ '# Cline nests tool info under the event key: { "preToolUse": { "tool": "..." } }',
140
+ '# For non-tool events (TaskCancel, PreCompact), TOOL_NAME will be empty — this is correct.',
141
+ 'HAS_JQ=false',
142
+ 'command -v jq >/dev/null 2>&1 && HAS_JQ=true',
143
+ '',
144
+ 'if [ "$HAS_JQ" = "true" ]; then',
145
+ ' TOOL_NAME=$(echo "$INPUT" | jq -r \'(.preToolUse.tool // .postToolUse.tool // empty)\' 2>/dev/null || true)',
146
+ 'else',
147
+ ' # Fallback: extract from nested event object. Looks for "tool" key after the event key.',
148
+ ' TOOL_NAME=$(echo "$INPUT" | sed -n \'s/.*"tool"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p\' | head -1)',
149
+ 'fi',
150
+ '',
151
+ '# Track combined result',
152
+ 'CANCELLED=false',
153
+ 'ERROR_MSG=""',
154
+ 'CONTEXT=""',
155
+ '',
156
+ 'tool_matches() {',
157
+ ' local tool="$1"; shift',
158
+ ' for t in "$@"; do',
159
+ ' [ "$tool" = "$t" ] && return 0',
160
+ ' done',
161
+ ' return 1',
162
+ '}',
163
+ '',
164
+ '# JSON-safe string escape (for printf output)',
165
+ 'json_escape() {',
166
+ ' local s="$1"',
167
+ ' s="${s//\\\\/\\\\\\\\}"', // escape backslashes
168
+ ' s="${s//\\"/\\\\\\"}"', // escape double quotes
169
+ ' printf "%s" "$s"',
170
+ '}',
171
+ '',
172
+ 'run_guard() {',
173
+ ' local script="$1" guard="$2"',
174
+ ' local result',
175
+ ' result=$(echo "$INPUT" | "$script" "$guard" 2>/dev/null) || return 0',
176
+ ' ',
177
+ ' if [ "$HAS_JQ" = "true" ]; then',
178
+ ' local cancel ctx msg',
179
+ ' cancel=$(echo "$result" | jq -r \'.cancel // false\' 2>/dev/null || true)',
180
+ ' if [ "$cancel" = "true" ]; then',
181
+ ' CANCELLED=true',
182
+ ' msg=$(echo "$result" | jq -r \'.errorMessage // empty\' 2>/dev/null || true)',
183
+ ' [ -n "$msg" ] && ERROR_MSG="${ERROR_MSG:+$ERROR_MSG; }$msg"',
184
+ ' fi',
185
+ ' ctx=$(echo "$result" | jq -r \'.contextModification // empty\' 2>/dev/null || true)',
186
+ ' [ -n "$ctx" ] && CONTEXT="${CONTEXT:+$CONTEXT; }$ctx"',
187
+ ' else',
188
+ ' # Fallback: grep-based JSON parsing',
189
+ ' local cancel',
190
+ ' cancel=$(echo "$result" | sed -n \'s/.*"cancel"[[:space:]]*:[[:space:]]*\\(true\\).*/\\1/p\' | head -1)',
191
+ ' if [ "$cancel" = "true" ]; then',
192
+ ' CANCELLED=true',
193
+ ' local msg',
194
+ ' msg=$(echo "$result" | sed -n \'s/.*"errorMessage"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p\' | head -1)',
195
+ ' [ -n "$msg" ] && ERROR_MSG="${ERROR_MSG:+$ERROR_MSG; }$msg"',
196
+ ' fi',
197
+ ' local ctx',
198
+ ' ctx=$(echo "$result" | sed -n \'s/.*"contextModification"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p\' | head -1)',
199
+ ' [ -n "$ctx" ] && CONTEXT="${CONTEXT:+$CONTEXT; }$ctx"',
200
+ ' fi',
201
+ '}',
202
+ '',
203
+ ...guardCalls,
204
+ '',
205
+ '# Output combined result — use jq for safe JSON encoding if available',
206
+ 'if [ "$HAS_JQ" = "true" ]; then',
207
+ ' if [ "$CANCELLED" = "true" ]; then',
208
+ ' jq -n --argjson cancel true --arg err "$ERROR_MSG" --arg ctx "$CONTEXT" \\',
209
+ ' \'if ($ctx | length) > 0 then {cancel:$cancel,errorMessage:$err,contextModification:$ctx} else {cancel:$cancel,errorMessage:$err} end\'',
210
+ ' elif [ -n "$CONTEXT" ]; then',
211
+ ' jq -n --argjson cancel false --arg ctx "$CONTEXT" \'{cancel:$cancel,contextModification:$ctx}\'',
212
+ ' else',
213
+ ' echo \'{"cancel":false}\'',
214
+ ' fi',
215
+ 'else',
216
+ ' # Fallback: manual JSON with escaped values',
217
+ ' if [ "$CANCELLED" = "true" ]; then',
218
+ ' if [ -n "$CONTEXT" ]; then',
219
+ ' printf \'{"cancel":true,"errorMessage":"%s","contextModification":"%s"}\\n\' "$(json_escape "$ERROR_MSG")" "$(json_escape "$CONTEXT")"',
220
+ ' else',
221
+ ' printf \'{"cancel":true,"errorMessage":"%s"}\\n\' "$(json_escape "$ERROR_MSG")"',
222
+ ' fi',
223
+ ' elif [ -n "$CONTEXT" ]; then',
224
+ ' printf \'{"cancel":false,"contextModification":"%s"}\\n\' "$(json_escape "$CONTEXT")"',
225
+ ' else',
226
+ ' printf \'{"cancel":false}\\n\'',
227
+ ' fi',
228
+ 'fi',
229
+ '',
230
+ '# === SLOPE END ===',
231
+ '',
232
+ ].join('\n');
233
+ }
234
+ return scripts;
235
+ }
236
+ installGuards(cwd, guards) {
237
+ const hooksDir = join(cwd, '.clinerules', 'hooks');
238
+ mkdirSync(hooksDir, { recursive: true });
239
+ // Create the guard dispatcher (used by per-event scripts)
240
+ const dispatcherPath = join(hooksDir, 'slope-guard.sh');
241
+ if (!existsSync(dispatcherPath)) {
242
+ const script = [
243
+ '#!/usr/bin/env bash',
244
+ '# SLOPE guard dispatcher — called by per-event hook scripts',
245
+ '# Auto-generated by slope hook add --level=full --harness=cline',
246
+ '#',
247
+ '# Receives JSON on stdin, passes to slope guard, returns JSON on stdout.',
248
+ '',
249
+ '# === SLOPE MANAGED (do not edit above this line) ===',
250
+ 'slope guard "$@"',
251
+ '# === SLOPE END ===',
252
+ '',
253
+ ].join('\n');
254
+ writeFileSync(dispatcherPath, script, { mode: 0o755 });
255
+ console.log(` Created ${dispatcherPath}`);
256
+ }
257
+ // Generate per-event scripts
258
+ const guardScript = join('.clinerules', 'hooks', 'slope-guard.sh');
259
+ const eventScripts = this.generateHooksConfig(guards, guardScript);
260
+ for (const [event, content] of Object.entries(eventScripts)) {
261
+ const scriptPath = join(hooksDir, event);
262
+ // Always overwrite event scripts (they're fully generated)
263
+ writeFileSync(scriptPath, content);
264
+ chmodSync(scriptPath, 0o755);
265
+ console.log(` Created ${scriptPath}`);
266
+ }
267
+ console.log(` Installed ${Object.keys(eventScripts).length} Cline hook scripts to ${hooksDir}`);
268
+ }
269
+ detect(cwd) {
270
+ // Only detect if hooks directory exists (not just .clinerules/)
271
+ // Prevents false-positives on Cline projects that use rules without SLOPE hooks
272
+ return existsSync(join(cwd, '.clinerules', 'hooks'));
273
+ }
274
+ }
275
+ /** Singleton instance */
276
+ export const clineAdapter = new ClineAdapter();
277
+ // Auto-register on import
278
+ registerAdapter(clineAdapter);
279
+ //# sourceMappingURL=cline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cline.js","sourceRoot":"","sources":["../../../src/core/adapters/cline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { HarnessAdapter, ToolNameMap } from '../harness.js';
2
+ import type { GuardResult, AnyGuardDefinition } from '../guard.js';
3
+ /** Cursor hook entry in .cursor/hooks.json */
4
+ export interface CursorHookEntry {
5
+ event: string;
6
+ matcher?: string;
7
+ command: string;
8
+ timeout?: number;
9
+ description?: string;
10
+ }
11
+ /** Cursor hooks config shape */
12
+ export interface CursorHooksConfig {
13
+ hooks: CursorHookEntry[];
14
+ }
15
+ /** Cursor hook output protocol */
16
+ export interface CursorHookOutput {
17
+ decision: 'allow' | 'block';
18
+ reason?: string;
19
+ context?: string;
20
+ }
21
+ /** Cursor adapter — formats guard output for Cursor's JSON hook protocol. */
22
+ export declare class CursorAdapter implements HarnessAdapter {
23
+ readonly id: "cursor";
24
+ readonly displayName = "Cursor";
25
+ readonly toolNames: ToolNameMap;
26
+ readonly supportedEvents: Set<string>;
27
+ readonly supportsContextInjection = true;
28
+ hooksConfigPath(cwd: string): string | null;
29
+ formatPreToolOutput(result: GuardResult): CursorHookOutput;
30
+ formatPostToolOutput(result: GuardResult): CursorHookOutput;
31
+ formatStopOutput(result: GuardResult): CursorHookOutput;
32
+ generateHooksConfig(guards: AnyGuardDefinition[], guardScriptPath: string): CursorHooksConfig;
33
+ installGuards(cwd: string, guards: AnyGuardDefinition[]): void;
34
+ detect(cwd: string): boolean;
35
+ }
36
+ /** Singleton instance */
37
+ export declare const cursorAdapter: CursorAdapter;
38
+ //# sourceMappingURL=cursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/cursor.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjE,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAanE,8CAA8C;AAC9C,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,gCAAgC;AAChC,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B;AAED,kCAAkC;AAClC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAYD,6EAA6E;AAC7E,qBAAa,aAAc,YAAW,cAAc;IAClD,QAAQ,CAAC,EAAE,EAAG,QAAQ,CAAU;IAChC,QAAQ,CAAC,WAAW,YAAY;IAChC,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAgB;IAC/C,QAAQ,CAAC,eAAe,cAAkD;IAC1E,QAAQ,CAAC,wBAAwB,QAAQ;IAEzC,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAI3C,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,gBAAgB;IAe1D,oBAAoB,CAAC,MAAM,EAAE,WAAW,GAAG,gBAAgB;IAc3D,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,gBAAgB;IAUvD,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,EAAE,EAAE,eAAe,EAAE,MAAM,GAAG,iBAAiB;IAsB7F,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,GAAG,IAAI;IAmD9D,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;CAG7B;AAED,yBAAyB;AACzB,eAAO,MAAM,aAAa,eAAsB,CAAC"}
@@ -0,0 +1,143 @@
1
+ // SLOPE CursorAdapter — adapts guard framework to Cursor's hook system.
2
+ // Cursor (v1.7+) uses JSON stdin/stdout protocol with .cursor/hooks.json config.
3
+ import { existsSync, writeFileSync, readFileSync, mkdirSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ import { registerAdapter, resolveToolMatcher } from '../harness.js';
6
+ /** Cursor tool name mappings */
7
+ const CURSOR_TOOLS = {
8
+ read_file: 'read_file',
9
+ write_file: 'file_edit|create_file',
10
+ search_files: 'list_directory',
11
+ search_content: 'grep_search',
12
+ execute_command: 'run_terminal_command',
13
+ create_subagent: 'create_subagent',
14
+ exit_plan: 'exit_plan',
15
+ };
16
+ /**
17
+ * Map SLOPE hook events to Cursor hook events.
18
+ * PreCompact is intentionally omitted — Cursor has no pre-compaction hook.
19
+ */
20
+ const HOOK_EVENT_MAP = {
21
+ PreToolUse: 'pre-tool-use',
22
+ PostToolUse: 'post-tool-use',
23
+ Stop: 'on-stop',
24
+ };
25
+ /** Cursor adapter — formats guard output for Cursor's JSON hook protocol. */
26
+ export class CursorAdapter {
27
+ id = 'cursor';
28
+ displayName = 'Cursor';
29
+ toolNames = CURSOR_TOOLS;
30
+ supportedEvents = new Set(['PreToolUse', 'PostToolUse', 'Stop']);
31
+ supportsContextInjection = true;
32
+ hooksConfigPath(cwd) {
33
+ return join(cwd, '.cursor', 'hooks.json');
34
+ }
35
+ formatPreToolOutput(result) {
36
+ if (result.decision === 'deny' || result.blockReason) {
37
+ return {
38
+ decision: 'block',
39
+ ...(result.blockReason && { reason: result.blockReason }),
40
+ ...(result.context && { context: result.context }),
41
+ };
42
+ }
43
+ // 'ask' falls through to 'allow' — Cursor has no user-confirmation prompt
44
+ return {
45
+ decision: 'allow',
46
+ ...(result.context && { context: result.context }),
47
+ };
48
+ }
49
+ formatPostToolOutput(result) {
50
+ if (result.blockReason) {
51
+ return {
52
+ decision: 'block',
53
+ reason: result.blockReason,
54
+ ...(result.context && { context: result.context }),
55
+ };
56
+ }
57
+ return {
58
+ decision: 'allow',
59
+ ...(result.context && { context: result.context }),
60
+ };
61
+ }
62
+ formatStopOutput(result) {
63
+ if (result.blockReason) {
64
+ return {
65
+ decision: 'block',
66
+ reason: result.blockReason,
67
+ };
68
+ }
69
+ return { decision: 'allow' };
70
+ }
71
+ generateHooksConfig(guards, guardScriptPath) {
72
+ const hooks = [];
73
+ for (const g of guards) {
74
+ const cursorEvent = HOOK_EVENT_MAP[g.hookEvent];
75
+ if (!cursorEvent)
76
+ continue; // Skip unsupported hook events
77
+ const matcher = resolveToolMatcher(this, 'toolCategories' in g ? g.toolCategories : undefined) ?? g.matcher;
78
+ const entry = {
79
+ event: cursorEvent,
80
+ command: `${guardScriptPath} ${g.name}`,
81
+ timeout: 10000,
82
+ description: `SLOPE: ${g.description}`,
83
+ };
84
+ if (matcher)
85
+ entry.matcher = matcher;
86
+ hooks.push(entry);
87
+ }
88
+ return { hooks };
89
+ }
90
+ installGuards(cwd, guards) {
91
+ const hooksDir = join(cwd, '.cursor', 'hooks');
92
+ mkdirSync(hooksDir, { recursive: true });
93
+ // Create the guard dispatcher script
94
+ const dispatcherPath = join(hooksDir, 'slope-guard.sh');
95
+ if (!existsSync(dispatcherPath)) {
96
+ const script = [
97
+ '#!/usr/bin/env bash',
98
+ '# SLOPE guard dispatcher — routes hook events to slope guard handlers',
99
+ '# Auto-generated by slope hook add --level=full --harness=cursor',
100
+ '#',
101
+ '# Cursor passes JSON on stdin and reads JSON from stdout.',
102
+ '',
103
+ '# === SLOPE MANAGED (do not edit above this line) ===',
104
+ 'slope guard "$@"',
105
+ '# === SLOPE END ===',
106
+ '',
107
+ ].join('\n');
108
+ writeFileSync(dispatcherPath, script, { mode: 0o755 });
109
+ console.log(` Created ${dispatcherPath}`);
110
+ }
111
+ // Generate hooks config and merge into .cursor/hooks.json
112
+ // Command paths are relative to the project root (cwd), not the hooks.json file
113
+ const guardScript = '.cursor/hooks/slope-guard.sh';
114
+ const hooksConfig = this.generateHooksConfig(guards, guardScript);
115
+ const configPath = join(cwd, '.cursor', 'hooks.json');
116
+ let existing = { hooks: [] };
117
+ if (existsSync(configPath)) {
118
+ try {
119
+ existing = JSON.parse(readFileSync(configPath, 'utf8'));
120
+ if (!Array.isArray(existing.hooks))
121
+ existing.hooks = [];
122
+ }
123
+ catch { /* start fresh */ }
124
+ }
125
+ // Merge — avoid duplicates by checking command
126
+ for (const entry of hooksConfig.hooks) {
127
+ const isDuplicate = existing.hooks.some(e => e.command === entry.command && e.event === entry.event);
128
+ if (!isDuplicate) {
129
+ existing.hooks.push(entry);
130
+ }
131
+ }
132
+ writeFileSync(configPath, JSON.stringify(existing, null, 2) + '\n');
133
+ console.log(` Updated ${configPath} with guard hooks`);
134
+ }
135
+ detect(cwd) {
136
+ return existsSync(join(cwd, '.cursor'));
137
+ }
138
+ }
139
+ /** Singleton instance */
140
+ export const cursorAdapter = new CursorAdapter();
141
+ // Auto-register on import
142
+ registerAdapter(cursorAdapter);
143
+ //# sourceMappingURL=cursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../../src/core/adapters/cursor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { HarnessAdapter, ToolNameMap } from '../harness.js';
2
+ import type { GuardResult, AnyGuardDefinition } from '../guard.js';
3
+ /** Guard manifest entry written to guards-manifest.json */
4
+ export interface GuardManifestEntry {
5
+ name: string;
6
+ description: string;
7
+ hookEvent: string;
8
+ matcher?: string;
9
+ level: string;
10
+ command: string;
11
+ }
12
+ /** Generic adapter — works with any harness via shell scripts and JSON manifest. */
13
+ export declare class GenericAdapter implements HarnessAdapter {
14
+ readonly id: "generic";
15
+ readonly displayName = "Generic (Shell)";
16
+ readonly toolNames: ToolNameMap;
17
+ readonly supportedEvents: Set<string>;
18
+ readonly supportsContextInjection = false;
19
+ hooksConfigPath(_cwd: string): string | null;
20
+ formatPreToolOutput(result: GuardResult): unknown;
21
+ formatPostToolOutput(result: GuardResult): unknown;
22
+ formatStopOutput(result: GuardResult): unknown;
23
+ generateHooksConfig(guards: AnyGuardDefinition[], guardScriptPath: string): GuardManifestEntry[];
24
+ installGuards(cwd: string, guards: AnyGuardDefinition[]): void;
25
+ detect(_cwd: string): boolean;
26
+ }
27
+ /** Singleton instance */
28
+ export declare const genericAdapter: GenericAdapter;
29
+ //# sourceMappingURL=generic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generic.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/generic.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjE,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAanE,2DAA2D;AAC3D,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,oFAAoF;AACpF,qBAAa,cAAe,YAAW,cAAc;IACnD,QAAQ,CAAC,EAAE,EAAG,SAAS,CAAU;IACjC,QAAQ,CAAC,WAAW,qBAAqB;IACzC,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAiB;IAChD,QAAQ,CAAC,eAAe,cAAkD;IAC1E,QAAQ,CAAC,wBAAwB,SAAS;IAE1C,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAI5C,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO;IAYjD,oBAAoB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO;IAQlD,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO;IAO9C,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,EAAE,EAAE,eAAe,EAAE,MAAM,GAAG,kBAAkB,EAAE;IAehG,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,GAAG,IAAI;IAyE9D,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAI9B;AAED,yBAAyB;AACzB,eAAO,MAAM,cAAc,gBAAuB,CAAC"}