harness-engineering-agent 0.1.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 (327) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +191 -0
  3. package/dist/config/config-defaults.d.ts +32 -0
  4. package/dist/config/config-defaults.d.ts.map +1 -0
  5. package/dist/config/config-defaults.js +32 -0
  6. package/dist/config/config-defaults.js.map +1 -0
  7. package/dist/config/config-errors.d.ts +7 -0
  8. package/dist/config/config-errors.d.ts.map +1 -0
  9. package/dist/config/config-errors.js +11 -0
  10. package/dist/config/config-errors.js.map +1 -0
  11. package/dist/config/config-file.d.ts +3 -0
  12. package/dist/config/config-file.d.ts.map +1 -0
  13. package/dist/config/config-file.js +31 -0
  14. package/dist/config/config-file.js.map +1 -0
  15. package/dist/config/config-merge.d.ts +8 -0
  16. package/dist/config/config-merge.d.ts.map +1 -0
  17. package/dist/config/config-merge.js +50 -0
  18. package/dist/config/config-merge.js.map +1 -0
  19. package/dist/config/config-schema.d.ts +135 -0
  20. package/dist/config/config-schema.d.ts.map +1 -0
  21. package/dist/config/config-schema.js +94 -0
  22. package/dist/config/config-schema.js.map +1 -0
  23. package/dist/config/config-types.d.ts +21 -0
  24. package/dist/config/config-types.d.ts.map +1 -0
  25. package/dist/config/config-types.js +2 -0
  26. package/dist/config/config-types.js.map +1 -0
  27. package/dist/config/harness-config.d.ts +6 -0
  28. package/dist/config/harness-config.d.ts.map +1 -0
  29. package/dist/config/harness-config.js +4 -0
  30. package/dist/config/harness-config.js.map +1 -0
  31. package/dist/config/index.d.ts +2 -0
  32. package/dist/config/index.d.ts.map +1 -0
  33. package/dist/config/index.js +2 -0
  34. package/dist/config/index.js.map +1 -0
  35. package/dist/config/load-harness-config.d.ts +9 -0
  36. package/dist/config/load-harness-config.d.ts.map +1 -0
  37. package/dist/config/load-harness-config.js +25 -0
  38. package/dist/config/load-harness-config.js.map +1 -0
  39. package/dist/controller/agent-output.d.ts +21 -0
  40. package/dist/controller/agent-output.d.ts.map +1 -0
  41. package/dist/controller/agent-output.js +75 -0
  42. package/dist/controller/agent-output.js.map +1 -0
  43. package/dist/controller/agent-session.d.ts +49 -0
  44. package/dist/controller/agent-session.d.ts.map +1 -0
  45. package/dist/controller/agent-session.js +220 -0
  46. package/dist/controller/agent-session.js.map +1 -0
  47. package/dist/controller/contracts.d.ts +65 -0
  48. package/dist/controller/contracts.d.ts.map +1 -0
  49. package/dist/controller/contracts.js +2 -0
  50. package/dist/controller/contracts.js.map +1 -0
  51. package/dist/controller/errors.d.ts +23 -0
  52. package/dist/controller/errors.d.ts.map +1 -0
  53. package/dist/controller/errors.js +37 -0
  54. package/dist/controller/errors.js.map +1 -0
  55. package/dist/controller/evidence-factory.d.ts +15 -0
  56. package/dist/controller/evidence-factory.d.ts.map +1 -0
  57. package/dist/controller/evidence-factory.js +38 -0
  58. package/dist/controller/evidence-factory.js.map +1 -0
  59. package/dist/controller/failure-analysis.d.ts +36 -0
  60. package/dist/controller/failure-analysis.d.ts.map +1 -0
  61. package/dist/controller/failure-analysis.js +175 -0
  62. package/dist/controller/failure-analysis.js.map +1 -0
  63. package/dist/controller/failure-factory.d.ts +85 -0
  64. package/dist/controller/failure-factory.d.ts.map +1 -0
  65. package/dist/controller/failure-factory.js +124 -0
  66. package/dist/controller/failure-factory.js.map +1 -0
  67. package/dist/controller/graph-validator.d.ts +4 -0
  68. package/dist/controller/graph-validator.d.ts.map +1 -0
  69. package/dist/controller/graph-validator.js +102 -0
  70. package/dist/controller/graph-validator.js.map +1 -0
  71. package/dist/controller/index.d.ts +15 -0
  72. package/dist/controller/index.d.ts.map +1 -0
  73. package/dist/controller/index.js +11 -0
  74. package/dist/controller/index.js.map +1 -0
  75. package/dist/controller/repair-loop.d.ts +42 -0
  76. package/dist/controller/repair-loop.d.ts.map +1 -0
  77. package/dist/controller/repair-loop.js +385 -0
  78. package/dist/controller/repair-loop.js.map +1 -0
  79. package/dist/controller/report-factory.d.ts +4 -0
  80. package/dist/controller/report-factory.d.ts.map +1 -0
  81. package/dist/controller/report-factory.js +107 -0
  82. package/dist/controller/report-factory.js.map +1 -0
  83. package/dist/controller/role-prompts.d.ts +8 -0
  84. package/dist/controller/role-prompts.d.ts.map +1 -0
  85. package/dist/controller/role-prompts.js +35 -0
  86. package/dist/controller/role-prompts.js.map +1 -0
  87. package/dist/controller/run-controller.d.ts +3 -0
  88. package/dist/controller/run-controller.d.ts.map +1 -0
  89. package/dist/controller/run-controller.js +291 -0
  90. package/dist/controller/run-controller.js.map +1 -0
  91. package/dist/controller/run-persistence.d.ts +15 -0
  92. package/dist/controller/run-persistence.d.ts.map +1 -0
  93. package/dist/controller/run-persistence.js +83 -0
  94. package/dist/controller/run-persistence.js.map +1 -0
  95. package/dist/controller/run-state.d.ts +61 -0
  96. package/dist/controller/run-state.d.ts.map +1 -0
  97. package/dist/controller/run-state.js +151 -0
  98. package/dist/controller/run-state.js.map +1 -0
  99. package/dist/controller/task-agent-output.d.ts +70 -0
  100. package/dist/controller/task-agent-output.d.ts.map +1 -0
  101. package/dist/controller/task-agent-output.js +256 -0
  102. package/dist/controller/task-agent-output.js.map +1 -0
  103. package/dist/controller/task-agent-schemas.d.ts +217 -0
  104. package/dist/controller/task-agent-schemas.d.ts.map +1 -0
  105. package/dist/controller/task-agent-schemas.js +171 -0
  106. package/dist/controller/task-agent-schemas.js.map +1 -0
  107. package/dist/controller/task-executor.d.ts +15 -0
  108. package/dist/controller/task-executor.d.ts.map +1 -0
  109. package/dist/controller/task-executor.js +751 -0
  110. package/dist/controller/task-executor.js.map +1 -0
  111. package/dist/controller/task-paths.d.ts +3 -0
  112. package/dist/controller/task-paths.d.ts.map +1 -0
  113. package/dist/controller/task-paths.js +20 -0
  114. package/dist/controller/task-paths.js.map +1 -0
  115. package/dist/controller/task-retry.d.ts +24 -0
  116. package/dist/controller/task-retry.d.ts.map +1 -0
  117. package/dist/controller/task-retry.js +42 -0
  118. package/dist/controller/task-retry.js.map +1 -0
  119. package/dist/controller/worktree-eligibility.d.ts +15 -0
  120. package/dist/controller/worktree-eligibility.d.ts.map +1 -0
  121. package/dist/controller/worktree-eligibility.js +38 -0
  122. package/dist/controller/worktree-eligibility.js.map +1 -0
  123. package/dist/controller/worktree-scheduler.d.ts +72 -0
  124. package/dist/controller/worktree-scheduler.d.ts.map +1 -0
  125. package/dist/controller/worktree-scheduler.js +142 -0
  126. package/dist/controller/worktree-scheduler.js.map +1 -0
  127. package/dist/domain/agent-result.d.ts +83 -0
  128. package/dist/domain/agent-result.d.ts.map +1 -0
  129. package/dist/domain/agent-result.js +44 -0
  130. package/dist/domain/agent-result.js.map +1 -0
  131. package/dist/domain/evidence.d.ts +97 -0
  132. package/dist/domain/evidence.d.ts.map +1 -0
  133. package/dist/domain/evidence.js +85 -0
  134. package/dist/domain/evidence.js.map +1 -0
  135. package/dist/domain/failure.d.ts +121 -0
  136. package/dist/domain/failure.d.ts.map +1 -0
  137. package/dist/domain/failure.js +72 -0
  138. package/dist/domain/failure.js.map +1 -0
  139. package/dist/domain/index.d.ts +19 -0
  140. package/dist/domain/index.d.ts.map +1 -0
  141. package/dist/domain/index.js +10 -0
  142. package/dist/domain/index.js.map +1 -0
  143. package/dist/domain/report.d.ts +904 -0
  144. package/dist/domain/report.d.ts.map +1 -0
  145. package/dist/domain/report.js +90 -0
  146. package/dist/domain/report.js.map +1 -0
  147. package/dist/domain/requirement.d.ts +10 -0
  148. package/dist/domain/requirement.d.ts.map +1 -0
  149. package/dist/domain/requirement.js +12 -0
  150. package/dist/domain/requirement.js.map +1 -0
  151. package/dist/domain/run.d.ts +857 -0
  152. package/dist/domain/run.d.ts.map +1 -0
  153. package/dist/domain/run.js +129 -0
  154. package/dist/domain/run.js.map +1 -0
  155. package/dist/domain/shared.d.ts +60 -0
  156. package/dist/domain/shared.d.ts.map +1 -0
  157. package/dist/domain/shared.js +66 -0
  158. package/dist/domain/shared.js.map +1 -0
  159. package/dist/domain/task.d.ts +316 -0
  160. package/dist/domain/task.d.ts.map +1 -0
  161. package/dist/domain/task.js +116 -0
  162. package/dist/domain/task.js.map +1 -0
  163. package/dist/index.d.ts +15 -0
  164. package/dist/index.d.ts.map +1 -0
  165. package/dist/index.js +15 -0
  166. package/dist/index.js.map +1 -0
  167. package/dist/path/workspace-path.d.ts +6 -0
  168. package/dist/path/workspace-path.d.ts.map +1 -0
  169. package/dist/path/workspace-path.js +36 -0
  170. package/dist/path/workspace-path.js.map +1 -0
  171. package/dist/plugin/create-harness-plugin.d.ts +40 -0
  172. package/dist/plugin/create-harness-plugin.d.ts.map +1 -0
  173. package/dist/plugin/create-harness-plugin.js +169 -0
  174. package/dist/plugin/create-harness-plugin.js.map +1 -0
  175. package/dist/plugin/harness-agent-config.d.ts +6 -0
  176. package/dist/plugin/harness-agent-config.d.ts.map +1 -0
  177. package/dist/plugin/harness-agent-config.js +130 -0
  178. package/dist/plugin/harness-agent-config.js.map +1 -0
  179. package/dist/plugin/harness-chat-hook.d.ts +27 -0
  180. package/dist/plugin/harness-chat-hook.d.ts.map +1 -0
  181. package/dist/plugin/harness-chat-hook.js +72 -0
  182. package/dist/plugin/harness-chat-hook.js.map +1 -0
  183. package/dist/plugin/harness-chat-parts.d.ts +10 -0
  184. package/dist/plugin/harness-chat-parts.d.ts.map +1 -0
  185. package/dist/plugin/harness-chat-parts.js +36 -0
  186. package/dist/plugin/harness-chat-parts.js.map +1 -0
  187. package/dist/plugin/harness-chat-protocol.d.ts +9 -0
  188. package/dist/plugin/harness-chat-protocol.d.ts.map +1 -0
  189. package/dist/plugin/harness-chat-protocol.js +23 -0
  190. package/dist/plugin/harness-chat-protocol.js.map +1 -0
  191. package/dist/plugin/harness-coordinator.d.ts +33 -0
  192. package/dist/plugin/harness-coordinator.d.ts.map +1 -0
  193. package/dist/plugin/harness-coordinator.js +188 -0
  194. package/dist/plugin/harness-coordinator.js.map +1 -0
  195. package/dist/plugin/harness-intake-prompt.d.ts +2 -0
  196. package/dist/plugin/harness-intake-prompt.d.ts.map +1 -0
  197. package/dist/plugin/harness-intake-prompt.js +52 -0
  198. package/dist/plugin/harness-intake-prompt.js.map +1 -0
  199. package/dist/plugin/harness-intent.d.ts +72 -0
  200. package/dist/plugin/harness-intent.d.ts.map +1 -0
  201. package/dist/plugin/harness-intent.js +82 -0
  202. package/dist/plugin/harness-intent.js.map +1 -0
  203. package/dist/plugin/harness-parent-session-dispatcher.d.ts +46 -0
  204. package/dist/plugin/harness-parent-session-dispatcher.d.ts.map +1 -0
  205. package/dist/plugin/harness-parent-session-dispatcher.js +33 -0
  206. package/dist/plugin/harness-parent-session-dispatcher.js.map +1 -0
  207. package/dist/plugin/harness-requirement.d.ts +4 -0
  208. package/dist/plugin/harness-requirement.d.ts.map +1 -0
  209. package/dist/plugin/harness-requirement.js +37 -0
  210. package/dist/plugin/harness-requirement.js.map +1 -0
  211. package/dist/session/contracts.d.ts +178 -0
  212. package/dist/session/contracts.d.ts.map +1 -0
  213. package/dist/session/contracts.js +28 -0
  214. package/dist/session/contracts.js.map +1 -0
  215. package/dist/session/fake-session-adapter.d.ts +22 -0
  216. package/dist/session/fake-session-adapter.d.ts.map +1 -0
  217. package/dist/session/fake-session-adapter.js +238 -0
  218. package/dist/session/fake-session-adapter.js.map +1 -0
  219. package/dist/session/fake-session-errors.d.ts +23 -0
  220. package/dist/session/fake-session-errors.d.ts.map +1 -0
  221. package/dist/session/fake-session-errors.js +37 -0
  222. package/dist/session/fake-session-errors.js.map +1 -0
  223. package/dist/session/harness-agent-names.d.ts +51 -0
  224. package/dist/session/harness-agent-names.d.ts.map +1 -0
  225. package/dist/session/harness-agent-names.js +98 -0
  226. package/dist/session/harness-agent-names.js.map +1 -0
  227. package/dist/session/index.d.ts +9 -0
  228. package/dist/session/index.d.ts.map +1 -0
  229. package/dist/session/index.js +9 -0
  230. package/dist/session/index.js.map +1 -0
  231. package/dist/session/opencode-session-adapter.d.ts +9 -0
  232. package/dist/session/opencode-session-adapter.d.ts.map +1 -0
  233. package/dist/session/opencode-session-adapter.js +243 -0
  234. package/dist/session/opencode-session-adapter.js.map +1 -0
  235. package/dist/session/opencode-session-client.d.ts +58 -0
  236. package/dist/session/opencode-session-client.d.ts.map +1 -0
  237. package/dist/session/opencode-session-client.js +17 -0
  238. package/dist/session/opencode-session-client.js.map +1 -0
  239. package/dist/session/opencode-session-errors.d.ts +15 -0
  240. package/dist/session/opencode-session-errors.d.ts.map +1 -0
  241. package/dist/session/opencode-session-errors.js +19 -0
  242. package/dist/session/opencode-session-errors.js.map +1 -0
  243. package/dist/session/opencode-session-prompts.d.ts +12 -0
  244. package/dist/session/opencode-session-prompts.d.ts.map +1 -0
  245. package/dist/session/opencode-session-prompts.js +16 -0
  246. package/dist/session/opencode-session-prompts.js.map +1 -0
  247. package/dist/store/filesystem-run-store-io.d.ts +9 -0
  248. package/dist/store/filesystem-run-store-io.d.ts.map +1 -0
  249. package/dist/store/filesystem-run-store-io.js +85 -0
  250. package/dist/store/filesystem-run-store-io.js.map +1 -0
  251. package/dist/store/filesystem-run-store.d.ts +16 -0
  252. package/dist/store/filesystem-run-store.d.ts.map +1 -0
  253. package/dist/store/filesystem-run-store.js +286 -0
  254. package/dist/store/filesystem-run-store.js.map +1 -0
  255. package/dist/store/index.d.ts +5 -0
  256. package/dist/store/index.d.ts.map +1 -0
  257. package/dist/store/index.js +4 -0
  258. package/dist/store/index.js.map +1 -0
  259. package/dist/store/run-event.d.ts +786 -0
  260. package/dist/store/run-event.d.ts.map +1 -0
  261. package/dist/store/run-event.js +24 -0
  262. package/dist/store/run-event.js.map +1 -0
  263. package/dist/store/run-store-errors.d.ts +38 -0
  264. package/dist/store/run-store-errors.d.ts.map +1 -0
  265. package/dist/store/run-store-errors.js +62 -0
  266. package/dist/store/run-store-errors.js.map +1 -0
  267. package/dist/tools/context7-client.d.ts +22 -0
  268. package/dist/tools/context7-client.d.ts.map +1 -0
  269. package/dist/tools/context7-client.js +108 -0
  270. package/dist/tools/context7-client.js.map +1 -0
  271. package/dist/tools/grep-app-client.d.ts +21 -0
  272. package/dist/tools/grep-app-client.d.ts.map +1 -0
  273. package/dist/tools/grep-app-client.js +136 -0
  274. package/dist/tools/grep-app-client.js.map +1 -0
  275. package/dist/tools/harness-research-tools.d.ts +21 -0
  276. package/dist/tools/harness-research-tools.d.ts.map +1 -0
  277. package/dist/tools/harness-research-tools.js +101 -0
  278. package/dist/tools/harness-research-tools.js.map +1 -0
  279. package/dist/tools/lsp-client.d.ts +32 -0
  280. package/dist/tools/lsp-client.d.ts.map +1 -0
  281. package/dist/tools/lsp-client.js +234 -0
  282. package/dist/tools/lsp-client.js.map +1 -0
  283. package/dist/tools/lsp-json-rpc.d.ts +13 -0
  284. package/dist/tools/lsp-json-rpc.d.ts.map +1 -0
  285. package/dist/tools/lsp-json-rpc.js +98 -0
  286. package/dist/tools/lsp-json-rpc.js.map +1 -0
  287. package/dist/verification/command-policy.d.ts +11 -0
  288. package/dist/verification/command-policy.d.ts.map +1 -0
  289. package/dist/verification/command-policy.js +262 -0
  290. package/dist/verification/command-policy.js.map +1 -0
  291. package/dist/verification/contracts.d.ts +82 -0
  292. package/dist/verification/contracts.d.ts.map +1 -0
  293. package/dist/verification/contracts.js +6 -0
  294. package/dist/verification/contracts.js.map +1 -0
  295. package/dist/verification/fake-process-runner.d.ts +16 -0
  296. package/dist/verification/fake-process-runner.d.ts.map +1 -0
  297. package/dist/verification/fake-process-runner.js +28 -0
  298. package/dist/verification/fake-process-runner.js.map +1 -0
  299. package/dist/verification/index.d.ts +6 -0
  300. package/dist/verification/index.d.ts.map +1 -0
  301. package/dist/verification/index.js +5 -0
  302. package/dist/verification/index.js.map +1 -0
  303. package/dist/verification/node-process-runner.d.ts +12 -0
  304. package/dist/verification/node-process-runner.d.ts.map +1 -0
  305. package/dist/verification/node-process-runner.js +103 -0
  306. package/dist/verification/node-process-runner.js.map +1 -0
  307. package/dist/verification/verification-runner.d.ts +3 -0
  308. package/dist/verification/verification-runner.d.ts.map +1 -0
  309. package/dist/verification/verification-runner.js +101 -0
  310. package/dist/verification/verification-runner.js.map +1 -0
  311. package/dist/workspace/git-baseline.d.ts +63 -0
  312. package/dist/workspace/git-baseline.d.ts.map +1 -0
  313. package/dist/workspace/git-baseline.js +53 -0
  314. package/dist/workspace/git-baseline.js.map +1 -0
  315. package/dist/workspace/git-workspace-adapter.d.ts +43 -0
  316. package/dist/workspace/git-workspace-adapter.d.ts.map +1 -0
  317. package/dist/workspace/git-workspace-adapter.js +279 -0
  318. package/dist/workspace/git-workspace-adapter.js.map +1 -0
  319. package/dist/workspace/git-worktree-adapter.d.ts +45 -0
  320. package/dist/workspace/git-worktree-adapter.d.ts.map +1 -0
  321. package/dist/workspace/git-worktree-adapter.js +104 -0
  322. package/dist/workspace/git-worktree-adapter.js.map +1 -0
  323. package/dist/workspace/index.d.ts +7 -0
  324. package/dist/workspace/index.d.ts.map +1 -0
  325. package/dist/workspace/index.js +4 -0
  326. package/dist/workspace/index.js.map +1 -0
  327. package/package.json +45 -0
@@ -0,0 +1,234 @@
1
+ import { accessSync, constants } from "node:fs";
2
+ import { mkdir, readFile, rm } from "node:fs/promises";
3
+ import { createRequire } from "node:module";
4
+ import { delimiter, join, relative, resolve } from "node:path";
5
+ import { z } from "zod";
6
+ import { resolveWorkspacePath } from "../path/workspace-path.js";
7
+ import { createLspConnection } from "./lsp-json-rpc.js";
8
+ export class LspError extends Error {
9
+ code;
10
+ name = "LspError";
11
+ constructor(message, code, options) {
12
+ super(message, options);
13
+ this.code = code;
14
+ }
15
+ }
16
+ export const createLspClient = (input = {}) => {
17
+ const servers = new Map();
18
+ const timeoutMs = input.timeoutMs ?? 10_000;
19
+ const tempRoot = input.tempRoot ?? join("/tmp", "harness-engineering-agent", "lsp");
20
+ const getServer = async (workspaceRoot, language) => {
21
+ const key = `${workspaceRoot}:${language}`;
22
+ const existing = servers.get(key);
23
+ if (existing !== undefined)
24
+ return existing;
25
+ const command = (input.serverCommandResolver ?? findServerCommand)(language);
26
+ if (command === undefined) {
27
+ throw new LspError(`No LSP server available for ${language}`, "server_unavailable");
28
+ }
29
+ const dataDirectory = language === "java" ? join(tempRoot, encodeWorkspace(workspaceRoot)) : undefined;
30
+ if (dataDirectory !== undefined)
31
+ await mkdir(dataDirectory, { recursive: true });
32
+ const diagnostics = new Map();
33
+ const connection = (input.connectionFactory ?? createLspConnection)({
34
+ command: command.command,
35
+ args: dataDirectory === undefined ? command.args : [...command.args, "-data", dataDirectory],
36
+ cwd: workspaceRoot,
37
+ ...(language === "java" ? { env: { JAVA_HOME: "/usr/lib/jvm/java-21-openjdk-amd64" } } : {}),
38
+ onNotification: (method, params) => {
39
+ if (method !== "textDocument/publishDiagnostics")
40
+ return;
41
+ const payload = readDiagnosticNotification(params);
42
+ if (payload !== undefined)
43
+ diagnostics.set(payload.uri, payload.diagnostics);
44
+ },
45
+ });
46
+ try {
47
+ await withTimeout(connection.request("initialize", {
48
+ processId: process.pid,
49
+ rootUri: `file://${workspaceRoot}`,
50
+ capabilities: { textDocument: { publishDiagnostics: { relatedInformation: true } } },
51
+ workspaceFolders: [{ uri: `file://${workspaceRoot}`, name: "harness" }],
52
+ }), timeoutMs);
53
+ }
54
+ catch (error) {
55
+ await connection.close().catch(() => { });
56
+ throw normalizeLspError(error);
57
+ }
58
+ connection.notify("initialized", {});
59
+ const server = { language, connection, diagnostics, dataDirectory };
60
+ servers.set(key, server);
61
+ return server;
62
+ };
63
+ const prepare = async (request) => {
64
+ const workspaceRoot = resolve(request.workspaceRoot);
65
+ const filePath = resolveWorkspacePath(workspaceRoot, request.filePath);
66
+ const language = languageForPath(filePath);
67
+ const server = await getServer(workspaceRoot, language);
68
+ const uri = `file://${filePath}`;
69
+ const text = await readFile(filePath, "utf8");
70
+ server.connection.notify("textDocument/didOpen", {
71
+ textDocument: { uri, languageId: language, version: 1, text },
72
+ });
73
+ return {
74
+ server,
75
+ uri,
76
+ position: { line: Math.max(0, request.line - 1), character: Math.max(0, request.column - 1) },
77
+ };
78
+ };
79
+ return {
80
+ status: async () => Promise.all(["java", "typescript", "javascript"].map(async (language) => ({
81
+ language,
82
+ available: (input.serverCommandResolver ?? findServerCommand)(language) !== undefined,
83
+ status: (input.serverCommandResolver ?? findServerCommand)(language) === undefined
84
+ ? "unavailable"
85
+ : "available",
86
+ }))),
87
+ diagnostics: async (request) => {
88
+ const prepared = await prepare(request);
89
+ await new Promise((resolve) => setTimeout(resolve, 500));
90
+ return { uri: prepared.uri, diagnostics: prepared.server.diagnostics.get(prepared.uri) ?? [] };
91
+ },
92
+ definition: async (request) => {
93
+ const prepared = await prepare(request);
94
+ return withTimeout(prepared.server.connection
95
+ .request("textDocument/definition", {
96
+ textDocument: { uri: prepared.uri },
97
+ position: prepared.position,
98
+ })
99
+ .then(parseDefinitionResponse), timeoutMs).catch((error) => {
100
+ throw normalizeLspError(error);
101
+ });
102
+ },
103
+ references: async (request) => {
104
+ const prepared = await prepare(request);
105
+ return withTimeout(prepared.server.connection
106
+ .request("textDocument/references", {
107
+ textDocument: { uri: prepared.uri },
108
+ position: prepared.position,
109
+ context: { includeDeclaration: true },
110
+ })
111
+ .then(parseReferenceResponse), timeoutMs).catch((error) => {
112
+ throw normalizeLspError(error);
113
+ });
114
+ },
115
+ close: async () => {
116
+ await Promise.all([...servers.values()].map((server) => server.connection.close()));
117
+ await Promise.all([...servers.values()]
118
+ .map((server) => server.dataDirectory)
119
+ .filter((path) => path !== undefined)
120
+ .map((path) => rm(path, { recursive: true, force: true })));
121
+ servers.clear();
122
+ },
123
+ };
124
+ };
125
+ const findServerCommand = (language) => {
126
+ if (language === "java") {
127
+ const configuredCommand = process.env[String("HARNESS_JDTLS_COMMAND")];
128
+ const command = configuredCommand ??
129
+ which("jdtls") ??
130
+ "/persist/users/kasm-user/.vscode/extensions/redhat.java-1.55.0-linux-x64/server/bin/jdtls";
131
+ return exists(command) ? { command, args: [] } : undefined;
132
+ }
133
+ try {
134
+ const require = createRequire(import.meta.url);
135
+ return {
136
+ command: process.execPath,
137
+ args: [require.resolve("typescript-language-server/lib/cli.mjs"), "--stdio"],
138
+ };
139
+ }
140
+ catch {
141
+ return undefined;
142
+ }
143
+ };
144
+ const which = (command) => {
145
+ if (command.includes("/") || command.includes("\\")) {
146
+ return exists(command) ? command : undefined;
147
+ }
148
+ const { PATH: pathValue } = process.env;
149
+ if (pathValue === undefined || pathValue.length === 0) {
150
+ return undefined;
151
+ }
152
+ for (const entry of pathValue.split(delimiter)) {
153
+ const candidate = join(entry, command);
154
+ if (exists(candidate)) {
155
+ return candidate;
156
+ }
157
+ }
158
+ return undefined;
159
+ };
160
+ const exists = (path) => {
161
+ try {
162
+ accessSync(path, constants.X_OK);
163
+ return true;
164
+ }
165
+ catch {
166
+ return false;
167
+ }
168
+ };
169
+ const languageForPath = (path) => {
170
+ if (path.endsWith(".java"))
171
+ return "java";
172
+ if (path.endsWith(".jsx") || path.endsWith(".js"))
173
+ return "javascript";
174
+ if (path.endsWith(".tsx") || path.endsWith(".ts"))
175
+ return "typescript";
176
+ throw new LspError(`Unsupported LSP file extension: ${relative(process.cwd(), path)}`, "request_failed");
177
+ };
178
+ const encodeWorkspace = (workspaceRoot) => workspaceRoot.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "");
179
+ const readDiagnosticNotification = (params) => {
180
+ if (typeof params !== "object" || params === null)
181
+ return undefined;
182
+ const uri = Reflect.get(params, "uri");
183
+ const diagnostics = Reflect.get(params, "diagnostics");
184
+ return typeof uri === "string" && Array.isArray(diagnostics) ? { uri, diagnostics } : undefined;
185
+ };
186
+ const withTimeout = async (promise, timeoutMs) => Promise.race([
187
+ promise,
188
+ new Promise((_, reject) => setTimeout(() => reject(new LspError("LSP request timed out", "request_timeout")), timeoutMs)),
189
+ ]);
190
+ const LocationSchema = z
191
+ .object({
192
+ uri: z.string(),
193
+ range: z.object({
194
+ start: z.object({ line: z.number(), character: z.number() }),
195
+ end: z.object({ line: z.number(), character: z.number() }),
196
+ }),
197
+ })
198
+ .passthrough();
199
+ const parseDefinitionResponse = (value) => {
200
+ try {
201
+ return z.union([LocationSchema, z.array(LocationSchema), z.null()]).parse(value);
202
+ }
203
+ catch (error) {
204
+ throw new LspError("LSP returned malformed definition payload", "protocol_failure", {
205
+ cause: error,
206
+ });
207
+ }
208
+ };
209
+ const parseReferenceResponse = (value) => {
210
+ try {
211
+ return z.array(LocationSchema).parse(value);
212
+ }
213
+ catch (error) {
214
+ throw new LspError("LSP returned malformed references payload", "protocol_failure", {
215
+ cause: error,
216
+ });
217
+ }
218
+ };
219
+ const normalizeLspError = (error) => {
220
+ if (error instanceof LspError) {
221
+ return error;
222
+ }
223
+ if (error instanceof Error) {
224
+ if (error.message.includes("timed out")) {
225
+ return new LspError(error.message, "request_timeout", { cause: error });
226
+ }
227
+ if (error.message.includes("exited") || error.message.includes("closed")) {
228
+ return new LspError(error.message, "process_failure", { cause: error });
229
+ }
230
+ return new LspError(error.message, "request_failed", { cause: error });
231
+ }
232
+ return new LspError("LSP request failed", "request_failed");
233
+ };
234
+ //# sourceMappingURL=lsp-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lsp-client.js","sourceRoot":"","sources":["../../src/tools/lsp-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export type LspConnection = {
2
+ readonly request: (method: string, params: unknown) => Promise<unknown>;
3
+ readonly notify: (method: string, params: unknown) => void;
4
+ readonly close: () => Promise<void>;
5
+ };
6
+ export declare const createLspConnection: (input: {
7
+ readonly command: string;
8
+ readonly args: readonly string[];
9
+ readonly cwd: string;
10
+ readonly env?: NodeJS.ProcessEnv;
11
+ readonly onNotification?: (method: string, params: unknown) => void;
12
+ }) => LspConnection;
13
+ //# sourceMappingURL=lsp-json-rpc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lsp-json-rpc.d.ts","sourceRoot":"","sources":["../../src/tools/lsp-json-rpc.ts"],"names":[],"mappings":"AAuBA,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACvE,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;IAC1D,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACpC,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,OAAO;IACzC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IAChC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;CACpE,KAAG,aAuFH,CAAA"}
@@ -0,0 +1,98 @@
1
+ import { spawn } from "node:child_process";
2
+ import { z } from "zod";
3
+ const JsonRpcMessageSchema = z
4
+ .object({
5
+ jsonrpc: z.literal("2.0"),
6
+ id: z.number().optional(),
7
+ method: z.string().optional(),
8
+ params: z.unknown().optional(),
9
+ result: z.unknown().optional(),
10
+ error: z.object({ code: z.number(), message: z.string() }).optional(),
11
+ })
12
+ .passthrough();
13
+ export const createLspConnection = (input) => {
14
+ const child = spawn(input.command, [...input.args], {
15
+ cwd: input.cwd,
16
+ env: { ...process.env, ...input.env },
17
+ stdio: "pipe",
18
+ });
19
+ let nextId = 1;
20
+ let buffer = Buffer.alloc(0);
21
+ const pending = new Map();
22
+ child.stdout.on("data", (chunk) => {
23
+ buffer = Buffer.concat([buffer, chunk]);
24
+ parseMessages();
25
+ });
26
+ child.on("error", (error) => rejectAll(error));
27
+ child.on("exit", () => rejectAll(new Error("LSP server exited")));
28
+ const request = (method, params) => {
29
+ const id = nextId++;
30
+ const promise = new Promise((resolve, reject) => pending.set(id, { resolve, reject }));
31
+ send({ jsonrpc: "2.0", id, method, params });
32
+ return promise;
33
+ };
34
+ const notify = (method, params) => {
35
+ send({ jsonrpc: "2.0", method, params });
36
+ };
37
+ const close = async () => {
38
+ if (child.exitCode !== null)
39
+ return;
40
+ notify("shutdown", null);
41
+ child.stdin.end();
42
+ await new Promise((resolve) => {
43
+ const timer = setTimeout(() => {
44
+ child.kill();
45
+ resolve();
46
+ }, 1000);
47
+ child.once("exit", () => {
48
+ clearTimeout(timer);
49
+ resolve();
50
+ });
51
+ });
52
+ };
53
+ const parseMessages = () => {
54
+ while (true) {
55
+ const separator = buffer.indexOf("\r\n\r\n");
56
+ if (separator < 0)
57
+ return;
58
+ const header = buffer.subarray(0, separator).toString("ascii");
59
+ const length = /^Content-Length:\s*(\d+)$/im.exec(header)?.[1];
60
+ if (length === undefined) {
61
+ buffer = buffer.subarray(separator + 4);
62
+ continue;
63
+ }
64
+ const bodyStart = separator + 4;
65
+ const bodyEnd = bodyStart + Number(length);
66
+ if (buffer.length < bodyEnd)
67
+ return;
68
+ const body = buffer.subarray(bodyStart, bodyEnd).toString("utf8");
69
+ buffer = buffer.subarray(bodyEnd);
70
+ const raw = JSON.parse(body);
71
+ const message = JsonRpcMessageSchema.parse(raw);
72
+ if (message.id !== undefined) {
73
+ const current = pending.get(message.id);
74
+ if (current === undefined)
75
+ continue;
76
+ pending.delete(message.id);
77
+ if (message.error !== undefined)
78
+ current.reject(new Error(message.error.message));
79
+ else
80
+ current.resolve(message.result);
81
+ }
82
+ else if (message.method !== undefined) {
83
+ input.onNotification?.(message.method, message.params);
84
+ }
85
+ }
86
+ };
87
+ const send = (message) => {
88
+ const body = JSON.stringify(message);
89
+ child.stdin.write(`Content-Length: ${Buffer.byteLength(body)}\r\n\r\n${body}`);
90
+ };
91
+ const rejectAll = (error) => {
92
+ for (const current of pending.values())
93
+ current.reject(error);
94
+ pending.clear();
95
+ };
96
+ return { request, notify, close };
97
+ };
98
+ //# sourceMappingURL=lsp-json-rpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lsp-json-rpc.js","sourceRoot":"","sources":["../../src/tools/lsp-json-rpc.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { VerificationCommand } from "../domain/index.js";
2
+ import type { ProcessRunnerCommand } from "./contracts.js";
3
+ export declare class VerificationCommandPolicyError extends Error {
4
+ readonly name = "VerificationCommandPolicyError";
5
+ }
6
+ export declare const normalizeVerificationCommand: (input: {
7
+ readonly workspaceRoot: string;
8
+ readonly command: VerificationCommand;
9
+ }) => ProcessRunnerCommand;
10
+ export declare const sanitizeResearchToolOutput: (value: unknown) => unknown;
11
+ //# sourceMappingURL=command-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-policy.d.ts","sourceRoot":"","sources":["../../src/verification/command-policy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAG7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAgE1D,qBAAa,8BAA+B,SAAQ,KAAK;IACvD,QAAQ,CAAC,IAAI,oCAAmC;CACjD;AAED,eAAO,MAAM,4BAA4B,GAAI,OAAO;IAClD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAA;CACtC,KAAG,oBAuBH,CAAA;AA+PD,eAAO,MAAM,0BAA0B,GAAI,OAAO,OAAO,KAAG,OAa3D,CAAA"}
@@ -0,0 +1,262 @@
1
+ import { basename, resolve } from "node:path";
2
+ import { redactEvidenceSummary } from "../domain/index.js";
3
+ import { resolveWorkspacePath } from "../path/workspace-path.js";
4
+ const DEFAULT_COMMAND_ORIGIN = "config";
5
+ const READ_ONLY_EXECUTABLES = new Set([
6
+ "node",
7
+ "pnpm",
8
+ "npm",
9
+ "npx",
10
+ "bun",
11
+ "vitest",
12
+ "tsc",
13
+ "biome",
14
+ ]);
15
+ const WORKSPACE_WRITE_EXECUTABLES = new Set([...READ_ONLY_EXECUTABLES, "git"]);
16
+ const ENV_ALLOWLIST = new Set([
17
+ "CI",
18
+ "FORCE_COLOR",
19
+ "HARNESS_JDTLS_COMMAND",
20
+ "JAVA_HOME",
21
+ "NODE_ENV",
22
+ "NO_COLOR",
23
+ "PATH",
24
+ "PNPM_HOME",
25
+ "TMPDIR",
26
+ "TMP",
27
+ "TEMP",
28
+ ]);
29
+ const DANGEROUS_TOKENS = new Set([
30
+ "curl",
31
+ "wget",
32
+ "rm",
33
+ "rmdir",
34
+ "mv",
35
+ "dd",
36
+ "mkfs",
37
+ "shutdown",
38
+ "reboot",
39
+ "poweroff",
40
+ "git-reset",
41
+ "git-clean",
42
+ "git-checkout",
43
+ ]);
44
+ const SHELL_CONTROL_OPERATORS = new Set(["&&", "||", "|", ";", "$(", "`", ">", ">>", "<", "<<"]);
45
+ const GIT_DESTRUCTIVE_SUBCOMMANDS = new Set(["reset", "clean", "checkout"]);
46
+ const EXEC_WRAPPERS = new Set(["pnpm", "npm", "npx"]);
47
+ const NODE_EVAL_FLAGS = new Set(["-e", "--eval"]);
48
+ const ALLOWED_READ_ONLY_NODE_EVAL = {
49
+ command: "node",
50
+ args: ["--input-type=module", "-e", "import('./dist/index.js')"],
51
+ };
52
+ export class VerificationCommandPolicyError extends Error {
53
+ name = "VerificationCommandPolicyError";
54
+ }
55
+ export const normalizeVerificationCommand = (input) => {
56
+ const origin = input.command.origin ?? DEFAULT_COMMAND_ORIGIN;
57
+ const cwd = resolveWorkspacePath(input.workspaceRoot, input.command.workingDirectory);
58
+ assertContainedWorkspaceRoot(input.workspaceRoot, cwd);
59
+ const argv = input.command.args === undefined
60
+ ? parseCommandString(input.command.command)
61
+ : [input.command.command, ...input.command.args];
62
+ const executable = normalizeExecutable(argv[0] ?? "");
63
+ assertNoShellControlSyntax(argv);
64
+ assertExecutableAllowed(executable, input.command.sideEffectLevel);
65
+ assertNoDangerousNestedExecution(argv, input.command.sideEffectLevel);
66
+ assertOriginAllowed(origin, input.command.sideEffectLevel);
67
+ assertConfirmationSatisfied(input.command, executable);
68
+ const env = sanitizeEnvironment(input.command.allowedEnv);
69
+ return {
70
+ command: argv[0] ?? input.command.command,
71
+ args: argv.slice(1),
72
+ cwd,
73
+ timeoutMs: input.command.timeoutMs,
74
+ shell: false,
75
+ ...(env === undefined ? {} : { env }),
76
+ };
77
+ };
78
+ const assertContainedWorkspaceRoot = (workspaceRoot, cwd) => {
79
+ const workspace = resolve(workspaceRoot);
80
+ const candidate = resolve(cwd);
81
+ if (candidate !== workspace && !candidate.startsWith(`${workspace}/`)) {
82
+ throw new VerificationCommandPolicyError(`verification cwd must stay within the task workspace: ${candidate}`);
83
+ }
84
+ };
85
+ const assertExecutableAllowed = (executable, sideEffectLevel) => {
86
+ if (executable.length === 0) {
87
+ throw new VerificationCommandPolicyError("verification command cannot be empty");
88
+ }
89
+ switch (sideEffectLevel) {
90
+ case "read_only":
91
+ if (!READ_ONLY_EXECUTABLES.has(executable)) {
92
+ throw new VerificationCommandPolicyError(`command executable is not allowed for read-only verification: ${executable}`);
93
+ }
94
+ return;
95
+ case "workspace_write":
96
+ if (!WORKSPACE_WRITE_EXECUTABLES.has(executable)) {
97
+ throw new VerificationCommandPolicyError(`command executable is not allowlisted for workspace mutation: ${executable}`);
98
+ }
99
+ return;
100
+ case "external_side_effect":
101
+ throw new VerificationCommandPolicyError(`external side effects are not allowed for verification commands: ${executable}`);
102
+ }
103
+ };
104
+ const assertOriginAllowed = (origin, sideEffectLevel) => {
105
+ if (sideEffectLevel === "read_only") {
106
+ return;
107
+ }
108
+ if (origin === "worker") {
109
+ throw new VerificationCommandPolicyError(`worker-origin verification commands cannot request ${sideEffectLevel}`);
110
+ }
111
+ };
112
+ const assertConfirmationSatisfied = (command, executable) => {
113
+ const dangerous = isDangerousCommand(executable, command.command);
114
+ if (!dangerous && command.requiresConfirmation !== true) {
115
+ return;
116
+ }
117
+ if (command.confirmation === undefined) {
118
+ throw new VerificationCommandPolicyError(`verification command requires explicit confirmation before execution: ${command.name}`);
119
+ }
120
+ };
121
+ const isDangerousCommand = (executable, rawCommand) => {
122
+ if (DANGEROUS_TOKENS.has(executable)) {
123
+ return true;
124
+ }
125
+ if (executable === "git") {
126
+ return /\bgit\s+(?:reset|clean|checkout)\b/.test(rawCommand);
127
+ }
128
+ return false;
129
+ };
130
+ const assertNoShellControlSyntax = (argv) => {
131
+ for (const token of argv) {
132
+ if (containsShellControlSyntax(token)) {
133
+ throw new VerificationCommandPolicyError(`verification command contains disallowed shell control syntax: ${token}`);
134
+ }
135
+ }
136
+ };
137
+ const containsShellControlSyntax = (token) => {
138
+ if (token.length === 0) {
139
+ return false;
140
+ }
141
+ if (token.includes("$(") || token.includes("`") || token.includes("&&") || token.includes("||")) {
142
+ return true;
143
+ }
144
+ if (token === "|" ||
145
+ token === ";" ||
146
+ token === ">" ||
147
+ token === ">>" ||
148
+ token === "<" ||
149
+ token === "<<") {
150
+ return true;
151
+ }
152
+ return [...SHELL_CONTROL_OPERATORS].some((operator) => token !== operator && token.includes(operator));
153
+ };
154
+ const assertNoDangerousNestedExecution = (argv, sideEffectLevel) => {
155
+ const executable = normalizeExecutable(argv[0] ?? "");
156
+ if (executable === "git" && GIT_DESTRUCTIVE_SUBCOMMANDS.has(normalizeExecutable(argv[1] ?? ""))) {
157
+ throw new VerificationCommandPolicyError(`verification command cannot execute destructive git subcommand: ${argv[1]}`);
158
+ }
159
+ if (executable === "node") {
160
+ assertSafeNodeInvocation(argv, sideEffectLevel);
161
+ return;
162
+ }
163
+ if (EXEC_WRAPPERS.has(executable)) {
164
+ assertSafePackageManagerInvocation(executable, argv);
165
+ }
166
+ };
167
+ const assertSafeNodeInvocation = (argv, sideEffectLevel) => {
168
+ for (let index = 1; index < argv.length; index += 1) {
169
+ const token = argv[index];
170
+ if (token !== undefined && NODE_EVAL_FLAGS.has(token)) {
171
+ if (sideEffectLevel === "read_only" && isAllowedReadOnlyNodeEval(argv)) {
172
+ return;
173
+ }
174
+ if (sideEffectLevel === "read_only") {
175
+ throw new VerificationCommandPolicyError(`read-only verification cannot execute arbitrary node eval payloads: ${token}`);
176
+ }
177
+ const script = argv[index + 1] ?? "";
178
+ if (containsDangerousScriptToken(script)) {
179
+ throw new VerificationCommandPolicyError(`verification command cannot execute dangerous node eval payload: ${token}`);
180
+ }
181
+ }
182
+ }
183
+ };
184
+ const isAllowedReadOnlyNodeEval = (argv) => {
185
+ if (argv[0] !== ALLOWED_READ_ONLY_NODE_EVAL.command) {
186
+ return false;
187
+ }
188
+ return (argv.length === 1 + ALLOWED_READ_ONLY_NODE_EVAL.args.length &&
189
+ ALLOWED_READ_ONLY_NODE_EVAL.args.every((token, index) => argv[index + 1] === token));
190
+ };
191
+ const assertSafePackageManagerInvocation = (executable, argv) => {
192
+ if (executable === "npx") {
193
+ assertNestedExecutableAllowed(argv[1], "npx");
194
+ assertNestedGitSubcommandAllowed(argv.slice(1), "npx");
195
+ return;
196
+ }
197
+ for (let index = 1; index < argv.length; index += 1) {
198
+ const token = argv[index];
199
+ if (token === "exec") {
200
+ const nestedArgs = argv.slice(index + 1);
201
+ assertNestedExecutableAllowed(nestedArgs[0], `${executable} exec`);
202
+ assertNestedGitSubcommandAllowed(nestedArgs, `${executable} exec`);
203
+ return;
204
+ }
205
+ }
206
+ };
207
+ const assertNestedExecutableAllowed = (token, source) => {
208
+ const nested = normalizeExecutable(token ?? "");
209
+ if (nested.length === 0) {
210
+ return;
211
+ }
212
+ if (DANGEROUS_TOKENS.has(nested) || nested === "git") {
213
+ throw new VerificationCommandPolicyError(`verification command cannot launch nested executable via ${source}: ${nested}`);
214
+ }
215
+ };
216
+ const assertNestedGitSubcommandAllowed = (argv, source) => {
217
+ const nestedExecutable = normalizeExecutable(argv[0] ?? "");
218
+ if (nestedExecutable !== "git") {
219
+ return;
220
+ }
221
+ const subcommandIndex = argv[1] === "--" ? 2 : 1;
222
+ const subcommand = normalizeExecutable(argv[subcommandIndex] ?? "");
223
+ if (GIT_DESTRUCTIVE_SUBCOMMANDS.has(subcommand)) {
224
+ throw new VerificationCommandPolicyError(`verification command cannot launch destructive git subcommand via ${source}: ${subcommand}`);
225
+ }
226
+ };
227
+ const containsDangerousScriptToken = (script) => {
228
+ const lowered = script.toLowerCase();
229
+ const tokens = tokenizeScript(script).map((token) => normalizeExecutable(token));
230
+ return (tokens.some((token) => DANGEROUS_TOKENS.has(token)) ||
231
+ tokens.some((token, index) => token === "git" && GIT_DESTRUCTIVE_SUBCOMMANDS.has(tokens[index + 1] ?? "")) ||
232
+ /\bgit\s+reset\b/.test(lowered) ||
233
+ /\bgit\s+clean\b/.test(lowered) ||
234
+ /\bgit\s+checkout\b/.test(lowered) ||
235
+ containsShellControlSyntax(script));
236
+ };
237
+ const tokenizeScript = (value) => value.match(/[A-Za-z0-9_./:-]+/g) ?? [];
238
+ const parseCommandString = (value) => {
239
+ const tokens = value.match(/"[^"]*"|'[^']*'|\S+/g) ?? [];
240
+ return tokens.map((token) => token.replace(/^['"]|['"]$/g, ""));
241
+ };
242
+ const normalizeExecutable = (value) => basename(value).toLowerCase();
243
+ const sanitizeEnvironment = (env) => {
244
+ if (env === undefined) {
245
+ return undefined;
246
+ }
247
+ const filtered = Object.fromEntries(Object.entries(env).filter(([key]) => ENV_ALLOWLIST.has(key)));
248
+ return Object.keys(filtered).length === 0 ? undefined : filtered;
249
+ };
250
+ export const sanitizeResearchToolOutput = (value) => {
251
+ if (typeof value === "string") {
252
+ return redactEvidenceSummary(value).summary;
253
+ }
254
+ if (Array.isArray(value)) {
255
+ return value.map((entry) => sanitizeResearchToolOutput(entry));
256
+ }
257
+ if (typeof value === "object" && value !== null) {
258
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, sanitizeResearchToolOutput(entry)]));
259
+ }
260
+ return value;
261
+ };
262
+ //# sourceMappingURL=command-policy.js.map