@martinloop/mcp 0.3.6 → 0.3.7

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 (102) hide show
  1. package/README.md +137 -145
  2. package/dist/discovery-metadata.d.ts +1 -1
  3. package/dist/discovery-metadata.js +1 -1
  4. package/dist/package-version.d.ts +1 -1
  5. package/dist/package-version.js +1 -1
  6. package/dist/resources.d.ts +2 -1
  7. package/dist/resources.js +251 -197
  8. package/dist/server-validation.d.ts +1 -1
  9. package/dist/server-validation.js +11 -16
  10. package/dist/server.d.ts +0 -23
  11. package/dist/server.js +7 -152
  12. package/dist/tools/run-loop.d.ts +2 -1
  13. package/dist/tools/run-loop.js +5 -1
  14. package/dist/tools/tool-support.js +1 -0
  15. package/dist/vendor/adapters/adapters/src/claude-cli.d.ts +146 -0
  16. package/dist/vendor/adapters/adapters/src/claude-cli.js +1100 -0
  17. package/dist/vendor/adapters/adapters/src/cli-bridge.d.ts +103 -0
  18. package/dist/vendor/adapters/adapters/src/cli-bridge.js +569 -0
  19. package/dist/vendor/adapters/adapters/src/codex-launcher.d.ts +78 -0
  20. package/dist/vendor/adapters/adapters/src/codex-launcher.js +663 -0
  21. package/dist/vendor/adapters/adapters/src/direct-provider.d.ts +10 -0
  22. package/dist/vendor/adapters/adapters/src/direct-provider.js +40 -0
  23. package/dist/vendor/adapters/adapters/src/index.d.ts +8 -0
  24. package/dist/vendor/adapters/adapters/src/index.js +8 -0
  25. package/dist/vendor/adapters/adapters/src/openai-compatible.d.ts +62 -0
  26. package/dist/vendor/adapters/adapters/src/openai-compatible.js +306 -0
  27. package/dist/vendor/adapters/adapters/src/runtime-support.d.ts +17 -0
  28. package/dist/vendor/adapters/adapters/src/runtime-support.js +59 -0
  29. package/dist/vendor/adapters/adapters/src/stub-agent-cli.d.ts +8 -0
  30. package/dist/vendor/adapters/adapters/src/stub-agent-cli.js +40 -0
  31. package/dist/vendor/adapters/adapters/src/stub-direct-provider.d.ts +8 -0
  32. package/dist/vendor/adapters/adapters/src/stub-direct-provider.js +12 -0
  33. package/dist/vendor/adapters/adapters/src/verifier-only.d.ts +9 -0
  34. package/dist/vendor/adapters/adapters/src/verifier-only.js +63 -0
  35. package/dist/vendor/adapters/claude-cli.d.ts +2 -2
  36. package/dist/vendor/adapters/claude-cli.js +28 -42
  37. package/dist/vendor/adapters/contracts/src/context-graph.d.ts +48 -0
  38. package/dist/vendor/adapters/contracts/src/context-graph.js +26 -0
  39. package/dist/vendor/adapters/contracts/src/execution-policy.d.ts +78 -0
  40. package/dist/vendor/adapters/contracts/src/execution-policy.js +43 -0
  41. package/dist/vendor/adapters/contracts/src/governance.d.ts +24 -0
  42. package/dist/vendor/adapters/contracts/src/governance.js +11 -0
  43. package/dist/vendor/adapters/contracts/src/identity.d.ts +29 -0
  44. package/dist/vendor/adapters/contracts/src/identity.js +30 -0
  45. package/dist/vendor/adapters/contracts/src/index.d.ts +412 -0
  46. package/dist/vendor/adapters/contracts/src/index.js +225 -0
  47. package/dist/vendor/adapters/contracts/src/operator.d.ts +19 -0
  48. package/dist/vendor/adapters/contracts/src/operator.js +11 -0
  49. package/dist/vendor/adapters/contracts/src/trajectory.d.ts +26 -0
  50. package/dist/vendor/adapters/contracts/src/trajectory.js +27 -0
  51. package/dist/vendor/adapters/core/src/compiler.d.ts +52 -0
  52. package/dist/vendor/adapters/core/src/compiler.js +52 -0
  53. package/dist/vendor/adapters/core/src/context-graph.d.ts +3 -0
  54. package/dist/vendor/adapters/core/src/context-graph.js +371 -0
  55. package/dist/vendor/adapters/core/src/context-integrity.d.ts +26 -0
  56. package/dist/vendor/adapters/core/src/context-integrity.js +80 -0
  57. package/dist/vendor/adapters/core/src/grounding.d.ts +38 -0
  58. package/dist/vendor/adapters/core/src/grounding.js +273 -0
  59. package/dist/vendor/adapters/core/src/identity.d.ts +20 -0
  60. package/dist/vendor/adapters/core/src/identity.js +86 -0
  61. package/dist/vendor/adapters/core/src/index.d.ts +186 -0
  62. package/dist/vendor/adapters/core/src/index.js +1495 -0
  63. package/dist/vendor/adapters/core/src/leash.d.ts +48 -0
  64. package/dist/vendor/adapters/core/src/leash.js +497 -0
  65. package/dist/vendor/adapters/core/src/persistence/compiler.d.ts +18 -0
  66. package/dist/vendor/adapters/core/src/persistence/compiler.js +34 -0
  67. package/dist/vendor/adapters/core/src/persistence/index.d.ts +10 -0
  68. package/dist/vendor/adapters/core/src/persistence/index.js +5 -0
  69. package/dist/vendor/adapters/core/src/persistence/integrity.d.ts +39 -0
  70. package/dist/vendor/adapters/core/src/persistence/integrity.js +252 -0
  71. package/dist/vendor/adapters/core/src/persistence/ledger.d.ts +23 -0
  72. package/dist/vendor/adapters/core/src/persistence/ledger.js +9 -0
  73. package/dist/vendor/adapters/core/src/persistence/memory-store.d.ts +63 -0
  74. package/dist/vendor/adapters/core/src/persistence/memory-store.js +115 -0
  75. package/dist/vendor/adapters/core/src/persistence/runs-reader.d.ts +66 -0
  76. package/dist/vendor/adapters/core/src/persistence/runs-reader.js +140 -0
  77. package/dist/vendor/adapters/core/src/persistence/store.d.ts +89 -0
  78. package/dist/vendor/adapters/core/src/persistence/store.js +125 -0
  79. package/dist/vendor/adapters/core/src/persistence/trace-store.d.ts +85 -0
  80. package/dist/vendor/adapters/core/src/persistence/trace-store.js +125 -0
  81. package/dist/vendor/adapters/core/src/policy-compiler.d.ts +2 -0
  82. package/dist/vendor/adapters/core/src/policy-compiler.js +195 -0
  83. package/dist/vendor/adapters/core/src/policy.d.ts +156 -0
  84. package/dist/vendor/adapters/core/src/policy.js +704 -0
  85. package/dist/vendor/adapters/core/src/repo-analyzer.d.ts +53 -0
  86. package/dist/vendor/adapters/core/src/repo-analyzer.js +263 -0
  87. package/dist/vendor/adapters/core/src/rollback.d.ts +15 -0
  88. package/dist/vendor/adapters/core/src/rollback.js +253 -0
  89. package/dist/vendor/adapters/core/src/routing.d.ts +82 -0
  90. package/dist/vendor/adapters/core/src/routing.js +336 -0
  91. package/dist/vendor/adapters/core/src/test-integrity.d.ts +64 -0
  92. package/dist/vendor/adapters/core/src/test-integrity.js +197 -0
  93. package/dist/vendor/adapters/core/src/trajectory.d.ts +18 -0
  94. package/dist/vendor/adapters/core/src/trajectory.js +295 -0
  95. package/dist/vendor/adapters/openai-compatible.js +6 -6
  96. package/dist/vendor/adapters/verifier-only.js +2 -2
  97. package/dist/vendor/contracts/index.d.ts +1 -1
  98. package/dist/vendor/core/compiler.js +4 -9
  99. package/dist/vendor/core/index.js +1 -88
  100. package/dist/vendor/core/rollback.js +2 -3
  101. package/package.json +76 -76
  102. package/server.json +21 -21
@@ -0,0 +1,273 @@
1
+ import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { extname, join, relative } from "node:path";
4
+ const TEXT_EXTENSIONS = new Set([
5
+ ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs",
6
+ ".json", ".md", ".yaml", ".yml", ".py", ".go",
7
+ ".rs", ".java", ".sh"
8
+ ]);
9
+ const IGNORED_DIRS = new Set([
10
+ ".git", "node_modules", ".next", "dist", "build",
11
+ ".turbo", "coverage", ".npm-cache", ".pnpm-store"
12
+ ]);
13
+ const MAX_FILE_BYTES = 64_000;
14
+ const MAX_FILES = 500;
15
+ export function resolveGroundingRoot(env = process.env) {
16
+ return env["MARTIN_GROUNDING_DIR"]?.trim() ||
17
+ join(homedir(), ".martin", "grounding");
18
+ }
19
+ export async function loadOrBuildRepoGroundingIndex(repoRoot) {
20
+ const cachePath = getGroundingCachePath(repoRoot);
21
+ try {
22
+ const cached = JSON.parse(await readFile(cachePath, "utf8"));
23
+ if (cached?.schemaVersion === "martin.grounding.v1") {
24
+ return cached;
25
+ }
26
+ }
27
+ catch { }
28
+ const index = await buildRepoGroundingIndex(repoRoot);
29
+ try {
30
+ await mkdir(resolveGroundingRoot(), { recursive: true });
31
+ await writeFile(cachePath, JSON.stringify(index, null, 2), "utf8");
32
+ }
33
+ catch {
34
+ // Cache persistence is best-effort; runtime grounding must still work even
35
+ // when the local filesystem blocks writes to ~/.martin/grounding.
36
+ }
37
+ return index;
38
+ }
39
+ export async function buildRepoGroundingIndex(repoRoot) {
40
+ const files = [];
41
+ const discovered = await walk(repoRoot, repoRoot, files, { count: 0 });
42
+ return {
43
+ schemaVersion: "martin.grounding.v1",
44
+ repoRoot,
45
+ createdAt: new Date().toISOString(),
46
+ fileCount: discovered.count,
47
+ files
48
+ };
49
+ }
50
+ export function queryRepoGroundingIndex(index, query, limit = 6) {
51
+ const terms = tokenize(query);
52
+ if (terms.length === 0)
53
+ return [];
54
+ return index.files
55
+ .map((file) => {
56
+ let score = 0;
57
+ const matched = new Set();
58
+ for (const term of terms) {
59
+ if (file.path.toLowerCase().includes(term)) {
60
+ score += 5;
61
+ matched.add(term);
62
+ }
63
+ if (file.keywords.some((keyword) => keyword === term)) {
64
+ score += 3;
65
+ matched.add(term);
66
+ }
67
+ if (file.symbols.some((symbol) => symbol.toLowerCase().includes(term))) {
68
+ score += 4;
69
+ matched.add(term);
70
+ }
71
+ }
72
+ if (score === 0)
73
+ return undefined;
74
+ return {
75
+ path: file.path,
76
+ score,
77
+ matchedTerms: [...matched],
78
+ symbols: file.symbols.slice(0, 5)
79
+ };
80
+ })
81
+ .filter((item) => Boolean(item))
82
+ .sort((a, b) => b.score - a.score || a.path.localeCompare(b.path))
83
+ .slice(0, limit);
84
+ }
85
+ function getGroundingCachePath(repoRoot) {
86
+ return join(resolveGroundingRoot(), `${Buffer.from(repoRoot).toString("base64url")}.json`);
87
+ }
88
+ async function walk(repoRoot, currentDir, files, state) {
89
+ if (state.count >= MAX_FILES)
90
+ return state;
91
+ const entries = await readdir(currentDir, { withFileTypes: true });
92
+ for (const entry of entries) {
93
+ if (state.count >= MAX_FILES)
94
+ break;
95
+ const absPath = join(currentDir, entry.name);
96
+ if (entry.isDirectory()) {
97
+ if (!IGNORED_DIRS.has(entry.name)) {
98
+ await walk(repoRoot, absPath, files, state);
99
+ }
100
+ continue;
101
+ }
102
+ if (!entry.isFile())
103
+ continue;
104
+ if (!TEXT_EXTENSIONS.has(extname(entry.name).toLowerCase()))
105
+ continue;
106
+ try {
107
+ const content = await readFile(absPath, "utf8");
108
+ if (content.length > MAX_FILE_BYTES)
109
+ continue;
110
+ const relPath = relative(repoRoot, absPath).replace(/\\/g, "/");
111
+ files.push({
112
+ path: relPath,
113
+ symbols: extractSymbols(content),
114
+ keywords: extractKeywords(relPath, content)
115
+ });
116
+ state.count += 1;
117
+ }
118
+ catch { }
119
+ }
120
+ return state;
121
+ }
122
+ function extractSymbols(content) {
123
+ const out = new Set();
124
+ const patterns = [
125
+ /export\s+(?:async\s+)?function\s+([A-Za-z0-9_]+)/g,
126
+ /export\s+class\s+([A-Za-z0-9_]+)/g,
127
+ /export\s+const\s+([A-Za-z0-9_]+)/g,
128
+ /function\s+([A-Za-z0-9_]+)/g,
129
+ /class\s+([A-Za-z0-9_]+)/g,
130
+ /def\s+([A-Za-z0-9_]+)/g
131
+ ];
132
+ for (const pattern of patterns) {
133
+ for (const match of content.matchAll(pattern)) {
134
+ if (match[1])
135
+ out.add(match[1]);
136
+ }
137
+ }
138
+ return [...out].slice(0, 12);
139
+ }
140
+ function extractKeywords(relPath, content) {
141
+ const out = new Set();
142
+ for (const part of relPath.split(/[\/.\-_]+/u)) {
143
+ if (part.length >= 3)
144
+ out.add(part.toLowerCase());
145
+ }
146
+ for (const term of tokenize(content.split("\n").slice(0, 10).join(" "))) {
147
+ out.add(term);
148
+ }
149
+ return [...out].slice(0, 20);
150
+ }
151
+ function tokenize(input) {
152
+ const stopWords = new Set([
153
+ "the", "and", "for", "with", "from", "that",
154
+ "this", "into", "only", "keep", "fix", "make", "loop"
155
+ ]);
156
+ return [...new Set(input.toLowerCase().match(/[a-z0-9_]{3,}/g) ?? [])].filter((term) => !stopWords.has(term));
157
+ }
158
+ export function scanPatchForGroundingViolations(diff, index, options = {}) {
159
+ const violations = [];
160
+ const resolvedFiles = [];
161
+ const indexedPaths = new Set(index.files.map((file) => file.path));
162
+ const indexedSymbols = new Set(index.files.flatMap((file) => file.symbols.map((symbol) => symbol.toLowerCase())));
163
+ const referencedFiles = new Set();
164
+ const diffFilePattern = /^(?:---|\+\+\+)\s+[ab]\/(.+)$/gm;
165
+ for (const match of diff.matchAll(diffFilePattern)) {
166
+ const filePath = match[1]?.trim();
167
+ if (filePath && filePath !== "/dev/null") {
168
+ referencedFiles.add(filePath);
169
+ }
170
+ }
171
+ for (const filePath of referencedFiles) {
172
+ if (indexedPaths.has(filePath)) {
173
+ resolvedFiles.push(filePath);
174
+ }
175
+ else {
176
+ violations.push({
177
+ kind: "file_not_found",
178
+ reference: filePath,
179
+ sourceHint: `diff header references ${filePath}`
180
+ });
181
+ }
182
+ if (options.allowedPaths?.length) {
183
+ const isAllowed = options.allowedPaths.some((pattern) => matchesGlobPattern(filePath, pattern));
184
+ if (!isAllowed) {
185
+ violations.push({
186
+ kind: "patch_outside_allowed_paths",
187
+ reference: filePath,
188
+ sourceHint: `${filePath} is outside allowed paths: ${options.allowedPaths.join(", ")}`
189
+ });
190
+ }
191
+ }
192
+ }
193
+ const addedLinePattern = /^\+(?!\+\+)(.+)$/gm;
194
+ const importPattern = /(?:import|require)\s*(?:.*\s+from\s+)?['"]([^'"]+)['"]/g;
195
+ const identifierPattern = /\b([A-Za-z_][A-Za-z0-9_]{2,})\b/g;
196
+ const symbolKeywords = new Set([
197
+ "const",
198
+ "let",
199
+ "var",
200
+ "function",
201
+ "class",
202
+ "return",
203
+ "export",
204
+ "import",
205
+ "from",
206
+ "await",
207
+ "async",
208
+ "new",
209
+ "true",
210
+ "false",
211
+ "null",
212
+ "undefined"
213
+ ]);
214
+ for (const lineMatch of diff.matchAll(addedLinePattern)) {
215
+ const line = lineMatch[1] ?? "";
216
+ for (const importMatch of line.matchAll(importPattern)) {
217
+ const reference = importMatch[1] ?? "";
218
+ if (!reference.startsWith(".") && !reference.startsWith("/")) {
219
+ continue;
220
+ }
221
+ const normalized = reference
222
+ .replace(/^\.\//, "")
223
+ .replace(/\.(js|ts|tsx|jsx)$/, "");
224
+ const hasMatch = index.files.some((file) => {
225
+ const withoutExt = file.path.replace(/\.(js|ts|tsx|jsx)$/, "");
226
+ return withoutExt.endsWith(normalized) || withoutExt.includes(normalized);
227
+ });
228
+ if (!hasMatch) {
229
+ violations.push({
230
+ kind: "import_not_found",
231
+ reference,
232
+ sourceHint: `import in added line: ${line.trim().slice(0, 80)}`
233
+ });
234
+ }
235
+ }
236
+ for (const symbolMatch of line.matchAll(identifierPattern)) {
237
+ const symbol = symbolMatch[1];
238
+ if (!symbol)
239
+ continue;
240
+ if (symbolKeywords.has(symbol))
241
+ continue;
242
+ if (symbol.toUpperCase() === symbol)
243
+ continue;
244
+ if (indexedSymbols.has(symbol.toLowerCase()))
245
+ continue;
246
+ if (/^[a-z]+$/.test(symbol) && symbol.length <= 4)
247
+ continue;
248
+ violations.push({
249
+ kind: "symbol_not_found",
250
+ reference: symbol,
251
+ sourceHint: `symbol in added line: ${line.trim().slice(0, 80)}`
252
+ });
253
+ }
254
+ }
255
+ // Detect content-only diff (only comments, whitespace, empty lines added)
256
+ const substantiveLinePattern = /^\+(?!\+\+)\s*(?!\/\/|\/\*|\*|#).*\S/gm;
257
+ const hasSubstantiveLines = substantiveLinePattern.test(diff);
258
+ const contentOnly = !hasSubstantiveLines && diff.includes("+");
259
+ return {
260
+ violations,
261
+ scannedReferences: referencedFiles.size,
262
+ resolvedFiles,
263
+ contentOnly
264
+ };
265
+ }
266
+ function matchesGlobPattern(filePath, pattern) {
267
+ const regexStr = pattern
268
+ .replace(/[.+^${}()|[\]\\]/g, "\\$&")
269
+ .replace(/\*\*/g, "__DOUBLESTAR__")
270
+ .replace(/\*/g, "[^/]*")
271
+ .replace(/__DOUBLESTAR__/g, ".*");
272
+ return new RegExp(`^${regexStr}$`).test(filePath);
273
+ }
@@ -0,0 +1,20 @@
1
+ import { type IdentityAttestation, type IdentityClaims, type IdentityToken } from "../../../contracts/index.js";
2
+ export interface LocalIdentityAuthority {
3
+ keyId: string;
4
+ algorithm: "ed25519";
5
+ privateKeyPem: string;
6
+ publicKeyPem: string;
7
+ }
8
+ export declare function createLocalIdentityAuthority(input?: {
9
+ keyId?: string;
10
+ }): LocalIdentityAuthority;
11
+ export declare function issueIdentityToken(input: {
12
+ authority: Pick<LocalIdentityAuthority, "keyId" | "algorithm" | "privateKeyPem">;
13
+ claims: IdentityClaims;
14
+ }): IdentityToken;
15
+ export declare function verifyIdentityToken(input: {
16
+ token: IdentityToken;
17
+ publicKeyPem: string;
18
+ now?: string;
19
+ }): IdentityAttestation;
20
+ export declare function hasIdentityScope(token: IdentityToken, requiredScope: string): boolean;
@@ -0,0 +1,86 @@
1
+ import { createPrivateKey, createPublicKey, generateKeyPairSync, sign, verify } from "node:crypto";
2
+ import { cloneIdentityAttestation, cloneIdentityClaims, cloneIdentityToken } from "../../../contracts/index.js";
3
+ export function createLocalIdentityAuthority(input = {}) {
4
+ const { privateKey, publicKey } = generateKeyPairSync("ed25519");
5
+ return {
6
+ keyId: input.keyId ?? `martin-local-${Date.now().toString(36)}`,
7
+ algorithm: "ed25519",
8
+ privateKeyPem: privateKey.export({ format: "pem", type: "pkcs8" }).toString(),
9
+ publicKeyPem: publicKey.export({ format: "pem", type: "spki" }).toString()
10
+ };
11
+ }
12
+ export function issueIdentityToken(input) {
13
+ const claims = cloneIdentityClaims(input.claims);
14
+ const signer = createPrivateKey(input.authority.privateKeyPem);
15
+ const payload = serializeIdentityClaims(claims);
16
+ const signature = sign(null, payload, signer).toString("base64");
17
+ return cloneIdentityToken({
18
+ schemaVersion: "martin.identity.v1",
19
+ algorithm: input.authority.algorithm,
20
+ keyId: input.authority.keyId,
21
+ claims,
22
+ signature
23
+ });
24
+ }
25
+ export function verifyIdentityToken(input) {
26
+ const token = cloneIdentityToken(input.token);
27
+ const verifier = createPublicKey(input.publicKeyPem);
28
+ const payload = serializeIdentityClaims(token.claims);
29
+ const verifiedAt = input.now ?? new Date().toISOString();
30
+ if (token.schemaVersion !== "martin.identity.v1") {
31
+ return cloneIdentityAttestation({
32
+ valid: false,
33
+ verifiedAt,
34
+ reason: `Unsupported identity schema version '${token.schemaVersion}'.`,
35
+ token
36
+ });
37
+ }
38
+ const signatureValid = verify(null, payload, verifier, Buffer.from(token.signature, "base64"));
39
+ if (!signatureValid) {
40
+ return cloneIdentityAttestation({
41
+ valid: false,
42
+ verifiedAt,
43
+ reason: "Identity signature verification failed.",
44
+ token
45
+ });
46
+ }
47
+ const expiresAt = token.claims.expiresAt ? Date.parse(token.claims.expiresAt) : undefined;
48
+ if (expiresAt !== undefined && Number.isFinite(expiresAt) && expiresAt <= Date.parse(verifiedAt)) {
49
+ return cloneIdentityAttestation({
50
+ valid: false,
51
+ verifiedAt,
52
+ reason: "Identity token is expired.",
53
+ token
54
+ });
55
+ }
56
+ return cloneIdentityAttestation({
57
+ valid: true,
58
+ verifiedAt,
59
+ reason: `Identity token for role '${token.claims.role}' verified successfully.`,
60
+ token
61
+ });
62
+ }
63
+ export function hasIdentityScope(token, requiredScope) {
64
+ const required = requiredScope.trim().toLowerCase();
65
+ if (required.length === 0) {
66
+ return false;
67
+ }
68
+ return token.claims.scopes.some((scope) => scope.trim().toLowerCase() === required);
69
+ }
70
+ function serializeIdentityClaims(claims) {
71
+ return Buffer.from(JSON.stringify(claims, sortKeys), "utf8");
72
+ }
73
+ function sortKeys(_, value) {
74
+ if (Array.isArray(value)) {
75
+ return value;
76
+ }
77
+ if (value && typeof value === "object") {
78
+ return Object.keys(value)
79
+ .sort()
80
+ .reduce((sorted, key) => {
81
+ sorted[key] = value[key];
82
+ return sorted;
83
+ }, {});
84
+ }
85
+ return value;
86
+ }
@@ -0,0 +1,186 @@
1
+ import { type ApprovalPolicy, type CostProvenance, type ExecutionProfile, type FailureClass, type InterventionType, type LoopArtifact, type LoopAttempt, type LoopBudget, type ProviderUsageSettlement, type MutationMode, type LoopRecord, type LoopTask, type ReceiptScope } from "../../../contracts/index.js";
2
+ import { classifyFailure, computeEvidenceVector, evaluatePatchDecision, evaluateCostGovernor, evaluateBudgetPreflight, inferExit, nextPolicyPhase, policyPhaseToLifecycleState, scorePatchDecision, selectRecoveryRecipe, type ExitDecision } from "./policy.js";
3
+ import { evaluateChangeApprovalLeash, evaluateFilesystemLeash, evaluateSecretLeash, redactSecretsFromText, resolveExecutionProfile, evaluateVerificationLeash } from "./leash.js";
4
+ import { buildRepoGroundingIndex, loadOrBuildRepoGroundingIndex, queryRepoGroundingIndex, scanPatchForGroundingViolations } from "./grounding.js";
5
+ import { captureRollbackBoundary, listAttemptChangedFilesSinceBoundary, restoreRollbackBoundary } from "./rollback.js";
6
+ import { type RunStore } from "./persistence/index.js";
7
+ export type { ApprovalPolicy, BudgetPreflightEstimate, BudgetSettlement, CostProvenance, EvidenceVector, ExecutionProfile, FailureClass, InterventionType, PatchDecision, PatchDecisionArtifact, PatchDecisionReasonCode, PatchScore, MutationMode, RollbackBoundaryArtifact, RollbackBoundaryStrategy, RollbackFileSnapshot, RollbackOutcomeArtifact, RollbackOutcomeStatus, PolicyPhase, CallStage, AgentRole, FirstDelta, RoutingEconomics } from "../../../contracts/index.js";
8
+ export { classifyFailure, computeEvidenceVector, evaluatePatchDecision, evaluateCostGovernor, evaluateBudgetPreflight, inferExit, nextPolicyPhase, policyPhaseToLifecycleState, scorePatchDecision, selectRecoveryRecipe, evaluateVerificationLeash, evaluateFilesystemLeash, evaluateChangeApprovalLeash, evaluateSecretLeash, resolveExecutionProfile, redactSecretsFromText, buildRepoGroundingIndex, loadOrBuildRepoGroundingIndex, queryRepoGroundingIndex, scanPatchForGroundingViolations, captureRollbackBoundary, listAttemptChangedFilesSinceBoundary, restoreRollbackBoundary };
9
+ export type { BudgetPreflightDecision, BudgetPreflightInput, CostGovernorState, EvidenceVectorInput, EvaluatedPatchDecision, ExitDecision, FailureAssessment, PatchDecisionInput, RecoveryDecision, RecoveryRecipe } from "./policy.js";
10
+ export type { ResolvedExecutionProfile, SafetyLeashDecision, SafetyViolation } from "./leash.js";
11
+ export type { GroundingScanResult, GroundingViolation, GroundingViolationKind, RepoGroundingHit, RepoGroundingIndex } from "./grounding.js";
12
+ export { buildContextGraphSnapshot, queryContextGraph } from "./context-graph.js";
13
+ export { createLocalIdentityAuthority, hasIdentityScope, issueIdentityToken, verifyIdentityToken } from "./identity.js";
14
+ export type { LocalIdentityAuthority } from "./identity.js";
15
+ export { compileExecutionPolicy } from "./policy-compiler.js";
16
+ export { assessTrajectory, decideCircuitBreak } from "./trajectory.js";
17
+ export { classifyRoute, evaluatePreworkBurnPolicy, resolveModelForTier, selectBestEngine } from "./routing.js";
18
+ export type { RouteDecision, RouteClassificationInput, AvailableEngine } from "./routing.js";
19
+ export { validateTestIntegrity, snapshotTestFiles, identifyNewTests, findTestFiles, isTestFile, extractImports, hasTrivialAssertionsOnly, importsPreExistingCode } from "./test-integrity.js";
20
+ export type { TestIntegrityReport, TestIntegrityFinding } from "./test-integrity.js";
21
+ export { analyzeRepoStyle, buildPromptDirectives } from "./repo-analyzer.js";
22
+ export type { RepoStyleProfile } from "./repo-analyzer.js";
23
+ export { runContextIntegrityPrecheck } from "./context-integrity.js";
24
+ export type { ContextIntegrityPrecheck, ContextIntegrityVerdict } from "./context-integrity.js";
25
+ export { compilePromptPacket } from "./compiler.js";
26
+ export type { PromptPacket, CompilerAdapterRequest } from "./compiler.js";
27
+ export { createFileRunStore, makeLedgerEvent, readAllLoopRecords, readLatestLoopRecord, readLatestLoopRecordFromFile, readLoopRecordsFromFile, resolveRunsRoot, resolveReceiptIntegrityPath, verifyReceiptIntegrityFromFiles, writeReceiptIntegrityMaterial } from "./persistence/index.js";
28
+ export type { AttemptArtifacts, LedgerEvent, LedgerEventKind, LoopAttemptRecord, LoopRunRecord, ReceiptIntegrityChainEntry, RunContract, RunStore, StoredReceiptIntegrityMaterial } from "./persistence/index.js";
29
+ export { compileAndPersistContext } from "./persistence/index.js";
30
+ export type { CompileResult } from "./persistence/index.js";
31
+ export { appendMemory, readMemoryEntries, getPreference, buildMemorySummary, recordPreference, recordConsent } from "./persistence/memory-store.js";
32
+ export type { MemoryEntry, MemoryKind, MemorySummary } from "./persistence/memory-store.js";
33
+ export { appendTraceEntry, readTraceEntries, aggregateTraces, getHistoricalDirectSuccessRate } from "./persistence/trace-store.js";
34
+ export type { TraceEntry, TraceAggregation } from "./persistence/trace-store.js";
35
+ export interface MartinAdapterRequest {
36
+ loopId: string;
37
+ attemptId: string;
38
+ context: {
39
+ taskTitle: string;
40
+ objective: string;
41
+ verificationPlan: string[];
42
+ verificationStack?: LoopTask["verificationStack"];
43
+ mutationMode?: MutationMode;
44
+ /** Absolute path to the repository root. */
45
+ repoRoot?: string;
46
+ /** Glob patterns for files the agent may modify. Empty = no restriction. */
47
+ allowedPaths?: string[];
48
+ /** Glob patterns for files the agent must never modify. */
49
+ deniedPaths?: string[];
50
+ /** Human-readable acceptance criteria injected into the prompt. */
51
+ acceptanceCriteria?: string[];
52
+ executionProfile?: ExecutionProfile;
53
+ allowedNetworkDomains?: string[];
54
+ approvalPolicy?: ApprovalPolicy;
55
+ focus: string;
56
+ remainingBudgetUsd: number;
57
+ remainingIterations: number;
58
+ remainingTokens: number;
59
+ };
60
+ previousAttempts: LoopAttempt[];
61
+ }
62
+ export interface MartinVerificationStep {
63
+ command: string;
64
+ launched: boolean;
65
+ exitCode?: number;
66
+ timedOut: boolean;
67
+ fastFail?: boolean;
68
+ detail?: string;
69
+ }
70
+ export interface MartinVerificationOutcome {
71
+ passed: boolean;
72
+ summary: string;
73
+ steps?: MartinVerificationStep[];
74
+ warnings?: string[];
75
+ }
76
+ export interface MartinAdapterResult {
77
+ status: "completed" | "failed";
78
+ summary: string;
79
+ usage: {
80
+ actualUsd: number;
81
+ estimatedUsd?: number;
82
+ tokensIn: number;
83
+ tokensOut: number;
84
+ cachedInputTokens?: number;
85
+ reasoningTokensOut?: number;
86
+ provenance?: CostProvenance;
87
+ providerSettlement?: ProviderUsageSettlement;
88
+ };
89
+ verification: {
90
+ passed: boolean;
91
+ summary: string;
92
+ steps?: MartinVerificationStep[];
93
+ warnings?: string[];
94
+ };
95
+ execution?: {
96
+ changedFiles?: string[];
97
+ diffStats?: {
98
+ filesChanged: number;
99
+ addedLines: number;
100
+ deletedLines: number;
101
+ };
102
+ structuredErrors?: Array<{
103
+ file: string;
104
+ line?: number;
105
+ col?: number;
106
+ code?: string;
107
+ message: string;
108
+ }>;
109
+ };
110
+ artifacts?: LoopArtifact[];
111
+ failure?: {
112
+ message: string;
113
+ classHint?: FailureClass;
114
+ };
115
+ }
116
+ export interface MartinAdapter {
117
+ adapterId: string;
118
+ kind: "direct-provider" | "agent-cli";
119
+ label: string;
120
+ metadata: {
121
+ providerId: string;
122
+ model: string;
123
+ transport?: "cli" | "http" | "routed_http";
124
+ capabilities?: {
125
+ preflight?: boolean;
126
+ usageSettlement?: boolean;
127
+ diffArtifacts?: boolean;
128
+ structuredErrors?: boolean;
129
+ cachingSignals?: boolean;
130
+ workspaceMutations?: boolean;
131
+ };
132
+ [key: string]: unknown;
133
+ };
134
+ execute(request: MartinAdapterRequest): Promise<MartinAdapterResult>;
135
+ withModel?(model: string): MartinAdapter;
136
+ }
137
+ export interface DistilledContext {
138
+ focus: string;
139
+ recentAttempts: LoopAttempt[];
140
+ constraints: {
141
+ remainingBudgetUsd: number;
142
+ remainingIterations: number;
143
+ remainingTokens: number;
144
+ };
145
+ }
146
+ export interface AttemptPolicyDecision {
147
+ allowed: boolean;
148
+ reason: string;
149
+ recommendedIntervention?: InterventionType;
150
+ trajectoryAssessment?: import("../../../contracts/index.js").TrajectoryAssessment;
151
+ circuitBreakDecision?: import("../../../contracts/index.js").CircuitBreakDecision;
152
+ }
153
+ /**
154
+ * Admission gate — must pass before any attempt is executed.
155
+ * Evaluates budget headroom, oscillation, and repetitive failure patterns.
156
+ * PolicyPhase remains explicit: attempts are only admitted in ADMIT phase.
157
+ */
158
+ export declare function evaluateAttemptPolicy(input: {
159
+ request: MartinAdapterRequest;
160
+ projectedUsd: number;
161
+ }): AttemptPolicyDecision;
162
+ export interface RunMartinInput {
163
+ workspaceId: string;
164
+ projectId: string;
165
+ teamId?: string;
166
+ task: LoopTask;
167
+ budget: LoopBudget;
168
+ metadata?: Record<string, string>;
169
+ adapter: MartinAdapter;
170
+ now?: () => string;
171
+ idFactory?: (prefix: string) => string;
172
+ maxRecentAttempts?: number;
173
+ fallbackModels?: string[];
174
+ fallbackAdapters?: MartinAdapter[];
175
+ receiptScope?: ReceiptScope;
176
+ /** Optional persistence store. When provided, runMartin writes artifacts on each lifecycle event. */
177
+ store?: RunStore;
178
+ }
179
+ export interface RunMartinResult {
180
+ loop: LoopRecord;
181
+ decision: ExitDecision;
182
+ }
183
+ export declare function distillContext(loop: Pick<LoopRecord, "task" | "budget" | "cost" | "attempts">, options?: {
184
+ maxRecentAttempts?: number;
185
+ }): DistilledContext;
186
+ export declare function runMartin(input: RunMartinInput): Promise<RunMartinResult>;