@martinloop/mcp 0.3.7 → 0.3.9

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 (88) hide show
  1. package/README.md +196 -137
  2. package/dist/resources.js +148 -148
  3. package/dist/server.js +0 -0
  4. package/dist/tools/tool-support.js +11 -1
  5. package/dist/vendor/adapters/claude-cli.d.ts +2 -2
  6. package/dist/vendor/adapters/claude-cli.js +127 -51
  7. package/dist/vendor/adapters/codex-launcher.js +10 -1
  8. package/dist/vendor/adapters/openai-compatible.js +6 -6
  9. package/package.json +86 -76
  10. package/server.json +21 -21
  11. package/dist/vendor/adapters/adapters/src/claude-cli.d.ts +0 -146
  12. package/dist/vendor/adapters/adapters/src/claude-cli.js +0 -1100
  13. package/dist/vendor/adapters/adapters/src/cli-bridge.d.ts +0 -103
  14. package/dist/vendor/adapters/adapters/src/cli-bridge.js +0 -569
  15. package/dist/vendor/adapters/adapters/src/codex-launcher.d.ts +0 -78
  16. package/dist/vendor/adapters/adapters/src/codex-launcher.js +0 -663
  17. package/dist/vendor/adapters/adapters/src/direct-provider.d.ts +0 -10
  18. package/dist/vendor/adapters/adapters/src/direct-provider.js +0 -40
  19. package/dist/vendor/adapters/adapters/src/index.d.ts +0 -8
  20. package/dist/vendor/adapters/adapters/src/index.js +0 -8
  21. package/dist/vendor/adapters/adapters/src/openai-compatible.d.ts +0 -62
  22. package/dist/vendor/adapters/adapters/src/openai-compatible.js +0 -306
  23. package/dist/vendor/adapters/adapters/src/runtime-support.d.ts +0 -17
  24. package/dist/vendor/adapters/adapters/src/runtime-support.js +0 -59
  25. package/dist/vendor/adapters/adapters/src/stub-agent-cli.d.ts +0 -8
  26. package/dist/vendor/adapters/adapters/src/stub-agent-cli.js +0 -40
  27. package/dist/vendor/adapters/adapters/src/stub-direct-provider.d.ts +0 -8
  28. package/dist/vendor/adapters/adapters/src/stub-direct-provider.js +0 -12
  29. package/dist/vendor/adapters/adapters/src/verifier-only.d.ts +0 -9
  30. package/dist/vendor/adapters/adapters/src/verifier-only.js +0 -63
  31. package/dist/vendor/adapters/contracts/src/context-graph.d.ts +0 -48
  32. package/dist/vendor/adapters/contracts/src/context-graph.js +0 -26
  33. package/dist/vendor/adapters/contracts/src/execution-policy.d.ts +0 -78
  34. package/dist/vendor/adapters/contracts/src/execution-policy.js +0 -43
  35. package/dist/vendor/adapters/contracts/src/governance.d.ts +0 -24
  36. package/dist/vendor/adapters/contracts/src/governance.js +0 -11
  37. package/dist/vendor/adapters/contracts/src/identity.d.ts +0 -29
  38. package/dist/vendor/adapters/contracts/src/identity.js +0 -30
  39. package/dist/vendor/adapters/contracts/src/index.d.ts +0 -412
  40. package/dist/vendor/adapters/contracts/src/index.js +0 -225
  41. package/dist/vendor/adapters/contracts/src/operator.d.ts +0 -19
  42. package/dist/vendor/adapters/contracts/src/operator.js +0 -11
  43. package/dist/vendor/adapters/contracts/src/trajectory.d.ts +0 -26
  44. package/dist/vendor/adapters/contracts/src/trajectory.js +0 -27
  45. package/dist/vendor/adapters/core/src/compiler.d.ts +0 -52
  46. package/dist/vendor/adapters/core/src/compiler.js +0 -52
  47. package/dist/vendor/adapters/core/src/context-graph.d.ts +0 -3
  48. package/dist/vendor/adapters/core/src/context-graph.js +0 -371
  49. package/dist/vendor/adapters/core/src/context-integrity.d.ts +0 -26
  50. package/dist/vendor/adapters/core/src/context-integrity.js +0 -80
  51. package/dist/vendor/adapters/core/src/grounding.d.ts +0 -38
  52. package/dist/vendor/adapters/core/src/grounding.js +0 -273
  53. package/dist/vendor/adapters/core/src/identity.d.ts +0 -20
  54. package/dist/vendor/adapters/core/src/identity.js +0 -86
  55. package/dist/vendor/adapters/core/src/index.d.ts +0 -186
  56. package/dist/vendor/adapters/core/src/index.js +0 -1495
  57. package/dist/vendor/adapters/core/src/leash.d.ts +0 -48
  58. package/dist/vendor/adapters/core/src/leash.js +0 -497
  59. package/dist/vendor/adapters/core/src/persistence/compiler.d.ts +0 -18
  60. package/dist/vendor/adapters/core/src/persistence/compiler.js +0 -34
  61. package/dist/vendor/adapters/core/src/persistence/index.d.ts +0 -10
  62. package/dist/vendor/adapters/core/src/persistence/index.js +0 -5
  63. package/dist/vendor/adapters/core/src/persistence/integrity.d.ts +0 -39
  64. package/dist/vendor/adapters/core/src/persistence/integrity.js +0 -252
  65. package/dist/vendor/adapters/core/src/persistence/ledger.d.ts +0 -23
  66. package/dist/vendor/adapters/core/src/persistence/ledger.js +0 -9
  67. package/dist/vendor/adapters/core/src/persistence/memory-store.d.ts +0 -63
  68. package/dist/vendor/adapters/core/src/persistence/memory-store.js +0 -115
  69. package/dist/vendor/adapters/core/src/persistence/runs-reader.d.ts +0 -66
  70. package/dist/vendor/adapters/core/src/persistence/runs-reader.js +0 -140
  71. package/dist/vendor/adapters/core/src/persistence/store.d.ts +0 -89
  72. package/dist/vendor/adapters/core/src/persistence/store.js +0 -125
  73. package/dist/vendor/adapters/core/src/persistence/trace-store.d.ts +0 -85
  74. package/dist/vendor/adapters/core/src/persistence/trace-store.js +0 -125
  75. package/dist/vendor/adapters/core/src/policy-compiler.d.ts +0 -2
  76. package/dist/vendor/adapters/core/src/policy-compiler.js +0 -195
  77. package/dist/vendor/adapters/core/src/policy.d.ts +0 -156
  78. package/dist/vendor/adapters/core/src/policy.js +0 -704
  79. package/dist/vendor/adapters/core/src/repo-analyzer.d.ts +0 -53
  80. package/dist/vendor/adapters/core/src/repo-analyzer.js +0 -263
  81. package/dist/vendor/adapters/core/src/rollback.d.ts +0 -15
  82. package/dist/vendor/adapters/core/src/rollback.js +0 -253
  83. package/dist/vendor/adapters/core/src/routing.d.ts +0 -82
  84. package/dist/vendor/adapters/core/src/routing.js +0 -336
  85. package/dist/vendor/adapters/core/src/test-integrity.d.ts +0 -64
  86. package/dist/vendor/adapters/core/src/test-integrity.js +0 -197
  87. package/dist/vendor/adapters/core/src/trajectory.d.ts +0 -18
  88. package/dist/vendor/adapters/core/src/trajectory.js +0 -295
@@ -1,48 +0,0 @@
1
- import type { ApprovalPolicy, ExecutionProfile, LoopTask } from "../../../contracts/index.js";
2
- export type SafetySurface = "command" | "filesystem" | "secret" | "spend" | "network" | "dependency";
3
- export type SafetyViolationKind = "command_blocked" | "path_not_allowed" | "path_denied" | "path_outside_repo" | "network_blocked" | "dependency_approval_required" | "migration_approval_required" | "config_change_approval_required" | "secret_value" | "protected_path";
4
- export interface SafetyViolation {
5
- kind: SafetyViolationKind;
6
- message: string;
7
- command?: string;
8
- file?: string;
9
- match?: string;
10
- }
11
- export interface SafetyLeashDecision {
12
- allowed: boolean;
13
- blocked: boolean;
14
- riskLevel: "safe" | "blocked";
15
- surface: SafetySurface;
16
- profile?: ExecutionProfile;
17
- blockedCommands: string[];
18
- violations: SafetyViolation[];
19
- reason?: string;
20
- }
21
- export interface ResolvedExecutionProfile {
22
- name: ExecutionProfile;
23
- networkMode: "off" | "allowlisted" | "open";
24
- allowedNetworkDomains: string[];
25
- requireDependencyApproval: boolean;
26
- requireMigrationApproval: boolean;
27
- requireConfigApproval: boolean;
28
- }
29
- export declare function evaluateVerificationLeash(task: Pick<LoopTask, "verificationPlan" | "verificationStack" | "executionProfile" | "allowedNetworkDomains">): SafetyLeashDecision;
30
- export declare function evaluateFilesystemLeash(input: {
31
- repoRoot?: string;
32
- changedFiles: string[];
33
- allowedPaths?: string[];
34
- deniedPaths?: string[];
35
- }): SafetyLeashDecision;
36
- export declare function evaluateSecretLeash(input: {
37
- values: string[];
38
- }): SafetyLeashDecision;
39
- export declare function resolveExecutionProfile(input: {
40
- executionProfile?: ExecutionProfile;
41
- allowedNetworkDomains?: string[];
42
- }): ResolvedExecutionProfile;
43
- export declare function evaluateChangeApprovalLeash(input: {
44
- changedFiles: string[];
45
- executionProfile?: ExecutionProfile;
46
- approvalPolicy?: ApprovalPolicy;
47
- }): SafetyLeashDecision;
48
- export declare function redactSecretsFromText(input: string): string;
@@ -1,497 +0,0 @@
1
- import { isAbsolute, relative, resolve } from "node:path";
2
- const BLOCKED_PATTERNS = [
3
- /(^|[\s;&|`(])rm\s+-rf(\s|$)/iu,
4
- /git\s+reset\s+--hard/iu,
5
- /git\s+clean\s+-fd/iu,
6
- /curl\b[^\n|]*\|\s*(sh|bash)/iu,
7
- /wget\b[^\n|]*\|\s*(sh|bash)/iu,
8
- /(^|[\s;&|`(])sudo(\s|$)/iu,
9
- /(^|[\s;&|`(])mkfs(\.|\s|$)/iu,
10
- /(^|[\s;&|`(])dd\s+if=/iu,
11
- /(shutdown|reboot)(\s|$)/iu,
12
- /:\(\)\s*\{\s*:\|:&\s*\}\s*;\s*:/iu,
13
- /chmod\s+-R\s+777\s+\//iu,
14
- /(kubectl|docker)\s+.*\b(delete|prune|rm)\b/iu,
15
- /ssh\s+/iu,
16
- /scp\s+/iu,
17
- // bash/sh -c "<destructive command>" wrappers — flags the wrapper shape directly,
18
- // since a naive regex on the outer command misses the destructive inner command.
19
- /\b(?:bash|sh|zsh)\s+-c\s+["'`]/iu,
20
- // recursive directory deletion via `find ... -delete` / `find ... -exec rm`
21
- /\bfind\s+\S+(?:\s+-[a-z-]+(?:\s+\S+)?)*\s+-delete\b/iu,
22
- /\bfind\s+\S+(?:\s+-[a-z-]+(?:\s+\S+)?)*\s+-exec\s+rm\b/iu,
23
- // scripting-language recursive deletion one-liners
24
- /\bshutil\.rmtree\s*\(/iu,
25
- /\bos\.(?:remove|rmdir|removedirs|unlink)\s*\(/iu,
26
- /\.(?:rm|rmdir|unlink)(?:Sync)?\s*\(/iu,
27
- /\brimraf\s*\(/iu,
28
- // Windows destructive deletion / formatting patterns
29
- /\b(?:cmd(?:\.exe)?\s+\/c\s+)?del(?:\.exe)?\s+\/[^\n]*(?:\bs\b|\bq\b|\bf\b)/iu,
30
- /\b(?:cmd(?:\.exe)?\s+\/c\s+)?rmdir(?:\.exe)?\s+\/[^\n]*\bs\b/iu,
31
- /\bremove-item\b[^\n]*(?:-recurse|-r)\b[^\n]*(?:-force|-fo)\b/iu,
32
- /\b(?:format-volume|diskpart)\b/iu
33
- ];
34
- /**
35
- * Detects `rm` invocations that combine recursive + force flags regardless of
36
- * flag ordering/grouping (`-rf`, `-fr`, `-r -f`, `--recursive --force`),
37
- * absolute-path invocation (`/bin/rm`, `/usr/bin/rm`), case, or `${IFS}`-style
38
- * shell obfuscation — all of which slip past the literal `rm\s+-rf` pattern.
39
- */
40
- function commandContainsDestructiveRemoval(command) {
41
- const normalized = command.replace(/\$\{?IFS\}?/giu, " ").toLowerCase();
42
- const rmInvocation = /(?:^|[\s;&|`(])(?:[^\s;&|`(]+\/)?rm\s+([^\n;|`]+)/giu;
43
- let match;
44
- while ((match = rmInvocation.exec(normalized)) !== null) {
45
- const args = match[1] ?? "";
46
- const hasRecursive = /(?:^|\s)-[a-z]*r[a-z]*(?:\s|$)|--recursive\b/u.test(args);
47
- const hasForce = /(?:^|\s)-[a-z]*f[a-z]*(?:\s|$)|--force\b/u.test(args);
48
- if (hasRecursive && hasForce) {
49
- return true;
50
- }
51
- }
52
- return false;
53
- }
54
- const SECRET_PATTERNS = [
55
- {
56
- kind: "secret_value",
57
- pattern: /\bOPENAI_API_KEY\s*=\s*[^\s"'`]+/giu,
58
- replacement: "OPENAI_API_KEY=[REDACTED_SECRET]"
59
- },
60
- {
61
- kind: "secret_value",
62
- pattern: /\bsk-[A-Za-z0-9_-]{8,}\b/gu,
63
- replacement: "[REDACTED_SECRET]"
64
- },
65
- {
66
- kind: "secret_value",
67
- pattern: /\bghp_[A-Za-z0-9_]{16,}\b/gu,
68
- replacement: "[REDACTED_SECRET]"
69
- },
70
- {
71
- kind: "secret_value",
72
- pattern: /\bgithub_pat_[A-Za-z0-9_]{20,}\b/gu,
73
- replacement: "[REDACTED_SECRET]"
74
- },
75
- {
76
- kind: "secret_value",
77
- pattern: /\b(?:gho|ghu|ghs|ghr)_[A-Za-z0-9_]{16,}\b/gu,
78
- replacement: "[REDACTED_SECRET]"
79
- },
80
- {
81
- kind: "secret_value",
82
- pattern: /\bAKIA[0-9A-Z]{16}\b/gu,
83
- replacement: "[REDACTED_SECRET]"
84
- },
85
- {
86
- kind: "secret_value",
87
- pattern: /\b(?:aws_secret_access_key|AWS_SECRET_ACCESS_KEY)\s*[:=]\s*[^\s"'`]+/giu,
88
- replacement: "AWS_SECRET_ACCESS_KEY=[REDACTED_SECRET]"
89
- },
90
- {
91
- kind: "secret_value",
92
- pattern: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/giu,
93
- replacement: "[REDACTED_SECRET]"
94
- },
95
- {
96
- kind: "secret_value",
97
- pattern: /\bAIza[0-9A-Za-z_-]{30,}\b/gu,
98
- replacement: "[REDACTED_SECRET]"
99
- },
100
- {
101
- kind: "secret_value",
102
- pattern: /-----BEGIN(?:\s+[A-Z0-9]+)*\s+PRIVATE KEY-----[\s\S]*?-----END(?:\s+[A-Z0-9]+)*\s+PRIVATE KEY-----/gu,
103
- replacement: "[REDACTED_SECRET]"
104
- },
105
- {
106
- kind: "secret_value",
107
- pattern: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/gu,
108
- replacement: "[REDACTED_SECRET]"
109
- },
110
- {
111
- kind: "secret_value",
112
- pattern: /\b(?:api[_-]?key|secret|password|passwd|token)\s*[:=]\s*["']?[A-Za-z0-9_\-/+=]{12,}["']?/giu,
113
- replacement: "[REDACTED_SECRET]"
114
- }
115
- ];
116
- const PROTECTED_PATH_PATTERNS = [
117
- {
118
- kind: "protected_path",
119
- pattern: /\B\.env(?!\.example\b)(?:\.[A-Za-z0-9._-]+)?\b/giu,
120
- replacement: "[REDACTED_PATH]"
121
- },
122
- {
123
- kind: "protected_path",
124
- pattern: /\bid_rsa\b/giu,
125
- replacement: "[REDACTED_PATH]"
126
- },
127
- {
128
- kind: "protected_path",
129
- pattern: /\b[A-Za-z0-9._/-]+\.(pem|p12|key)\b/giu,
130
- replacement: "[REDACTED_PATH]"
131
- }
132
- ];
133
- export function evaluateVerificationLeash(task) {
134
- const commands = [
135
- ...(task.verificationPlan ?? []),
136
- ...((task.verificationStack ?? []).map((step) => step.command))
137
- ].filter(Boolean);
138
- const profile = resolveExecutionProfile(task);
139
- const blockedCommands = commands.filter((command) => BLOCKED_PATTERNS.some((pattern) => pattern.test(command)) ||
140
- commandContainsDestructiveRemoval(command));
141
- const violations = blockedCommands.map((command) => ({
142
- kind: "command_blocked",
143
- command,
144
- message: `Blocked destructive verifier command: ${command}`
145
- }));
146
- if (blockedCommands.length > 0) {
147
- return {
148
- allowed: false,
149
- blocked: true,
150
- riskLevel: "blocked",
151
- surface: "command",
152
- profile: profile.name,
153
- blockedCommands,
154
- violations,
155
- reason: "Safety leash blocked destructive or unbounded verifier commands."
156
- };
157
- }
158
- const networkViolations = commands
159
- .map((command) => buildNetworkViolation(command, profile))
160
- .filter((violation) => Boolean(violation));
161
- if (networkViolations.length > 0) {
162
- return {
163
- allowed: false,
164
- blocked: true,
165
- riskLevel: "blocked",
166
- surface: "network",
167
- profile: profile.name,
168
- blockedCommands: commands.filter((command) => buildNetworkViolation(command, profile)),
169
- violations: networkViolations,
170
- reason: `Safety leash blocked outbound network access for the ${profile.name} profile.`
171
- };
172
- }
173
- return {
174
- allowed: true,
175
- blocked: false,
176
- riskLevel: "safe",
177
- surface: "command",
178
- profile: profile.name,
179
- blockedCommands: [],
180
- violations: []
181
- };
182
- }
183
- export function evaluateFilesystemLeash(input) {
184
- const violations = [];
185
- for (const rawFile of input.changedFiles) {
186
- const normalized = normalizeChangedFile(rawFile, input.repoRoot);
187
- if (normalized.outsideRepo) {
188
- violations.push({
189
- kind: "path_outside_repo",
190
- file: rawFile,
191
- message: `Changed file is outside the configured repo root: ${rawFile}`
192
- });
193
- continue;
194
- }
195
- const file = normalized.file;
196
- if (!file) {
197
- continue;
198
- }
199
- if ((input.deniedPaths ?? []).some((pattern) => matchesPathPattern(file, pattern))) {
200
- violations.push({
201
- kind: "path_denied",
202
- file,
203
- message: `Changed file matches a denylisted path: ${file}`
204
- });
205
- continue;
206
- }
207
- const allowedPaths = input.allowedPaths ?? [];
208
- if (allowedPaths.length > 0 && !allowedPaths.some((pattern) => matchesPathPattern(file, pattern))) {
209
- violations.push({
210
- kind: "path_not_allowed",
211
- file,
212
- message: `Changed file is outside the allowed paths: ${file}`
213
- });
214
- }
215
- }
216
- if (violations.length > 0) {
217
- return {
218
- allowed: false,
219
- blocked: true,
220
- riskLevel: "blocked",
221
- surface: "filesystem",
222
- blockedCommands: [],
223
- violations,
224
- reason: "Safety leash blocked file changes outside the allowed repo contract."
225
- };
226
- }
227
- return {
228
- allowed: true,
229
- blocked: false,
230
- riskLevel: "safe",
231
- surface: "filesystem",
232
- blockedCommands: [],
233
- violations: []
234
- };
235
- }
236
- export function evaluateSecretLeash(input) {
237
- const violations = [];
238
- for (const value of input.values) {
239
- if (!value)
240
- continue;
241
- for (const rule of SECRET_PATTERNS) {
242
- for (const match of value.matchAll(rule.pattern)) {
243
- const matched = match[0];
244
- if (!matched)
245
- continue;
246
- violations.push({
247
- kind: rule.kind,
248
- match: matched,
249
- message: "Secret-like credential value detected in the runtime context."
250
- });
251
- }
252
- }
253
- }
254
- if (violations.length > 0) {
255
- return {
256
- allowed: false,
257
- blocked: true,
258
- riskLevel: "blocked",
259
- surface: "secret",
260
- blockedCommands: [],
261
- violations,
262
- reason: "Safety leash blocked secret-like credential values from entering the runtime context."
263
- };
264
- }
265
- return {
266
- allowed: true,
267
- blocked: false,
268
- riskLevel: "safe",
269
- surface: "secret",
270
- blockedCommands: [],
271
- violations: []
272
- };
273
- }
274
- export function resolveExecutionProfile(input) {
275
- const name = input.executionProfile ?? "strict_local";
276
- const allowedNetworkDomains = [...(input.allowedNetworkDomains ?? [])];
277
- switch (name) {
278
- case "ci_safe":
279
- return {
280
- name,
281
- networkMode: "off",
282
- allowedNetworkDomains,
283
- requireDependencyApproval: true,
284
- requireMigrationApproval: true,
285
- requireConfigApproval: true
286
- };
287
- case "staging_controlled":
288
- return {
289
- name,
290
- networkMode: allowedNetworkDomains.length > 0 ? "allowlisted" : "off",
291
- allowedNetworkDomains,
292
- requireDependencyApproval: true,
293
- requireMigrationApproval: true,
294
- requireConfigApproval: true
295
- };
296
- case "research_untrusted":
297
- return {
298
- name,
299
- networkMode: allowedNetworkDomains.length > 0 ? "allowlisted" : "open",
300
- allowedNetworkDomains,
301
- requireDependencyApproval: true,
302
- requireMigrationApproval: true,
303
- requireConfigApproval: true
304
- };
305
- case "strict_local":
306
- default:
307
- return {
308
- name: "strict_local",
309
- networkMode: "off",
310
- allowedNetworkDomains,
311
- requireDependencyApproval: true,
312
- requireMigrationApproval: true,
313
- requireConfigApproval: true
314
- };
315
- }
316
- }
317
- export function evaluateChangeApprovalLeash(input) {
318
- const profile = resolveExecutionProfile({
319
- executionProfile: input.executionProfile
320
- });
321
- const violations = [];
322
- for (const file of input.changedFiles.map((entry) => entry.replace(/\\/gu, "/"))) {
323
- if (isDependencyFile(file) && profile.requireDependencyApproval && !input.approvalPolicy?.dependencyAdds) {
324
- violations.push({
325
- kind: "dependency_approval_required",
326
- file,
327
- message: `Dependency-related file change requires approval in the ${profile.name} profile: ${file}`
328
- });
329
- continue;
330
- }
331
- if (isMigrationFile(file) && profile.requireMigrationApproval && !input.approvalPolicy?.migrations) {
332
- violations.push({
333
- kind: "migration_approval_required",
334
- file,
335
- message: `Migration change requires approval in the ${profile.name} profile: ${file}`
336
- });
337
- continue;
338
- }
339
- if (isConfigChangeFile(file) && profile.requireConfigApproval && !input.approvalPolicy?.configChanges) {
340
- violations.push({
341
- kind: "config_change_approval_required",
342
- file,
343
- message: `Deployment or configuration change requires approval in the ${profile.name} profile: ${file}`
344
- });
345
- }
346
- }
347
- if (violations.length > 0) {
348
- return {
349
- allowed: false,
350
- blocked: true,
351
- riskLevel: "blocked",
352
- surface: "dependency",
353
- profile: profile.name,
354
- blockedCommands: [],
355
- violations,
356
- reason: "Safety leash blocked dependency, migration, or configuration changes that require approval."
357
- };
358
- }
359
- return {
360
- allowed: true,
361
- blocked: false,
362
- riskLevel: "safe",
363
- surface: "dependency",
364
- profile: profile.name,
365
- blockedCommands: [],
366
- violations: []
367
- };
368
- }
369
- export function redactSecretsFromText(input) {
370
- let output = input;
371
- for (const rule of [...SECRET_PATTERNS, ...PROTECTED_PATH_PATTERNS]) {
372
- output = output.replace(rule.pattern, rule.replacement);
373
- }
374
- return output;
375
- }
376
- function normalizeChangedFile(file, repoRoot) {
377
- const normalizedInput = file.replace(/\\/gu, "/");
378
- if (!repoRoot) {
379
- return {
380
- file: normalizedInput,
381
- outsideRepo: normalizedInput.startsWith("../") || normalizedInput.includes("/../")
382
- };
383
- }
384
- const absoluteRoot = resolve(repoRoot);
385
- const absoluteFile = isAbsolute(file) ? resolve(file) : resolve(absoluteRoot, file);
386
- const repoRelative = relative(absoluteRoot, absoluteFile).replace(/\\/gu, "/");
387
- if (repoRelative.length === 0 ||
388
- repoRelative === ".." ||
389
- repoRelative.startsWith("../") ||
390
- isAbsolute(repoRelative)) {
391
- return { outsideRepo: true };
392
- }
393
- return {
394
- file: repoRelative,
395
- outsideRepo: false
396
- };
397
- }
398
- function matchesPathPattern(file, pattern) {
399
- const normalizedFile = normalizePathForMatching(file);
400
- const normalizedPattern = normalizePathForMatching(pattern);
401
- if (!normalizedPattern.includes("*")) {
402
- return (normalizedFile === normalizedPattern ||
403
- normalizedFile.startsWith(`${normalizedPattern.replace(/\/$/u, "")}/`));
404
- }
405
- const regexStr = normalizedPattern
406
- .replace(/[.+^${}()|[\]\\]/gu, "\\$&")
407
- .replace(/\*\*/gu, "__DOUBLESTAR__")
408
- .replace(/\*/gu, "[^/]*")
409
- .replace(/__DOUBLESTAR__/gu, ".*");
410
- return new RegExp(`^${regexStr}$`, "u").test(normalizedFile);
411
- }
412
- function normalizePathForMatching(value) {
413
- return value
414
- .replace(/\\/gu, "/")
415
- .replace(/^\.\//u, "")
416
- .replace(/\/{2,}/gu, "/")
417
- .replace(/\/$/u, "");
418
- }
419
- function buildNetworkViolation(command, profile) {
420
- const targets = extractNetworkTargets(command);
421
- if (targets.length === 0) {
422
- return undefined;
423
- }
424
- if (profile.networkMode === "open") {
425
- return undefined;
426
- }
427
- if (profile.networkMode === "allowlisted") {
428
- const blockedTarget = targets.find((target) => !profile.allowedNetworkDomains.some((domain) => target === domain || target.endsWith(`.${domain}`)));
429
- if (!blockedTarget) {
430
- return undefined;
431
- }
432
- return {
433
- kind: "network_blocked",
434
- command,
435
- match: blockedTarget,
436
- message: `Network target is not allowlisted for the ${profile.name} profile: ${blockedTarget}`
437
- };
438
- }
439
- return {
440
- kind: "network_blocked",
441
- command,
442
- match: targets[0],
443
- message: `Outbound network access is blocked for the ${profile.name} profile.`
444
- };
445
- }
446
- function extractNetworkTargets(command) {
447
- if (!/\b(curl|wget|invoke-webrequest|iwr|httpie|http)\b/iu.test(command)) {
448
- return [];
449
- }
450
- return [...command.matchAll(/https?:\/\/([^/\s"'`]+)/giu)]
451
- .map((match) => match[1]?.toLowerCase())
452
- .filter((value) => Boolean(value));
453
- }
454
- function isDependencyFile(file) {
455
- const normalized = file.replace(/\\/gu, "/");
456
- return [
457
- "package.json",
458
- "package-lock.json",
459
- "pnpm-lock.yaml",
460
- "yarn.lock",
461
- "bun.lock",
462
- "bun.lockb",
463
- "pyproject.toml",
464
- "requirements.txt",
465
- "Cargo.toml",
466
- "Cargo.lock"
467
- ].includes(normalized.split("/").at(-1) ?? normalized);
468
- }
469
- function isMigrationFile(file) {
470
- const normalized = file.replace(/\\/gu, "/");
471
- return (normalized.includes("/migrations/") ||
472
- normalized.startsWith("migrations/") ||
473
- normalized.includes("prisma/migrations/"));
474
- }
475
- function isConfigChangeFile(file) {
476
- const normalized = file.replace(/\\/gu, "/");
477
- const leaf = normalized.split("/").at(-1) ?? normalized;
478
- if ([
479
- "vercel.json",
480
- "netlify.toml",
481
- "wrangler.toml",
482
- "docker-compose.yml",
483
- "docker-compose.yaml",
484
- "compose.yml",
485
- "compose.yaml",
486
- "fly.toml",
487
- "railway.json"
488
- ].includes(leaf)) {
489
- return true;
490
- }
491
- return (normalized.startsWith(".github/workflows/") ||
492
- normalized.startsWith("deploy/") ||
493
- normalized.startsWith("deployment/") ||
494
- normalized.startsWith("infra/") ||
495
- normalized.startsWith("infrastructure/") ||
496
- normalized.startsWith("ops/"));
497
- }
@@ -1,18 +0,0 @@
1
- import { type CompilerAdapterRequest, type PromptPacket } from "../compiler.js";
2
- import type { RunStore } from "./store.js";
3
- export interface CompileResult {
4
- packet: PromptPacket;
5
- }
6
- /**
7
- * Compile a deterministic PromptPacket from the request state and, when a
8
- * store is provided, persist it as compiled-context.json in the attempt
9
- * artifact directory.
10
- *
11
- * R3.7: Context compiler produces deterministic compiled-context.json.
12
- * R3.8: Any attempt prompt can be reconstructed from disk artifacts alone.
13
- */
14
- export declare function compileAndPersistContext(request: CompilerAdapterRequest, options: {
15
- attemptIndex: number;
16
- store?: RunStore;
17
- now?: string;
18
- }): Promise<CompileResult>;
@@ -1,34 +0,0 @@
1
- import { compilePromptPacket } from "../compiler.js";
2
- import { makeLedgerEvent } from "./ledger.js";
3
- /**
4
- * Compile a deterministic PromptPacket from the request state and, when a
5
- * store is provided, persist it as compiled-context.json in the attempt
6
- * artifact directory.
7
- *
8
- * R3.7: Context compiler produces deterministic compiled-context.json.
9
- * R3.8: Any attempt prompt can be reconstructed from disk artifacts alone.
10
- */
11
- export async function compileAndPersistContext(request, options) {
12
- const packet = compilePromptPacket(request);
13
- const ts = options.now ?? new Date().toISOString();
14
- if (options.store) {
15
- // Write compiled-context.json to attempt artifact directory
16
- await options.store.writeAttemptArtifacts(request.loopId, options.attemptIndex, {
17
- compiledContext: packet
18
- });
19
- // Append prompt.compiled ledger event
20
- await options.store.appendLedger(request.loopId, makeLedgerEvent({
21
- kind: "prompt.compiled",
22
- runId: request.loopId,
23
- attemptIndex: options.attemptIndex,
24
- payload: {
25
- attemptId: request.attemptId,
26
- attemptNumber: packet.attemptNumber,
27
- priorFailurePatterns: packet.priorFailurePatterns,
28
- budgetEnvelope: packet.budgetEnvelope
29
- },
30
- timestamp: ts
31
- }));
32
- }
33
- return { packet };
34
- }
@@ -1,10 +0,0 @@
1
- export { makeLedgerEvent } from "./ledger.js";
2
- export type { LedgerEvent, LedgerEventDraft, LedgerEventKind } from "./ledger.js";
3
- export { resolveReceiptIntegrityPath, verifyReceiptIntegrityFromFiles, writeReceiptIntegrityMaterial } from "./integrity.js";
4
- export type { ReceiptIntegrityChainEntry, StoredReceiptIntegrityMaterial } from "./integrity.js";
5
- export { artifactDir, createFileRunStore, resolveRunsRoot, runDir } from "./store.js";
6
- export type { AttemptArtifacts, RunContract, RunStore } from "./store.js";
7
- export { readAllLoopRecords, readLatestLoopRecord, readLatestLoopRecordFromFile, readLoopRecordsFromFile } from "./runs-reader.js";
8
- export type { LoopAttemptRecord, LoopRunRecord } from "./runs-reader.js";
9
- export { compileAndPersistContext } from "./compiler.js";
10
- export type { CompileResult } from "./compiler.js";
@@ -1,5 +0,0 @@
1
- export { makeLedgerEvent } from "./ledger.js";
2
- export { resolveReceiptIntegrityPath, verifyReceiptIntegrityFromFiles, writeReceiptIntegrityMaterial } from "./integrity.js";
3
- export { artifactDir, createFileRunStore, resolveRunsRoot, runDir } from "./store.js";
4
- export { readAllLoopRecords, readLatestLoopRecord, readLatestLoopRecordFromFile, readLoopRecordsFromFile } from "./runs-reader.js";
5
- export { compileAndPersistContext } from "./compiler.js";
@@ -1,39 +0,0 @@
1
- import type { LoopRecord, ReceiptIntegritySummary, ReceiptScope } from "../../../../contracts/index.js";
2
- export interface ReceiptIntegrityChainEntry {
3
- index: number;
4
- eventId?: string;
5
- type?: string;
6
- kind?: string;
7
- timestamp?: string;
8
- prevHash: string;
9
- entryHash: string;
10
- }
11
- export interface StoredReceiptIntegrityMaterial {
12
- schemaVersion: "martin.receipt-integrity.v1";
13
- runId: string;
14
- keyId: string;
15
- signedAt: string;
16
- scope?: ReceiptScope;
17
- loopRecordSha256: string;
18
- ledgerSha256: string;
19
- ledgerHeadHash: string;
20
- entryCount: number;
21
- chain: ReceiptIntegrityChainEntry[];
22
- signatureHmacSha256: string;
23
- }
24
- export declare function resolveReceiptIntegrityRoot(env?: NodeJS.ProcessEnv): string;
25
- export declare function writeReceiptIntegrityMaterial(input: {
26
- runId: string;
27
- runsRoot: string;
28
- loopRecord: LoopRecord;
29
- ledgerEntries: unknown[];
30
- scope?: ReceiptScope;
31
- signedAt?: string;
32
- }): Promise<StoredReceiptIntegrityMaterial | undefined>;
33
- export declare function verifyReceiptIntegrityFromFiles(input: {
34
- runId: string;
35
- runsRoot: string;
36
- loopRecordPath: string;
37
- ledgerPath: string;
38
- }): Promise<ReceiptIntegritySummary>;
39
- export declare function resolveReceiptIntegrityPath(runsRoot: string, runId: string): string;