@intutic/sync-daemon 1.10.0 → 2.0.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.
Files changed (200) hide show
  1. package/README.md +2 -2
  2. package/dist/agentReporter.d.ts +205 -0
  3. package/dist/agentReporter.d.ts.map +1 -0
  4. package/dist/agentReporter.js +394 -0
  5. package/dist/agentReporter.js.map +1 -0
  6. package/dist/configReader.d.ts +39 -2
  7. package/dist/configReader.d.ts.map +1 -1
  8. package/dist/configReader.js +56 -2
  9. package/dist/configReader.js.map +1 -1
  10. package/dist/configWriter.d.ts +51 -1
  11. package/dist/configWriter.d.ts.map +1 -1
  12. package/dist/configWriter.js +490 -63
  13. package/dist/configWriter.js.map +1 -1
  14. package/dist/harness/antigravityHooks.d.ts.map +1 -1
  15. package/dist/harness/antigravityHooks.js +33 -55
  16. package/dist/harness/antigravityHooks.js.map +1 -1
  17. package/dist/harness/claudeCodeHooks.d.ts +47 -13
  18. package/dist/harness/claudeCodeHooks.d.ts.map +1 -1
  19. package/dist/harness/claudeCodeHooks.js +316 -54
  20. package/dist/harness/claudeCodeHooks.js.map +1 -1
  21. package/dist/harness/claudeDesktopHooks.d.ts.map +1 -1
  22. package/dist/harness/claudeDesktopHooks.js +35 -48
  23. package/dist/harness/claudeDesktopHooks.js.map +1 -1
  24. package/dist/harness/clineHooks.d.ts.map +1 -1
  25. package/dist/harness/clineHooks.js +42 -34
  26. package/dist/harness/clineHooks.js.map +1 -1
  27. package/dist/harness/codexHooks.d.ts +36 -0
  28. package/dist/harness/codexHooks.d.ts.map +1 -0
  29. package/dist/harness/codexHooks.js +227 -0
  30. package/dist/harness/codexHooks.js.map +1 -0
  31. package/dist/harness/continueHooks.d.ts +45 -5
  32. package/dist/harness/continueHooks.d.ts.map +1 -1
  33. package/dist/harness/continueHooks.js +225 -5
  34. package/dist/harness/continueHooks.js.map +1 -1
  35. package/dist/harness/cursorHooks.d.ts +31 -0
  36. package/dist/harness/cursorHooks.d.ts.map +1 -1
  37. package/dist/harness/cursorHooks.js +78 -49
  38. package/dist/harness/cursorHooks.js.map +1 -1
  39. package/dist/harness/dshHooks.d.ts +198 -0
  40. package/dist/harness/dshHooks.d.ts.map +1 -0
  41. package/dist/harness/dshHooks.js +569 -0
  42. package/dist/harness/dshHooks.js.map +1 -0
  43. package/dist/harness/gateBody.d.ts +422 -0
  44. package/dist/harness/gateBody.d.ts.map +1 -0
  45. package/dist/harness/gateBody.js +1816 -0
  46. package/dist/harness/gateBody.js.map +1 -0
  47. package/dist/harness/gateKind.d.ts +164 -0
  48. package/dist/harness/gateKind.d.ts.map +1 -0
  49. package/dist/harness/gateKind.js +143 -0
  50. package/dist/harness/gateKind.js.map +1 -0
  51. package/dist/harness/githubCopilotHooks.d.ts +54 -0
  52. package/dist/harness/githubCopilotHooks.d.ts.map +1 -0
  53. package/dist/harness/githubCopilotHooks.js +218 -0
  54. package/dist/harness/githubCopilotHooks.js.map +1 -0
  55. package/dist/harness/gooseHooks.d.ts.map +1 -1
  56. package/dist/harness/gooseHooks.js +67 -37
  57. package/dist/harness/gooseHooks.js.map +1 -1
  58. package/dist/harness/grokHooks.d.ts +77 -0
  59. package/dist/harness/grokHooks.d.ts.map +1 -0
  60. package/dist/harness/grokHooks.js +350 -0
  61. package/dist/harness/grokHooks.js.map +1 -0
  62. package/dist/harness/hermesHooks.d.ts.map +1 -1
  63. package/dist/harness/hermesHooks.js +26 -55
  64. package/dist/harness/hermesHooks.js.map +1 -1
  65. package/dist/harness/holdRedaction.d.ts +69 -0
  66. package/dist/harness/holdRedaction.d.ts.map +1 -0
  67. package/dist/harness/holdRedaction.js +211 -0
  68. package/dist/harness/holdRedaction.js.map +1 -0
  69. package/dist/harness/jetbrainsXmlConfig.d.ts +51 -0
  70. package/dist/harness/jetbrainsXmlConfig.d.ts.map +1 -0
  71. package/dist/harness/jetbrainsXmlConfig.js +151 -0
  72. package/dist/harness/jetbrainsXmlConfig.js.map +1 -0
  73. package/dist/harness/mcpAutoWrite.d.ts +100 -3
  74. package/dist/harness/mcpAutoWrite.d.ts.map +1 -1
  75. package/dist/harness/mcpAutoWrite.js +712 -90
  76. package/dist/harness/mcpAutoWrite.js.map +1 -1
  77. package/dist/harness/museHooks.d.ts +53 -0
  78. package/dist/harness/museHooks.d.ts.map +1 -0
  79. package/dist/harness/museHooks.js +273 -0
  80. package/dist/harness/museHooks.js.map +1 -0
  81. package/dist/harness/n8nHooks.d.ts +25 -9
  82. package/dist/harness/n8nHooks.d.ts.map +1 -1
  83. package/dist/harness/n8nHooks.js +174 -9
  84. package/dist/harness/n8nHooks.js.map +1 -1
  85. package/dist/harness/openCodeHooks.d.ts +93 -0
  86. package/dist/harness/openCodeHooks.d.ts.map +1 -0
  87. package/dist/harness/openCodeHooks.js +248 -0
  88. package/dist/harness/openCodeHooks.js.map +1 -0
  89. package/dist/harness/openWebuiHooks.d.ts.map +1 -1
  90. package/dist/harness/openWebuiHooks.js +56 -11
  91. package/dist/harness/openWebuiHooks.js.map +1 -1
  92. package/dist/harness/openclawHooks.d.ts.map +1 -1
  93. package/dist/harness/openclawHooks.js +30 -54
  94. package/dist/harness/openclawHooks.js.map +1 -1
  95. package/dist/harness/openhandsHooks.d.ts.map +1 -1
  96. package/dist/harness/openhandsHooks.js +35 -41
  97. package/dist/harness/openhandsHooks.js.map +1 -1
  98. package/dist/harness/piHooks.d.ts.map +1 -1
  99. package/dist/harness/piHooks.js +31 -58
  100. package/dist/harness/piHooks.js.map +1 -1
  101. package/dist/harness/protectedPaths.d.ts +353 -0
  102. package/dist/harness/protectedPaths.d.ts.map +1 -0
  103. package/dist/harness/protectedPaths.js +805 -0
  104. package/dist/harness/protectedPaths.js.map +1 -0
  105. package/dist/harness/rooCodeHooks.d.ts.map +1 -1
  106. package/dist/harness/rooCodeHooks.js +34 -48
  107. package/dist/harness/rooCodeHooks.js.map +1 -1
  108. package/dist/harness/windsurfHooks.d.ts +72 -0
  109. package/dist/harness/windsurfHooks.d.ts.map +1 -1
  110. package/dist/harness/windsurfHooks.js +172 -58
  111. package/dist/harness/windsurfHooks.js.map +1 -1
  112. package/dist/harness/windsurfJetBrainsProxy.d.ts +78 -0
  113. package/dist/harness/windsurfJetBrainsProxy.d.ts.map +1 -0
  114. package/dist/harness/windsurfJetBrainsProxy.js +159 -0
  115. package/dist/harness/windsurfJetBrainsProxy.js.map +1 -0
  116. package/dist/hashReporter.js +1 -1
  117. package/dist/hashReporter.js.map +1 -1
  118. package/dist/index.d.ts +12 -6
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +14 -6
  121. package/dist/index.js.map +1 -1
  122. package/dist/integrityStore.d.ts +0 -8
  123. package/dist/integrityStore.d.ts.map +1 -1
  124. package/dist/integrityStore.js +6 -29
  125. package/dist/integrityStore.js.map +1 -1
  126. package/dist/lib/approvedBypasses.d.ts +76 -0
  127. package/dist/lib/approvedBypasses.d.ts.map +1 -0
  128. package/dist/lib/approvedBypasses.js +140 -0
  129. package/dist/lib/approvedBypasses.js.map +1 -0
  130. package/dist/lib/complianceProbes.d.ts.map +1 -1
  131. package/dist/lib/complianceProbes.js +5 -0
  132. package/dist/lib/complianceProbes.js.map +1 -1
  133. package/dist/lib/decisionsDigest.d.ts +99 -0
  134. package/dist/lib/decisionsDigest.d.ts.map +1 -0
  135. package/dist/lib/decisionsDigest.js +199 -0
  136. package/dist/lib/decisionsDigest.js.map +1 -0
  137. package/dist/lib/egressPolicy.d.ts +69 -0
  138. package/dist/lib/egressPolicy.d.ts.map +1 -0
  139. package/dist/lib/egressPolicy.js +126 -0
  140. package/dist/lib/egressPolicy.js.map +1 -0
  141. package/dist/lib/gitWorktrees.d.ts +140 -0
  142. package/dist/lib/gitWorktrees.d.ts.map +1 -0
  143. package/dist/lib/gitWorktrees.js +191 -0
  144. package/dist/lib/gitWorktrees.js.map +1 -0
  145. package/dist/lib/policySnapshot.d.ts +224 -0
  146. package/dist/lib/policySnapshot.d.ts.map +1 -0
  147. package/dist/lib/policySnapshot.js +637 -0
  148. package/dist/lib/policySnapshot.js.map +1 -0
  149. package/dist/lib/processPoller.d.ts +44 -0
  150. package/dist/lib/processPoller.d.ts.map +1 -1
  151. package/dist/lib/processPoller.js +176 -1
  152. package/dist/lib/processPoller.js.map +1 -1
  153. package/dist/lib/runtimeEnv.d.ts +8 -0
  154. package/dist/lib/runtimeEnv.d.ts.map +1 -1
  155. package/dist/lib/runtimeEnv.js +3 -0
  156. package/dist/lib/runtimeEnv.js.map +1 -1
  157. package/dist/localTrajectoryHeuristics.d.ts +51 -0
  158. package/dist/localTrajectoryHeuristics.d.ts.map +1 -0
  159. package/dist/localTrajectoryHeuristics.js +90 -0
  160. package/dist/localTrajectoryHeuristics.js.map +1 -0
  161. package/dist/sessionReporter.d.ts +70 -0
  162. package/dist/sessionReporter.d.ts.map +1 -0
  163. package/dist/sessionReporter.js +140 -0
  164. package/dist/sessionReporter.js.map +1 -0
  165. package/dist/skillWriter.d.ts +1 -1
  166. package/dist/skillWriter.d.ts.map +1 -1
  167. package/dist/skillWriter.js +5 -2
  168. package/dist/skillWriter.js.map +1 -1
  169. package/dist/syncLoop.d.ts +105 -3
  170. package/dist/syncLoop.d.ts.map +1 -1
  171. package/dist/syncLoop.js +397 -65
  172. package/dist/syncLoop.js.map +1 -1
  173. package/dist/trajectoryMonitor.d.ts +2 -0
  174. package/dist/trajectoryMonitor.d.ts.map +1 -1
  175. package/dist/trajectoryMonitor.js +57 -0
  176. package/dist/trajectoryMonitor.js.map +1 -1
  177. package/dist/watcher/driftWatcher.d.ts.map +1 -1
  178. package/dist/watcher/driftWatcher.js +12 -3
  179. package/dist/watcher/driftWatcher.js.map +1 -1
  180. package/dist/watcher/settingsGuard.d.ts +23 -0
  181. package/dist/watcher/settingsGuard.d.ts.map +1 -1
  182. package/dist/watcher/settingsGuard.js +202 -17
  183. package/dist/watcher/settingsGuard.js.map +1 -1
  184. package/package.json +37 -6
  185. package/dist/brainIndexer.d.ts +0 -51
  186. package/dist/brainIndexer.d.ts.map +0 -1
  187. package/dist/brainIndexer.js +0 -148
  188. package/dist/brainIndexer.js.map +0 -1
  189. package/dist/harness/cursorHooksJson.d.ts +0 -29
  190. package/dist/harness/cursorHooksJson.d.ts.map +0 -1
  191. package/dist/harness/cursorHooksJson.js +0 -130
  192. package/dist/harness/cursorHooksJson.js.map +0 -1
  193. package/dist/harness/gooseHooksWriter.d.ts +0 -27
  194. package/dist/harness/gooseHooksWriter.d.ts.map +0 -1
  195. package/dist/harness/gooseHooksWriter.js +0 -147
  196. package/dist/harness/gooseHooksWriter.js.map +0 -1
  197. package/dist/harness/openhandsHooksWriter.d.ts +0 -23
  198. package/dist/harness/openhandsHooksWriter.d.ts.map +0 -1
  199. package/dist/harness/openhandsHooksWriter.js +0 -146
  200. package/dist/harness/openhandsHooksWriter.js.map +0 -1
@@ -1,9 +1,44 @@
1
1
  /**
2
- * continueHooks.ts — Continue.dev governance via proxy routing.
2
+ * continueHooks.ts — Continue governance: proxy routing + CLI PreToolUse gate.
3
3
  *
4
- * Continue.dev has no native hook system. Governance is applied by routing
5
- * all model API calls through the Intutic proxy: each model's `apiBase`
6
- * field is set to `proxyUrl` in `~/.continue/config.json`.
4
+ * Two mechanisms, for two different Continue surfaces:
5
+ *
6
+ * 1. **Proxy routing** (both surfaces): each model's `apiBase` field in
7
+ * `~/.continue/config.json` is set to `proxyUrl`, so LLM egress traverses
8
+ * the Intutic proxy.
9
+ *
10
+ * 2. **PreToolUse gate** (Continue **CLI `cn` only** — the IDE extension has
11
+ * no hook system): the CLI executes PreToolUse hooks registered in
12
+ * `~/.continue/settings.json` (user) and `<repo>/.continue/settings.json`
13
+ * (project), with a Claude-Code-compatible stdin contract —
14
+ * {tool_name, tool_input, tool_use_id} — refused via exit code 2 (or a
15
+ * stdout `{"permissionDecision":"deny"}`; exit 2 is used here, the contract
16
+ * every other exit-2 harness shares).
17
+ *
18
+ * **LIVE-VERIFIED LIMITS (cn 1.5.47, 2026-08-10), do not oversell this
19
+ * gate:**
20
+ * - **Headless `-p`/`--print` mode does not execute PreToolUse hooks at
21
+ * all.** Verified against a real install with a bare marker hook: the
22
+ * terminal tool ran, the marker never fired, with the hook registered in
23
+ * every path the bundle's own search list names. The hooks engine (and
24
+ * this exact search list, including `.claude/settings.json`) is present
25
+ * in the shipped bundle — headless mode simply bypasses it. Interactive
26
+ * TUI sessions are the mode this registration targets; a headless `cn
27
+ * -p` run is governed by the proxy layer only.
28
+ * - **cn's hook engine fails OPEN on hook errors by its own design** —
29
+ * the bundled dispatcher catches a failed hook event and returns
30
+ * `{blocked: false}`. Our gate's own crash posture (fail-closed exit 2)
31
+ * cannot override the harness swallowing the failure; that is cn's
32
+ * contract, recorded here so the security matrix can say it honestly.
33
+ *
34
+ * **Overlap, stated so nobody "fixes" it:** the Continue CLI ALSO reads
35
+ * `.claude/settings.json`, so on a machine where claude-code is governed,
36
+ * `cn` may already run the claude-code gate by accident. This writer makes
37
+ * that deliberate by registering in Continue's own settings files — the
38
+ * dedicated registration is still correct because a user who runs continue
39
+ * but not claude-code has no `.claude/settings.json` and would otherwise
40
+ * get no gate at all. Double registration is harmless: both gates evaluate
41
+ * the same rules, and an allow/allow or block/block pair is idempotent.
7
42
  *
8
43
  * JSONC handling: ~/.continue/config.json allows `// comments`. We strip
9
44
  * single-line comments with a regex before parsing, then write back as
@@ -15,13 +50,18 @@
15
50
  * @module
16
51
  */
17
52
  /**
18
- * Configure Continue.dev to route all model API calls through the Intutic proxy.
53
+ * Configure Continue: proxy routing for both surfaces, and the CLI's
54
+ * PreToolUse gate.
19
55
  *
20
56
  * 1. Reads `~/.continue/config.json` (JSONC — strips // comments before parsing).
21
57
  * 2. Sets `apiBase = proxyUrl` on each model that doesn't already use it.
22
58
  * 3. Adds a `customInstructions` governance notice.
23
59
  * 4. Writes the merged result back atomically.
24
60
  * 5. Writes `.intutic/env/continue.env` with the proxy URL.
61
+ * 6. Writes the gate script `.intutic/hooks/continue-check.js` and registers
62
+ * it in `~/.continue/settings.json` and `<root>/.continue/settings.json`
63
+ * (Continue CLI PreToolUse — see the module header for the
64
+ * `.claude/settings.json` overlap).
25
65
  *
26
66
  * Safe to call repeatedly — uses atomic rename (`.intutic-tmp` → final path).
27
67
  *
@@ -1 +1 @@
1
- {"version":3,"file":"continueHooks.d.ts","sourceRoot":"","sources":["../../src/harness/continueHooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAmCH;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kBAAkB,CACtC,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,WAAW,SAAK,GACf,OAAO,CAAC,IAAI,CAAC,CAqFf"}
1
+ {"version":3,"file":"continueHooks.d.ts","sourceRoot":"","sources":["../../src/harness/continueHooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AA2MH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,kBAAkB,CACtC,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,WAAW,SAAK,GACf,OAAO,CAAC,IAAI,CAAC,CAoHf"}
@@ -1,9 +1,44 @@
1
1
  /**
2
- * continueHooks.ts — Continue.dev governance via proxy routing.
2
+ * continueHooks.ts — Continue governance: proxy routing + CLI PreToolUse gate.
3
3
  *
4
- * Continue.dev has no native hook system. Governance is applied by routing
5
- * all model API calls through the Intutic proxy: each model's `apiBase`
6
- * field is set to `proxyUrl` in `~/.continue/config.json`.
4
+ * Two mechanisms, for two different Continue surfaces:
5
+ *
6
+ * 1. **Proxy routing** (both surfaces): each model's `apiBase` field in
7
+ * `~/.continue/config.json` is set to `proxyUrl`, so LLM egress traverses
8
+ * the Intutic proxy.
9
+ *
10
+ * 2. **PreToolUse gate** (Continue **CLI `cn` only** — the IDE extension has
11
+ * no hook system): the CLI executes PreToolUse hooks registered in
12
+ * `~/.continue/settings.json` (user) and `<repo>/.continue/settings.json`
13
+ * (project), with a Claude-Code-compatible stdin contract —
14
+ * {tool_name, tool_input, tool_use_id} — refused via exit code 2 (or a
15
+ * stdout `{"permissionDecision":"deny"}`; exit 2 is used here, the contract
16
+ * every other exit-2 harness shares).
17
+ *
18
+ * **LIVE-VERIFIED LIMITS (cn 1.5.47, 2026-08-10), do not oversell this
19
+ * gate:**
20
+ * - **Headless `-p`/`--print` mode does not execute PreToolUse hooks at
21
+ * all.** Verified against a real install with a bare marker hook: the
22
+ * terminal tool ran, the marker never fired, with the hook registered in
23
+ * every path the bundle's own search list names. The hooks engine (and
24
+ * this exact search list, including `.claude/settings.json`) is present
25
+ * in the shipped bundle — headless mode simply bypasses it. Interactive
26
+ * TUI sessions are the mode this registration targets; a headless `cn
27
+ * -p` run is governed by the proxy layer only.
28
+ * - **cn's hook engine fails OPEN on hook errors by its own design** —
29
+ * the bundled dispatcher catches a failed hook event and returns
30
+ * `{blocked: false}`. Our gate's own crash posture (fail-closed exit 2)
31
+ * cannot override the harness swallowing the failure; that is cn's
32
+ * contract, recorded here so the security matrix can say it honestly.
33
+ *
34
+ * **Overlap, stated so nobody "fixes" it:** the Continue CLI ALSO reads
35
+ * `.claude/settings.json`, so on a machine where claude-code is governed,
36
+ * `cn` may already run the claude-code gate by accident. This writer makes
37
+ * that deliberate by registering in Continue's own settings files — the
38
+ * dedicated registration is still correct because a user who runs continue
39
+ * but not claude-code has no `.claude/settings.json` and would otherwise
40
+ * get no gate at all. Double registration is harmless: both gates evaluate
41
+ * the same rules, and an allow/allow or block/block pair is idempotent.
7
42
  *
8
43
  * JSONC handling: ~/.continue/config.json allows `// comments`. We strip
9
44
  * single-line comments with a regex before parsing, then write back as
@@ -19,6 +54,7 @@ import * as path from 'node:path';
19
54
  import * as os from 'node:os';
20
55
  import { createLogger } from '@intutic/logger';
21
56
  import { newIso } from '@intutic/id';
57
+ import { emitJsGate, emitJsFailClosedPrelude } from './gateBody.js';
22
58
  const log = createLogger('sync-continue-hooks');
23
59
  /** Default path to the Continue.dev global config file. */
24
60
  const CONTINUE_CONFIG_PATH = path.join(os.homedir(), '.continue', 'config.json');
@@ -39,15 +75,177 @@ function stripJsoncComments(raw) {
39
75
  // Simple approach: replace // up to end-of-line (acceptable for Continue config).
40
76
  return raw.replace(/\/\/[^\n]*/g, '');
41
77
  }
78
+ // ─── PreToolUse gate (Continue CLI `cn`) ──────────────────────────────────────
79
+ /**
80
+ * The pre-tool gate script — receives the Continue CLI's Claude-Code-compatible
81
+ * PreToolUse JSON on stdin, exits 0 to allow or 2 to block.
82
+ */
83
+ function buildHookScript(proxyUrl, workspaceRoot, workspaceId) {
84
+ const hookEventsLog = path.join(workspaceRoot, '.intutic', 'events', 'hook-events.jsonl');
85
+ return `#!/usr/bin/env node
86
+ /**
87
+ * Intutic Continue CLI governance gate.
88
+ * Auto-generated by intutic sync-daemon. DO NOT EDIT.
89
+ *
90
+ * Applies to the Continue CLI (cn) only — the IDE extension has no hook
91
+ * system. Note the CLI also reads .claude/settings.json, so a machine governed
92
+ * for claude-code may run that gate too; both evaluate the same rules.
93
+ *
94
+ * Proxy: ${proxyUrl}
95
+ * Generated: ${newIso()}
96
+ */
97
+ ${emitJsFailClosedPrelude({ harness: 'continue', contract: 'exit2' })}
98
+ const path = require('path');
99
+ const os = require('os');
100
+ const fs = require('fs');
101
+ const crypto = require('crypto');
102
+ const https = require('https');
103
+
104
+ // Runtime credentials
105
+ const _runtimeEnvPath = path.join(os.homedir(), '.intutic', 'env', 'runtime.env');
106
+ let _intuticHost = 'https://api.intutic.ai', _intuticKey = '', _intuticWsId = ${JSON.stringify(workspaceId)};
107
+ try {
108
+ fs.readFileSync(_runtimeEnvPath, 'utf-8').split('\\n').forEach(line => {
109
+ const eq = line.indexOf('='); if (eq < 0) return;
110
+ const k = line.slice(0, eq).trim(), v = line.slice(eq + 1).trim();
111
+ if (k === 'INTUTIC_HOST' && v) _intuticHost = v;
112
+ if (k === 'INTUTIC_API_KEY' && v) _intuticKey = v;
113
+ if (k === 'INTUTIC_WORKSPACE_ID' && v) _intuticWsId = v;
114
+ });
115
+ } catch {}
116
+
117
+ ${emitJsGate({ harness: 'continue', contract: 'exit2' })}
118
+
119
+ let _intuticSessionId = '';
120
+ function logEvent(verdict, toolName, reason) {
121
+ try {
122
+ const ts = new Date().toISOString();
123
+ const incidentId = crypto.createHash('sha1').update(ts + toolName + _intuticWsId).digest('hex').slice(0, 16);
124
+ const entry = JSON.stringify({
125
+ // Passed through, not collapsed to two values: the advisory tier emits
126
+ // 'tool_flagged', and a ternary here silently recorded it as an allow.
127
+ event: verdict,
128
+ toolName, reason: reason || '',
129
+ workspaceId: _intuticWsId,
130
+ harnessType: 'continue',
131
+ timestamp: ts,
132
+ incidentId,
133
+ ...(_intuticSessionId ? { sessionId: _intuticSessionId } : {}),
134
+ }) + '\\n';
135
+ fs.appendFileSync(${JSON.stringify(hookEventsLog)}, entry, { flag: 'a' });
136
+ if (_intuticKey) {
137
+ try {
138
+ const body = JSON.stringify({ events: [JSON.parse(entry)] });
139
+ const urlObj = new URL('/api/v1/hook-events', _intuticHost);
140
+ const mod = urlObj.protocol === 'https:' ? https : require('http');
141
+ const req = mod.request({ hostname: urlObj.hostname, port: urlObj.port || 443, path: urlObj.pathname, method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body), 'Authorization': 'Bearer ' + _intuticKey } });
142
+ req.on('error', () => { /* fire-and-forget */ });
143
+ req.write(body); req.end();
144
+ } catch { /* never crash the hook */ }
145
+ }
146
+ } catch { /* never crash the hook */ }
147
+ }
148
+
149
+ let raw = '';
150
+ process.stdin.on('data', (c) => { raw += c; });
151
+ process.stdin.on('end', () => {
152
+ try {
153
+ const ctx = JSON.parse(raw);
154
+ _intuticSessionId = ctx.session_id || ctx.sessionId || '';
155
+ // Verified during the v5 audit: this writer did NOT have the envelope
156
+ // guard its Claude-Code-compatible contract implied it inherited — a
157
+ // payload with neither a tool name nor a tool_input defaulted to toolName
158
+ // 'tool' with empty fields, matched no rule, and was allowed. Refused now.
159
+ intuticGuardEnvelope(ctx, ['tool_name', 'toolName', 'tool_input', 'toolInput'], logEvent);
160
+ const input = ctx.tool_input || ctx.toolInput || {};
161
+ const toolName = ctx.tool_name || ctx.toolName || 'tool';
162
+
163
+ // Every spelling any harness uses, matching the bash extractor. A field
164
+ // name this list misses is a path guard that silently does not run — and
165
+ // the caller controls which spelling it sends.
166
+ const targetPath = input.path || input.file_path || input.filePath || input.file ||
167
+ input.target || input.notebook_path || '';
168
+ const command = input.command || input.cmd || input.script || '';
169
+
170
+ intuticGate(toolName, targetPath, command, logEvent, _intuticWsId, input);
171
+
172
+ // Allow
173
+ logEvent('tool_allowed', toolName, '');
174
+ process.exit(0);
175
+ } catch (err) {
176
+ // Fail CLOSED
177
+ const errMsg = String(err);
178
+ process.stderr.write('[Intutic Governance] Hook error (fail-closed): ' + errMsg + '\\n');
179
+ logEvent('tool_blocked', 'unknown', errMsg);
180
+ process.exit(2);
181
+ }
182
+ });
183
+ `;
184
+ }
185
+ /**
186
+ * Merge the Intutic PreToolUse entry into a Continue settings.json, preserving
187
+ * everything the user registered themselves.
188
+ *
189
+ * De-duplication is by command (any entry whose hooks all invoke this gate
190
+ * script is ours and is replaced) — the claudeDesktopHooks convention — so
191
+ * repeated syncs never stack duplicate entries.
192
+ */
193
+ async function mergeContinueSettings(settingsPath, hookScriptPath) {
194
+ let existing = {};
195
+ try {
196
+ existing = JSON.parse(stripJsoncComments(await fs.readFile(settingsPath, 'utf-8')));
197
+ }
198
+ catch {
199
+ // File doesn't exist or is malformed — start fresh
200
+ }
201
+ const existingHooks = existing.hooks ?? {};
202
+ const existingPreToolUse = Array.isArray(existingHooks.PreToolUse)
203
+ ? existingHooks.PreToolUse
204
+ : [];
205
+ const intuticCmd = `node "${hookScriptPath}"`;
206
+ const filtered = existingPreToolUse.filter((entry) => {
207
+ if (typeof entry !== 'object' || entry === null)
208
+ return true;
209
+ const inner = entry.hooks ?? [];
210
+ return !(inner.length > 0 &&
211
+ inner.every((h) => typeof h === 'object' && h !== null && h.command === intuticCmd));
212
+ });
213
+ const merged = {
214
+ ...existing,
215
+ _intutic_comment: 'Intutic governance PreToolUse hook (Continue CLI) — auto-managed entries only; your own hooks are preserved.',
216
+ _intutic_last_sync: newIso(),
217
+ hooks: {
218
+ ...existingHooks,
219
+ PreToolUse: [
220
+ ...filtered,
221
+ {
222
+ // One catch-all matcher rather than a tool list: the gate itself
223
+ // decides from the arguments, so a tool name nobody anticipated is
224
+ // still evaluated rather than silently unmatched.
225
+ matcher: '.*',
226
+ hooks: [{ type: 'command', command: intuticCmd }],
227
+ },
228
+ ],
229
+ },
230
+ };
231
+ const tmp = settingsPath + '.intutic-tmp';
232
+ await fs.writeFile(tmp, JSON.stringify(merged, null, 2) + '\n', 'utf-8');
233
+ await fs.rename(tmp, settingsPath);
234
+ }
42
235
  // ─── Main export ──────────────────────────────────────────────────────────────
43
236
  /**
44
- * Configure Continue.dev to route all model API calls through the Intutic proxy.
237
+ * Configure Continue: proxy routing for both surfaces, and the CLI's
238
+ * PreToolUse gate.
45
239
  *
46
240
  * 1. Reads `~/.continue/config.json` (JSONC — strips // comments before parsing).
47
241
  * 2. Sets `apiBase = proxyUrl` on each model that doesn't already use it.
48
242
  * 3. Adds a `customInstructions` governance notice.
49
243
  * 4. Writes the merged result back atomically.
50
244
  * 5. Writes `.intutic/env/continue.env` with the proxy URL.
245
+ * 6. Writes the gate script `.intutic/hooks/continue-check.js` and registers
246
+ * it in `~/.continue/settings.json` and `<root>/.continue/settings.json`
247
+ * (Continue CLI PreToolUse — see the module header for the
248
+ * `.claude/settings.json` overlap).
51
249
  *
52
250
  * Safe to call repeatedly — uses atomic rename (`.intutic-tmp` → final path).
53
251
  *
@@ -120,5 +318,27 @@ export async function writeContinueHooks(workspaceRoot, proxyUrl, workspaceId =
120
318
  await fs.writeFile(tmpEnv, envContent, 'utf-8');
121
319
  await fs.rename(tmpEnv, envFilePath);
122
320
  log.info({ action: 'continue_env_written', path: envFilePath }, 'Continue.dev env snippet written');
321
+ // ── 7. PreToolUse gate for the Continue CLI (cn) ──────────────────────────
322
+ const hookScriptDir = path.join(workspaceRoot, '.intutic', 'hooks');
323
+ await fs.mkdir(hookScriptDir, { recursive: true });
324
+ await fs.mkdir(path.join(workspaceRoot, '.intutic', 'events'), { recursive: true });
325
+ // Named after its writer — see the note in claudeCodeHooks.ts about two
326
+ // writers overwriting one `pre-tool-check.js`.
327
+ const hookScriptPath = path.join(hookScriptDir, 'continue-check.js');
328
+ const tmpScript = hookScriptPath + '.intutic-tmp';
329
+ await fs.writeFile(tmpScript, buildHookScript(proxyUrl, workspaceRoot, workspaceId), 'utf-8');
330
+ await fs.rename(tmpScript, hookScriptPath);
331
+ await fs.chmod(hookScriptPath, 0o755);
332
+ // Project-level: <root>/.continue/settings.json
333
+ const projectContinueDir = path.join(workspaceRoot, '.continue');
334
+ await fs.mkdir(projectContinueDir, { recursive: true });
335
+ await mergeContinueSettings(path.join(projectContinueDir, 'settings.json'), hookScriptPath);
336
+ // User-level: ~/.continue/settings.json. homedir() read at call time (not the
337
+ // module-scope constant above) so tests that move HOME before invoking are
338
+ // honoured — see the gooseHooks note in generatedShellIntegrity.test.ts.
339
+ const userContinueDir = path.join(os.homedir(), '.continue');
340
+ await fs.mkdir(userContinueDir, { recursive: true });
341
+ await mergeContinueSettings(path.join(userContinueDir, 'settings.json'), hookScriptPath);
342
+ log.info({ action: 'continue_gate_written', path: hookScriptPath }, 'Continue CLI PreToolUse gate written and registered (project + user settings.json)');
123
343
  }
124
344
  //# sourceMappingURL=continueHooks.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"continueHooks.js","sourceRoot":"","sources":["../../src/harness/continueHooks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"continueHooks.js","sourceRoot":"","sources":["../../src/harness/continueHooks.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,37 @@
14
14
  *
15
15
  * @module
16
16
  */
17
+ /**
18
+ * Where system-level hooks.json lives for a given platform. Exported (not
19
+ * just inlined in `writeCursorHooks` below) so `mdmManifest.ts` can target
20
+ * the SAME path this file actually writes to — otherwise the MDM manifest's
21
+ * `target_path` and this file's real write path are two hand-typed copies
22
+ * of the same fact, which is exactly how they drifted before (see the
23
+ * `hookScriptPath` note below).
24
+ */
25
+ export declare function systemHooksDirFor(platform: NodeJS.Platform): string;
26
+ /**
27
+ * Build a Cursor hooks.json config object.
28
+ *
29
+ * Exported so `enterprise install` (`tools/cli/src/lib/mdmManifest.ts`) can
30
+ * populate its generated MDM hooks manifest from the SAME shape this file
31
+ * writes, rather than a hand-retyped literal — which is exactly how that
32
+ * manifest drifted before (it named `pre-tool-check.js`, this file's real
33
+ * script is `cursor-check.js`; see the note in `writeCursorHooks` below).
34
+ *
35
+ * @param hookScriptPath - Absolute path to the pre-tool-check script.
36
+ */
37
+ export declare function buildHooksConfig(hookScriptPath: string): {
38
+ _comment: string;
39
+ _lastSync: string;
40
+ failClosed: boolean;
41
+ hooks: {
42
+ [k: string]: {
43
+ command: string;
44
+ failClosed: boolean;
45
+ };
46
+ };
47
+ };
17
48
  /**
18
49
  * Write Cursor hooks at user-level and project-level.
19
50
  * System-level (/etc/cursor) is handled by the corporate policy installer.
@@ -1 +1 @@
1
- {"version":3,"file":"cursorHooks.d.ts","sourceRoot":"","sources":["../../src/harness/cursorHooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAqKH;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,WAAW,SAAK,EAChB,gBAAgB,UAAQ,GACvB,OAAO,CAAC,IAAI,CAAC,CAwCf"}
1
+ {"version":3,"file":"cursorHooks.d.ts","sourceRoot":"","sources":["../../src/harness/cursorHooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAkBH;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,GAAG,MAAM,CAEnE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,MAAM;;;;;;;;;;EAetD;AAoID;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,WAAW,SAAK,EAChB,gBAAgB,UAAQ,GACvB,OAAO,CAAC,IAAI,CAAC,CA8Cf"}
@@ -19,6 +19,7 @@ import * as path from 'node:path';
19
19
  import * as os from 'node:os';
20
20
  import { createLogger } from '@intutic/logger';
21
21
  import { newIso } from '@intutic/id';
22
+ import { emitJsGate, emitJsFailClosedPrelude } from './gateBody.js';
22
23
  const log = createLogger('sync-cursor-hooks');
23
24
  /** Hook events Cursor fires before execution. */
24
25
  const HOOK_EVENTS = [
@@ -26,12 +27,29 @@ const HOOK_EVENTS = [
26
27
  'beforeMCPExecution',
27
28
  'beforeFileEdit',
28
29
  ];
30
+ /**
31
+ * Where system-level hooks.json lives for a given platform. Exported (not
32
+ * just inlined in `writeCursorHooks` below) so `mdmManifest.ts` can target
33
+ * the SAME path this file actually writes to — otherwise the MDM manifest's
34
+ * `target_path` and this file's real write path are two hand-typed copies
35
+ * of the same fact, which is exactly how they drifted before (see the
36
+ * `hookScriptPath` note below).
37
+ */
38
+ export function systemHooksDirFor(platform) {
39
+ return platform === 'darwin' ? '/Library/Application Support/Cursor' : '/etc/cursor';
40
+ }
29
41
  /**
30
42
  * Build a Cursor hooks.json config object.
31
43
  *
44
+ * Exported so `enterprise install` (`tools/cli/src/lib/mdmManifest.ts`) can
45
+ * populate its generated MDM hooks manifest from the SAME shape this file
46
+ * writes, rather than a hand-retyped literal — which is exactly how that
47
+ * manifest drifted before (it named `pre-tool-check.js`, this file's real
48
+ * script is `cursor-check.js`; see the note in `writeCursorHooks` below).
49
+ *
32
50
  * @param hookScriptPath - Absolute path to the pre-tool-check script.
33
51
  */
34
- function buildHooksConfig(hookScriptPath) {
52
+ export function buildHooksConfig(hookScriptPath) {
35
53
  return {
36
54
  _comment: 'Intutic governance hooks — auto-generated. DO NOT EDIT.',
37
55
  _lastSync: newIso(),
@@ -45,20 +63,6 @@ function buildHooksConfig(hookScriptPath) {
45
63
  ])),
46
64
  };
47
65
  }
48
- /**
49
- * Governance-sensitive paths — mirrors the list in claudeCodeHooks.ts.
50
- * Any write/edit targeting these paths is blocked.
51
- */
52
- const PROTECTED_PATHS = [
53
- '.cursor/hooks.json',
54
- '.claude/settings.json',
55
- '.cline/hooks',
56
- '.intutic/hooks',
57
- '.intutic/integrity.json',
58
- '.codeium/windsurf/hooks.json',
59
- '.agents/plugins/intutic-governance',
60
- '.openhands/hooks.json',
61
- ];
62
66
  /**
63
67
  * The pre-tool-check.js script content — receives JSON context from Cursor
64
68
  * on stdin, exits 0 to allow or exits 2 to block.
@@ -72,6 +76,7 @@ function buildHookScript(proxyUrl, workspaceRoot, workspaceId) {
72
76
  * Proxy: ${proxyUrl}
73
77
  * Generated: ${newIso()}
74
78
  */
79
+ ${emitJsFailClosedPrelude({ harness: 'cursor', contract: 'exit2' })}
75
80
  const path = require('path');
76
81
  const os = require('os');
77
82
  const fs = require('fs');
@@ -91,19 +96,23 @@ try {
91
96
  });
92
97
  } catch {}
93
98
 
94
- const PROTECTED_PATHS = ${JSON.stringify(PROTECTED_PATHS)};
99
+ ${emitJsGate({ harness: 'cursor', contract: 'exit2' })}
95
100
 
101
+ let _intuticSessionId = '';
96
102
  function logEvent(verdict, toolName, reason) {
97
103
  try {
98
104
  const ts = new Date().toISOString();
99
105
  const incidentId = crypto.createHash('sha1').update(ts + toolName + _intuticWsId).digest('hex').slice(0, 16);
100
106
  const entry = JSON.stringify({
101
- event: verdict === 'blocked' ? 'tool_blocked' : 'tool_allowed',
107
+ // Passed through, not collapsed to two values: the advisory tier emits
108
+ // 'tool_flagged', and a ternary here silently recorded it as an allow.
109
+ event: verdict,
102
110
  toolName, reason: reason || '',
103
111
  workspaceId: _intuticWsId,
104
112
  harnessType: 'cursor',
105
113
  timestamp: ts,
106
114
  incidentId,
115
+ ...(_intuticSessionId ? { sessionId: _intuticSessionId } : {}),
107
116
  }) + '\\n';
108
117
  fs.appendFileSync(${JSON.stringify(hookEventsLog)}, entry, { flag: 'a' });
109
118
  if (_intuticKey) {
@@ -124,46 +133,60 @@ process.stdin.on('data', (c) => { raw += c; });
124
133
  process.stdin.on('end', () => {
125
134
  try {
126
135
  const ctx = JSON.parse(raw);
127
- const event = (ctx.event || '').toLowerCase();
136
+ _intuticSessionId = ctx.session_id || ctx.sessionId || ctx.conversation_id || ctx.conversationId || ctx.task_id || ctx.taskId || '';
137
+ // Cursor accepts FLAT payloads (fields at the top level, no tool_input
138
+ // wrapper — that is what the \`|| ctx\` fallback below reads), so the
139
+ // recognisable-envelope set is exactly the extractor's field set. Narrower
140
+ // would refuse real traffic; an envelope with none of these extracts to
141
+ // empty strings, matches no rule, and used to be allowed.
142
+ intuticGuardEnvelope(ctx, ['tool_name', 'toolName', 'tool_input', 'toolInput', 'input', 'event', 'hook_event_name',
143
+ 'command', 'cmd', 'script', 'path', 'file_path', 'filePath', 'file', 'target', 'notebook_path'], logEvent);
144
+ // Cursor's real field is \`hook_event_name\` (confirmed against Cursor's
145
+ // hooks documentation and a live \`beforeMCPExecution\` payload example
146
+ // from Cursor's own bug tracker, 2026-08 — \`ctx.event\` is not a field
147
+ // Cursor actually sends). Both are read: the correct name, and the one
148
+ // this file read alone before, so a future payload shape carrying \`event\`
149
+ // instead is not silently dropped.
150
+ const event = (ctx.hook_event_name || ctx.event || '').toLowerCase();
128
151
  const input = ctx.input || ctx.tool_input || ctx;
129
152
 
130
- // For file edits: check target path
131
- const targetPath = input.path || input.file || input.target || '';
132
- if (event === 'beforefileedit' || (input.path && input.path.length > 0)) {
133
- for (const p of PROTECTED_PATHS) {
134
- if (String(targetPath).includes(p)) {
135
- const reason = 'Attempt to modify governance-protected path "' + targetPath + '"';
136
- process.stderr.write('[Intutic Governance] BLOCKED: ' + reason + '\\n');
137
- logEvent('blocked', 'edit', reason);
138
- process.exit(2);
139
- }
140
- }
141
- }
153
+ // Every spelling any harness uses, matching the bash extractor. A field name
154
+ // this list misses is a path guard that silently does not run — and the
155
+ // caller controls which spelling it sends.
156
+ const targetPath = input.path || input.file_path || input.filePath || input.file ||
157
+ input.target || input.notebook_path || '';
158
+ const command = input.command || input.cmd || input.script || '';
159
+ let toolName = ctx.tool_name || ctx.toolName || event || 'tool';
142
160
 
143
- // Shell execution: scan command for dangerous patterns
144
- const command = input.command || input.cmd || '';
145
- const dangerPatterns = [
146
- /chmod\\s+[0-9]*7[0-9]*\\s+.*hooks/, // chmod on hook files
147
- /chattr\\s+-i\\s+/, // remove immutable flag
148
- /chflags\\s+nouchg/, // macOS remove uchg
149
- ];
150
- for (const pat of dangerPatterns) {
151
- if (pat.test(command)) {
152
- const reason = 'Command matches governance bypass pattern: "' + command + '"';
153
- process.stderr.write('[Intutic Governance] BLOCKED: ' + reason + '\\n');
154
- logEvent('blocked', 'bash', reason);
155
- process.exit(2);
156
- }
161
+ // M3: a \`beforeMCPExecution\` payload's \`tool_name\` is the BARE MCP tool
162
+ // name (e.g. "create_issue"), never "beforeMCPExecution" itself — but it
163
+ // was never composed into the \`mcp__<server>__<tool>\` shape every other
164
+ // harness's MCP tool name already takes, so an allowlist rule or a
165
+ // workspace's own \`mcp__github__.*\`-shaped SOP rule silently never fired
166
+ // on a Cursor MCP call. The server is a TOP-LEVEL sibling field —
167
+ // \`command\` for a stdio server, \`url\` for a remote one (per Cursor's
168
+ // hooks documentation; verified live payload: \`{tool_name, command,
169
+ // hook_event_name: "beforeMCPExecution", ...}\`) — composed in here, once,
170
+ // before anything reads \`toolName\`.
171
+ if (event === 'beforemcpexecution' && ctx.tool_name) {
172
+ const mcpServer = ctx.command || ctx.url || ctx.server_name || ctx.serverName;
173
+ if (mcpServer) toolName = 'mcp__' + mcpServer + '__' + ctx.tool_name;
157
174
  }
158
175
 
176
+ // The protected-path check used to be gated on \`event === 'beforefileedit'
177
+ // || input.path\`, so a shell command naming a protected path was only
178
+ // caught if it also carried a path argument. The shared gate tests the
179
+ // command and the target independently.
180
+ intuticGate(toolName, targetPath, command, logEvent, _intuticWsId, input);
181
+
159
182
  // Allow
160
- logEvent('allowed', event || 'tool', '');
183
+ logEvent('tool_allowed', toolName, '');
161
184
  process.exit(0);
162
185
  } catch (err) {
163
186
  // Fail CLOSED
164
187
  const errMsg = String(err);
165
188
  process.stderr.write('[Intutic Governance] Hook error (fail-closed): ' + errMsg + '\\n');
166
- logEvent('blocked', 'unknown', errMsg);
189
+ logEvent('tool_blocked', 'unknown', errMsg);
167
190
  process.exit(2);
168
191
  }
169
192
  });
@@ -183,7 +206,9 @@ export async function writeCursorHooks(workspaceRoot, proxyUrl, workspaceId = ''
183
206
  await fs.mkdir(hookScriptDir, { recursive: true });
184
207
  // Ensure hook events log directory exists
185
208
  await fs.mkdir(path.join(workspaceRoot, '.intutic', 'events'), { recursive: true });
186
- const hookScriptPath = path.join(hookScriptDir, 'pre-tool-check.js');
209
+ // Named after its writer — see the note in claudeCodeHooks.ts. Both emitted
210
+ // `pre-tool-check.js` here and silently overwrote each other.
211
+ const hookScriptPath = path.join(hookScriptDir, 'cursor-check.js');
187
212
  // Write the hook script
188
213
  const tmpScript = hookScriptPath + '.cursor-tmp';
189
214
  await fs.writeFile(tmpScript, buildHookScript(proxyUrl, workspaceRoot, workspaceId), 'utf-8');
@@ -200,9 +225,13 @@ export async function writeCursorHooks(workspaceRoot, proxyUrl, workspaceId = ''
200
225
  await fs.mkdir(userCursorDir, { recursive: true });
201
226
  await atomicWriteJson(path.join(userCursorDir, 'hooks.json'), config);
202
227
  log.info({ action: 'cursor_hooks_written', level: 'user', path: userCursorDir }, 'Cursor user-level hooks written');
203
- // 3. System-level: /etc/cursor/hooks.json (system administrator installation only)
228
+ // 3. System-level (system administrator installation only). macOS has no
229
+ // /etc/cursor convention Cursor itself reads — its own app-support
230
+ // directory is the closest machine-wide location. This branch was missing
231
+ // until now: the success log below always claimed "system-level hooks
232
+ // written" for a write that, on macOS, went to a path Cursor never reads.
204
233
  if (writeSystemLevel) {
205
- const systemCursorDir = '/etc/cursor';
234
+ const systemCursorDir = systemHooksDirFor(process.platform);
206
235
  try {
207
236
  await fs.mkdir(systemCursorDir, { recursive: true });
208
237
  await atomicWriteJson(path.join(systemCursorDir, 'hooks.json'), config);
@@ -1 +1 @@
1
- {"version":3,"file":"cursorHooks.js","sourceRoot":"","sources":["../../src/harness/cursorHooks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cursorHooks.js","sourceRoot":"","sources":["../../src/harness/cursorHooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAA;AACtC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AACjC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAA;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAEnE,MAAM,GAAG,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAA;AAE7C,iDAAiD;AACjD,MAAM,WAAW,GAAG;IAClB,sBAAsB;IACtB,oBAAoB;IACpB,gBAAgB;CACR,CAAA;AAEV;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAyB;IACzD,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,qCAAqC,CAAC,CAAC,CAAC,aAAa,CAAA;AACtF,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,cAAsB;IACrD,OAAO;QACL,QAAQ,EAAE,yDAAyD;QACnE,SAAS,EAAE,MAAM,EAAE;QACnB,UAAU,EAAE,IAAI;QAChB,KAAK,EAAE,MAAM,CAAC,WAAW,CACvB,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;YACzB,KAAK;YACL;gBACE,OAAO,EAAE,SAAS,cAAc,GAAG;gBACnC,UAAU,EAAE,IAAI;aACjB;SACF,CAAC,CACH;KACF,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,QAAgB,EAAE,aAAqB,EAAE,WAAmB;IACnF,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,mBAAmB,CAAC,CAAA;IACzF,OAAO;;;;YAIG,QAAQ;gBACJ,MAAM,EAAE;;EAEtB,uBAAuB,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;;;;;;;;;gFASa,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;;;;;;;;;;;EAWzG,UAAU,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;;;;;;;;;;;;;;;;;;wBAkB9B,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4EpD,CAAA;AACD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,aAAqB,EACrB,QAAgB,EAChB,WAAW,GAAG,EAAE,EAChB,gBAAgB,GAAG,KAAK;IAExB,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;IACnE,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAElD,0CAA0C;IAC1C,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAEnF,4EAA4E;IAC5E,8DAA8D;IAC9D,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAA;IAElE,wBAAwB;IACxB,MAAM,SAAS,GAAG,cAAc,GAAG,aAAa,CAAA;IAChD,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,eAAe,CAAC,QAAQ,EAAE,aAAa,EAAE,WAAW,CAAC,EAAE,OAAO,CAAC,CAAA;IAC7F,MAAM,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,cAAc,CAAC,CAAA;IAC1C,MAAM,EAAE,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAA;IAErC,MAAM,MAAM,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAA;IAE/C,uCAAuC;IACvC,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,CAAA;IAC5D,MAAM,EAAE,CAAC,KAAK,CAAC,gBAAgB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACrD,MAAM,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC,CAAA;IACxE,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,sBAAsB,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,oCAAoC,CAAC,CAAA;IAE5H,sCAAsC;IACtC,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAA;IACxD,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAClD,MAAM,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC,CAAA;IACrE,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,sBAAsB,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,iCAAiC,CAAC,CAAA;IAEnH,yEAAyE;IACzE,mEAAmE;IACnE,0EAA0E;IAC1E,sEAAsE;IACtE,0EAA0E;IAC1E,IAAI,gBAAgB,EAAE,CAAC;QACrB,MAAM,eAAe,GAAG,iBAAiB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC3D,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,KAAK,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;YACpD,MAAM,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC,CAAA;YACvE,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,sBAAsB,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,mCAAmC,CAAC,CAAA;QAC3H,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,4BAA4B,EAAE,GAAG,EAAE,EAAE,mDAAmD,CAAC,CAAA;QAC/G,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,QAAgB,EAAE,IAAa;IAC5D,MAAM,GAAG,GAAG,QAAQ,GAAG,cAAc,CAAA;IACrC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAA;IACtE,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;AAChC,CAAC"}