@martinloop/mcp 0.3.2 → 0.3.4
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.
- package/README.md +112 -107
- package/dist/discovery-support.js +2 -2
- package/dist/prompts.d.ts +2 -1
- package/dist/resources.d.ts +2 -1
- package/dist/resources.js +147 -147
- package/dist/server-validation.js +5 -2
- package/dist/server.js +5 -4
- package/dist/tools/eval.js +29 -5
- package/dist/tools/execution-policy.d.ts +11 -0
- package/dist/tools/execution-policy.js +47 -0
- package/dist/tools/run-dossier.js +2 -2
- package/dist/tools/run-loop.d.ts +2 -1
- package/dist/tools/run-loop.js +15 -2
- package/dist/tools/run-store.js +166 -6
- package/dist/tools/tool-support.d.ts +3 -2
- package/dist/tools/tool-support.js +112 -18
- package/dist/tools/triage-runs.js +31 -6
- package/dist/vendor/adapters/claude-cli.d.ts +1 -1
- package/dist/vendor/adapters/claude-cli.js +71 -20
- package/dist/vendor/adapters/cli-bridge.d.ts +6 -0
- package/dist/vendor/adapters/cli-bridge.js +91 -7
- package/dist/vendor/adapters/codex-launcher.js +65 -8
- package/dist/vendor/adapters/openai-compatible.d.ts +1 -1
- package/dist/vendor/adapters/openai-compatible.js +7 -7
- package/dist/vendor/adapters/verifier-only.js +1 -1
- package/dist/vendor/contracts/adapter-capabilities.d.ts +17 -0
- package/dist/vendor/contracts/adapter-capabilities.js +35 -0
- package/dist/vendor/contracts/context-graph.d.ts +48 -0
- package/dist/vendor/contracts/context-graph.js +26 -0
- package/dist/vendor/contracts/execution-policy.d.ts +62 -0
- package/dist/vendor/contracts/execution-policy.js +34 -0
- package/dist/vendor/contracts/governance.d.ts +6 -3
- package/dist/vendor/contracts/identity.d.ts +29 -0
- package/dist/vendor/contracts/identity.js +30 -0
- package/dist/vendor/contracts/index.d.ts +13 -2
- package/dist/vendor/contracts/index.js +4 -0
- package/dist/vendor/contracts/observation.d.ts +21 -0
- package/dist/vendor/contracts/observation.js +27 -0
- package/dist/vendor/contracts/trajectory.d.ts +26 -0
- package/dist/vendor/contracts/trajectory.js +27 -0
- package/dist/vendor/contracts/verification.d.ts +28 -0
- package/dist/vendor/contracts/verification.js +7 -0
- package/dist/vendor/core/context-graph.d.ts +3 -0
- package/dist/vendor/core/context-graph.js +371 -0
- package/dist/vendor/core/context-integrity.js +1 -1
- package/dist/vendor/core/grounding.js +1 -1
- package/dist/vendor/core/identity.d.ts +20 -0
- package/dist/vendor/core/identity.js +86 -0
- package/dist/vendor/core/index.d.ts +7 -0
- package/dist/vendor/core/index.js +63 -9
- package/dist/vendor/core/leash.js +1 -1
- package/dist/vendor/core/persistence/integrity.d.ts +1 -0
- package/dist/vendor/core/persistence/integrity.js +7 -3
- package/dist/vendor/core/persistence/runs-reader.d.ts +14 -0
- package/dist/vendor/core/persistence/runs-reader.js +61 -4
- package/dist/vendor/core/policy-compiler.d.ts +2 -0
- package/dist/vendor/core/policy-compiler.js +195 -0
- package/dist/vendor/core/policy.d.ts +2 -0
- package/dist/vendor/core/policy.js +71 -4
- package/dist/vendor/core/rollback.js +32 -12
- package/dist/vendor/core/trajectory.d.ts +18 -0
- package/dist/vendor/core/trajectory.js +295 -0
- package/package.json +76 -75
- package/server.json +21 -21
|
@@ -248,24 +248,81 @@ function hasSuccessfulCommandExecution(events) {
|
|
|
248
248
|
}
|
|
249
249
|
export function resolveCliCommandAvailability(command, options = {}) {
|
|
250
250
|
const platform = options.platform ?? process.platform;
|
|
251
|
+
const env = options.env ?? process.env;
|
|
251
252
|
const spawnSyncImpl = options.spawnSyncImpl ?? spawnSync;
|
|
252
253
|
const discovery = readLocatorCandidates(command, platform, spawnSyncImpl);
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
254
|
+
if (discovery.candidates.length > 0) {
|
|
255
|
+
const resolvedPath = discovery.candidates[0];
|
|
256
|
+
return {
|
|
256
257
|
command,
|
|
257
258
|
available: true,
|
|
258
259
|
locator: discovery.locator,
|
|
259
260
|
detail: `${command} is available on PATH.`,
|
|
260
261
|
...(resolvedPath ? { resolvedPath } : {}),
|
|
261
262
|
candidatePaths: discovery.candidates
|
|
262
|
-
}
|
|
263
|
-
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
// PATH didn't find it — search common install locations before giving up.
|
|
266
|
+
const offPathCandidate = discoverCommandOffPath(command, platform, env);
|
|
267
|
+
if (offPathCandidate) {
|
|
268
|
+
return {
|
|
264
269
|
command,
|
|
265
|
-
available:
|
|
266
|
-
locator: discovery
|
|
267
|
-
detail: `${command}
|
|
270
|
+
available: true,
|
|
271
|
+
locator: "off-path-discovery",
|
|
272
|
+
detail: `${command} found at ${offPathCandidate} (not on PATH, auto-discovered).`,
|
|
273
|
+
resolvedPath: offPathCandidate,
|
|
274
|
+
candidatePaths: [offPathCandidate]
|
|
268
275
|
};
|
|
276
|
+
}
|
|
277
|
+
return {
|
|
278
|
+
command,
|
|
279
|
+
available: false,
|
|
280
|
+
locator: discovery.locator,
|
|
281
|
+
detail: `${command} is not installed. ${suggestInstall(command)}`
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
function discoverCommandOffPath(command, platform, env) {
|
|
285
|
+
const home = env.HOME ?? env.USERPROFILE ?? "";
|
|
286
|
+
const dirs = [];
|
|
287
|
+
if (platform === "win32") {
|
|
288
|
+
const appData = env.APPDATA;
|
|
289
|
+
if (appData)
|
|
290
|
+
dirs.push(join(appData, "npm"));
|
|
291
|
+
const localAppData = env.LOCALAPPDATA;
|
|
292
|
+
if (localAppData)
|
|
293
|
+
dirs.push(join(localAppData, "OpenAI", "Codex", "bin"));
|
|
294
|
+
if (home)
|
|
295
|
+
dirs.push(join(home, "scoop", "shims"));
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
dirs.push("/usr/local/bin", "/opt/homebrew/bin");
|
|
299
|
+
if (home) {
|
|
300
|
+
dirs.push(join(home, ".local", "bin"), join(home, ".npm-global", "bin"), join(home, ".bun", "bin"), join(home, ".cargo", "bin"));
|
|
301
|
+
}
|
|
302
|
+
const nvmDir = env.NVM_DIR;
|
|
303
|
+
if (nvmDir)
|
|
304
|
+
dirs.push(join(nvmDir, "current", "bin"));
|
|
305
|
+
}
|
|
306
|
+
const extensions = platform === "win32"
|
|
307
|
+
? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").map((e) => e.trim().toLowerCase()).filter(Boolean)
|
|
308
|
+
: [""];
|
|
309
|
+
for (const dir of dirs) {
|
|
310
|
+
for (const ext of extensions) {
|
|
311
|
+
const candidate = ext ? join(dir, `${command}${ext}`) : join(dir, command);
|
|
312
|
+
if (existsSync(candidate)) {
|
|
313
|
+
return candidate;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return undefined;
|
|
318
|
+
}
|
|
319
|
+
function suggestInstall(command) {
|
|
320
|
+
const installs = {
|
|
321
|
+
claude: "Install with: npm install -g @anthropic-ai/claude-code",
|
|
322
|
+
codex: "Install with: npm install -g @openai/codex",
|
|
323
|
+
gemini: "Install with: npm install -g @google/gemini-cli"
|
|
324
|
+
};
|
|
325
|
+
return installs[command] ?? `Install ${command} and ensure it is available.`;
|
|
269
326
|
}
|
|
270
327
|
export function detectCodexHostPlatform(env = process.env, platform = process.platform) {
|
|
271
328
|
if (platform === "win32") {
|
|
@@ -43,7 +43,7 @@ export interface OpenAiCompatibleAdapterOptions {
|
|
|
43
43
|
systemPrompt?: string;
|
|
44
44
|
/** Request timeout in milliseconds. Default: 300_000 (5 min). */
|
|
45
45
|
timeoutMs?: number;
|
|
46
|
-
/** Verifier timeout in milliseconds. Default:
|
|
46
|
+
/** Verifier timeout in milliseconds. Default: 120_000. */
|
|
47
47
|
verifyTimeoutMs?: number;
|
|
48
48
|
/** Working directory for git artifact collection and verification. */
|
|
49
49
|
workingDirectory?: string;
|
|
@@ -72,12 +72,12 @@ function estimateCost(model, inputChars, outputChars) {
|
|
|
72
72
|
// ---------------------------------------------------------------------------
|
|
73
73
|
// Prompt builder
|
|
74
74
|
// ---------------------------------------------------------------------------
|
|
75
|
-
const DEFAULT_SYSTEM_PROMPT = `You are an expert software engineer executing a governed coding task.
|
|
76
|
-
Follow these rules exactly:
|
|
77
|
-
- Read the task description carefully and implement only what is asked.
|
|
78
|
-
- Do not add features, refactors, or improvements beyond the stated task.
|
|
79
|
-
- If the task asks you to write or modify code, output the complete file content with changes applied.
|
|
80
|
-
- Be precise, minimal, and test-backed in all changes.
|
|
75
|
+
const DEFAULT_SYSTEM_PROMPT = `You are an expert software engineer executing a governed coding task.
|
|
76
|
+
Follow these rules exactly:
|
|
77
|
+
- Read the task description carefully and implement only what is asked.
|
|
78
|
+
- Do not add features, refactors, or improvements beyond the stated task.
|
|
79
|
+
- If the task asks you to write or modify code, output the complete file content with changes applied.
|
|
80
|
+
- Be precise, minimal, and test-backed in all changes.
|
|
81
81
|
- State what you changed and why at the end of your response.`;
|
|
82
82
|
export const DEFAULT_OPENAI_BASE_URL = "https://api.openai.com";
|
|
83
83
|
export const DEFAULT_OPENAI_MODEL = "gpt-4.1-mini";
|
|
@@ -120,7 +120,7 @@ function buildPrompt(request) {
|
|
|
120
120
|
export function createOpenAiCompatibleAdapter(options) {
|
|
121
121
|
const workingDirectory = options.workingDirectory ?? process.cwd();
|
|
122
122
|
const timeoutMs = options.timeoutMs ?? 300_000;
|
|
123
|
-
const verifyTimeoutMs = options.verifyTimeoutMs ??
|
|
123
|
+
const verifyTimeoutMs = options.verifyTimeoutMs ?? 120_000;
|
|
124
124
|
const systemPrompt = options.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;
|
|
125
125
|
const fetchFn = options.fetchImpl ?? globalThis.fetch;
|
|
126
126
|
const runtimeConfig = resolveOpenAiCompatibleRuntimeConfig();
|
|
@@ -2,7 +2,7 @@ import { readGitChangedFiles, runVerification } from "./cli-bridge.js";
|
|
|
2
2
|
import { createAdapterCapabilities, normalizeUsage } from "./runtime-support.js";
|
|
3
3
|
export function createVerifierOnlyAdapter(options = {}) {
|
|
4
4
|
const workingDirectory = options.workingDirectory ?? process.cwd();
|
|
5
|
-
const verifyTimeoutMs = options.verifyTimeoutMs ??
|
|
5
|
+
const verifyTimeoutMs = options.verifyTimeoutMs ?? 120_000;
|
|
6
6
|
return {
|
|
7
7
|
adapterId: "direct:verifier:verify-only",
|
|
8
8
|
kind: "direct-provider",
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type DiffVisibilityLevel = "none" | "git" | "adapter_reported";
|
|
2
|
+
export type VerifierCompatibility = "full" | "verify_only" | "unsupported";
|
|
3
|
+
export type SandboxExpectation = "host_process" | "workspace_write" | "provider_managed" | "not_applicable";
|
|
4
|
+
export type LaunchReadiness = "path_lookup" | "configured_endpoint" | "built_in";
|
|
5
|
+
export type AdapterUsageSettlement = "actual" | "estimated" | "unavailable";
|
|
6
|
+
export interface AdapterCapabilityDescriptor {
|
|
7
|
+
preflight: boolean;
|
|
8
|
+
usageSettlement: AdapterUsageSettlement;
|
|
9
|
+
diffVisibility: DiffVisibilityLevel;
|
|
10
|
+
structuredErrors: boolean;
|
|
11
|
+
cachingSignals: boolean;
|
|
12
|
+
verifierCompatibility: VerifierCompatibility;
|
|
13
|
+
sandboxExpectation: SandboxExpectation;
|
|
14
|
+
launchReadiness: LaunchReadiness;
|
|
15
|
+
}
|
|
16
|
+
export declare function createAdapterCapabilityDescriptor(overrides?: Partial<AdapterCapabilityDescriptor>): AdapterCapabilityDescriptor;
|
|
17
|
+
export declare function getBuiltInEngineCapabilityDescriptor(engine: "claude" | "codex"): AdapterCapabilityDescriptor;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function createAdapterCapabilityDescriptor(overrides = {}) {
|
|
2
|
+
return {
|
|
3
|
+
preflight: true,
|
|
4
|
+
usageSettlement: "unavailable",
|
|
5
|
+
diffVisibility: "none",
|
|
6
|
+
structuredErrors: false,
|
|
7
|
+
cachingSignals: false,
|
|
8
|
+
verifierCompatibility: "full",
|
|
9
|
+
sandboxExpectation: "host_process",
|
|
10
|
+
launchReadiness: "path_lookup",
|
|
11
|
+
...overrides
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export function getBuiltInEngineCapabilityDescriptor(engine) {
|
|
15
|
+
if (engine === "claude") {
|
|
16
|
+
return createAdapterCapabilityDescriptor({
|
|
17
|
+
usageSettlement: "actual",
|
|
18
|
+
diffVisibility: "git",
|
|
19
|
+
structuredErrors: true,
|
|
20
|
+
cachingSignals: true,
|
|
21
|
+
verifierCompatibility: "full",
|
|
22
|
+
sandboxExpectation: "host_process",
|
|
23
|
+
launchReadiness: "path_lookup"
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return createAdapterCapabilityDescriptor({
|
|
27
|
+
usageSettlement: "estimated",
|
|
28
|
+
diffVisibility: "git",
|
|
29
|
+
structuredErrors: true,
|
|
30
|
+
cachingSignals: false,
|
|
31
|
+
verifierCompatibility: "full",
|
|
32
|
+
sandboxExpectation: "workspace_write",
|
|
33
|
+
launchReadiness: "path_lookup"
|
|
34
|
+
});
|
|
35
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export type ContextGraphNodeKind = "source_file" | "document" | "manifest" | "script" | "config";
|
|
2
|
+
export type ContextGraphEdgeKind = "imports" | "documents";
|
|
3
|
+
export interface ContextGraphNode {
|
|
4
|
+
nodeId: string;
|
|
5
|
+
path: string;
|
|
6
|
+
kind: ContextGraphNodeKind;
|
|
7
|
+
language?: string;
|
|
8
|
+
sizeBytes: number;
|
|
9
|
+
headings: string[];
|
|
10
|
+
symbols: string[];
|
|
11
|
+
keywords: string[];
|
|
12
|
+
imports: string[];
|
|
13
|
+
}
|
|
14
|
+
export interface ContextGraphEdge {
|
|
15
|
+
fromNodeId: string;
|
|
16
|
+
toNodeId: string;
|
|
17
|
+
kind: ContextGraphEdgeKind;
|
|
18
|
+
}
|
|
19
|
+
export interface ContextGraphSnapshot {
|
|
20
|
+
schemaVersion: "martin.context-graph.v1";
|
|
21
|
+
repoRoot: string;
|
|
22
|
+
createdAt: string;
|
|
23
|
+
nodeCount: number;
|
|
24
|
+
edgeCount: number;
|
|
25
|
+
truncated: boolean;
|
|
26
|
+
nodes: ContextGraphNode[];
|
|
27
|
+
edges: ContextGraphEdge[];
|
|
28
|
+
}
|
|
29
|
+
export interface ContextQuery {
|
|
30
|
+
text?: string;
|
|
31
|
+
terms?: string[];
|
|
32
|
+
pathPrefix?: string;
|
|
33
|
+
kinds?: ContextGraphNodeKind[];
|
|
34
|
+
limit?: number;
|
|
35
|
+
}
|
|
36
|
+
export interface ContextGraphBuildOptions {
|
|
37
|
+
maxFiles?: number;
|
|
38
|
+
maxFileBytes?: number;
|
|
39
|
+
}
|
|
40
|
+
export interface ContextGraphHit {
|
|
41
|
+
nodeId: string;
|
|
42
|
+
path: string;
|
|
43
|
+
kind: ContextGraphNodeKind;
|
|
44
|
+
score: number;
|
|
45
|
+
matchedTerms: string[];
|
|
46
|
+
reasons: string[];
|
|
47
|
+
}
|
|
48
|
+
export declare function cloneContextGraphSnapshot(snapshot: ContextGraphSnapshot): ContextGraphSnapshot;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function cloneContextGraphSnapshot(snapshot) {
|
|
2
|
+
return {
|
|
3
|
+
schemaVersion: snapshot.schemaVersion,
|
|
4
|
+
repoRoot: snapshot.repoRoot,
|
|
5
|
+
createdAt: snapshot.createdAt,
|
|
6
|
+
nodeCount: snapshot.nodeCount,
|
|
7
|
+
edgeCount: snapshot.edgeCount,
|
|
8
|
+
truncated: snapshot.truncated,
|
|
9
|
+
nodes: snapshot.nodes.map((node) => ({
|
|
10
|
+
nodeId: node.nodeId,
|
|
11
|
+
path: node.path,
|
|
12
|
+
kind: node.kind,
|
|
13
|
+
...(node.language ? { language: node.language } : {}),
|
|
14
|
+
sizeBytes: node.sizeBytes,
|
|
15
|
+
headings: [...node.headings],
|
|
16
|
+
symbols: [...node.symbols],
|
|
17
|
+
keywords: [...node.keywords],
|
|
18
|
+
imports: [...node.imports]
|
|
19
|
+
})),
|
|
20
|
+
edges: snapshot.edges.map((edge) => ({
|
|
21
|
+
fromNodeId: edge.fromNodeId,
|
|
22
|
+
toNodeId: edge.toNodeId,
|
|
23
|
+
kind: edge.kind
|
|
24
|
+
}))
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { ApprovalPolicy, LoopBudget, LoopTask, MutationMode } from "./index.js";
|
|
2
|
+
import type { DestructiveActionPolicy, PolicyProfile, TelemetryDestination } from "./governance.js";
|
|
3
|
+
export interface ExecutionPolicy {
|
|
4
|
+
configPath: string;
|
|
5
|
+
budget: LoopBudget;
|
|
6
|
+
governance: {
|
|
7
|
+
policyProfile: PolicyProfile;
|
|
8
|
+
telemetryDestination: TelemetryDestination;
|
|
9
|
+
destructiveActionPolicy: DestructiveActionPolicy;
|
|
10
|
+
};
|
|
11
|
+
task: {
|
|
12
|
+
verificationPlan: string[];
|
|
13
|
+
mutationMode?: MutationMode;
|
|
14
|
+
repoRoot?: string;
|
|
15
|
+
allowedPaths?: string[];
|
|
16
|
+
deniedPaths?: string[];
|
|
17
|
+
acceptanceCriteria?: string[];
|
|
18
|
+
approvalPolicy?: ApprovalPolicy;
|
|
19
|
+
};
|
|
20
|
+
provenance: ExecutionPolicyProvenanceEntry[];
|
|
21
|
+
}
|
|
22
|
+
export interface ExecutionPolicyProvenanceEntry {
|
|
23
|
+
field: string;
|
|
24
|
+
source: "default" | "config" | "request";
|
|
25
|
+
value: string;
|
|
26
|
+
}
|
|
27
|
+
export interface ExecutionPolicyDefaults {
|
|
28
|
+
budget: LoopBudget;
|
|
29
|
+
policyProfile: PolicyProfile;
|
|
30
|
+
telemetryDestination: TelemetryDestination;
|
|
31
|
+
destructiveActionPolicy: DestructiveActionPolicy;
|
|
32
|
+
verifierRules: string[];
|
|
33
|
+
}
|
|
34
|
+
export interface ExecutionPolicyConfigInput {
|
|
35
|
+
policyProfile?: string;
|
|
36
|
+
budget?: Partial<LoopBudget>;
|
|
37
|
+
governance?: {
|
|
38
|
+
destructiveActionPolicy?: string;
|
|
39
|
+
telemetryDestination?: string;
|
|
40
|
+
verifierRules?: string[];
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export interface ExecutionPolicyRequestInput {
|
|
44
|
+
budget: LoopBudget;
|
|
45
|
+
budgetOverrides?: Partial<Record<keyof LoopBudget, true>>;
|
|
46
|
+
policyProfile?: string;
|
|
47
|
+
telemetryDestination?: string;
|
|
48
|
+
verificationPlan?: string[];
|
|
49
|
+
mutationMode?: LoopTask["mutationMode"];
|
|
50
|
+
repoRoot?: string;
|
|
51
|
+
allowedPaths?: string[];
|
|
52
|
+
deniedPaths?: string[];
|
|
53
|
+
acceptanceCriteria?: string[];
|
|
54
|
+
approvalPolicy?: ApprovalPolicy;
|
|
55
|
+
}
|
|
56
|
+
export interface ExecutionPolicyCompileInput {
|
|
57
|
+
configPath: string;
|
|
58
|
+
defaults: ExecutionPolicyDefaults;
|
|
59
|
+
config?: ExecutionPolicyConfigInput;
|
|
60
|
+
request: ExecutionPolicyRequestInput;
|
|
61
|
+
}
|
|
62
|
+
export declare function cloneExecutionPolicy(policy: ExecutionPolicy): ExecutionPolicy;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export function cloneExecutionPolicy(policy) {
|
|
2
|
+
return {
|
|
3
|
+
configPath: policy.configPath,
|
|
4
|
+
budget: {
|
|
5
|
+
maxUsd: policy.budget.maxUsd,
|
|
6
|
+
softLimitUsd: policy.budget.softLimitUsd,
|
|
7
|
+
maxIterations: policy.budget.maxIterations,
|
|
8
|
+
maxTokens: policy.budget.maxTokens
|
|
9
|
+
},
|
|
10
|
+
governance: {
|
|
11
|
+
policyProfile: policy.governance.policyProfile,
|
|
12
|
+
telemetryDestination: policy.governance.telemetryDestination,
|
|
13
|
+
destructiveActionPolicy: policy.governance.destructiveActionPolicy
|
|
14
|
+
},
|
|
15
|
+
task: {
|
|
16
|
+
verificationPlan: [...policy.task.verificationPlan],
|
|
17
|
+
...(policy.task.mutationMode ? { mutationMode: policy.task.mutationMode } : {}),
|
|
18
|
+
...(policy.task.repoRoot ? { repoRoot: policy.task.repoRoot } : {}),
|
|
19
|
+
...(policy.task.allowedPaths ? { allowedPaths: [...policy.task.allowedPaths] } : {}),
|
|
20
|
+
...(policy.task.deniedPaths ? { deniedPaths: [...policy.task.deniedPaths] } : {}),
|
|
21
|
+
...(policy.task.acceptanceCriteria
|
|
22
|
+
? { acceptanceCriteria: [...policy.task.acceptanceCriteria] }
|
|
23
|
+
: {}),
|
|
24
|
+
...(policy.task.approvalPolicy
|
|
25
|
+
? {
|
|
26
|
+
approvalPolicy: {
|
|
27
|
+
...policy.task.approvalPolicy
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
: {})
|
|
31
|
+
},
|
|
32
|
+
provenance: policy.provenance.map((entry) => ({ ...entry }))
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
+
export type PolicyProfile = "strict" | "balanced" | "overnight" | "debug";
|
|
2
|
+
export type DestructiveActionPolicy = "never" | "approval" | "allowed";
|
|
3
|
+
export type TelemetryDestination = "local-only" | "control-plane";
|
|
1
4
|
export type GovernanceSnapshot = {
|
|
2
|
-
policyProfile:
|
|
5
|
+
policyProfile: PolicyProfile;
|
|
3
6
|
maxUsd: number;
|
|
4
7
|
softLimitUsd: number;
|
|
5
8
|
maxTokens: number;
|
|
6
9
|
maxIterations: number;
|
|
7
10
|
allowedAdapters: string[];
|
|
8
11
|
allowedModels: string[];
|
|
9
|
-
destructiveActionPolicy:
|
|
12
|
+
destructiveActionPolicy: DestructiveActionPolicy;
|
|
10
13
|
approvalRequired: boolean;
|
|
11
14
|
verifierRules: string[];
|
|
12
15
|
escalationRoute: string;
|
|
13
|
-
telemetryDestination:
|
|
16
|
+
telemetryDestination: TelemetryDestination;
|
|
14
17
|
retentionPolicy: string;
|
|
15
18
|
provenance: Array<{
|
|
16
19
|
field: string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type IdentityAlgorithm = "ed25519";
|
|
2
|
+
export type IdentityRole = "governor" | "verifier" | "worker" | "reviewer" | "observer";
|
|
3
|
+
export interface IdentityClaims {
|
|
4
|
+
subject: string;
|
|
5
|
+
issuer: string;
|
|
6
|
+
role: IdentityRole;
|
|
7
|
+
scopes: string[];
|
|
8
|
+
issuedAt: string;
|
|
9
|
+
expiresAt?: string;
|
|
10
|
+
workspaceId?: string;
|
|
11
|
+
sessionId?: string;
|
|
12
|
+
metadata?: Record<string, string>;
|
|
13
|
+
}
|
|
14
|
+
export interface IdentityToken {
|
|
15
|
+
schemaVersion: "martin.identity.v1";
|
|
16
|
+
algorithm: IdentityAlgorithm;
|
|
17
|
+
keyId: string;
|
|
18
|
+
claims: IdentityClaims;
|
|
19
|
+
signature: string;
|
|
20
|
+
}
|
|
21
|
+
export interface IdentityAttestation {
|
|
22
|
+
valid: boolean;
|
|
23
|
+
verifiedAt: string;
|
|
24
|
+
reason: string;
|
|
25
|
+
token: IdentityToken;
|
|
26
|
+
}
|
|
27
|
+
export declare function cloneIdentityClaims(claims: IdentityClaims): IdentityClaims;
|
|
28
|
+
export declare function cloneIdentityToken(token: IdentityToken): IdentityToken;
|
|
29
|
+
export declare function cloneIdentityAttestation(attestation: IdentityAttestation): IdentityAttestation;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export function cloneIdentityClaims(claims) {
|
|
2
|
+
return {
|
|
3
|
+
subject: claims.subject,
|
|
4
|
+
issuer: claims.issuer,
|
|
5
|
+
role: claims.role,
|
|
6
|
+
scopes: [...claims.scopes],
|
|
7
|
+
issuedAt: claims.issuedAt,
|
|
8
|
+
...(claims.expiresAt ? { expiresAt: claims.expiresAt } : {}),
|
|
9
|
+
...(claims.workspaceId ? { workspaceId: claims.workspaceId } : {}),
|
|
10
|
+
...(claims.sessionId ? { sessionId: claims.sessionId } : {}),
|
|
11
|
+
...(claims.metadata ? { metadata: { ...claims.metadata } } : {})
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export function cloneIdentityToken(token) {
|
|
15
|
+
return {
|
|
16
|
+
schemaVersion: token.schemaVersion,
|
|
17
|
+
algorithm: token.algorithm,
|
|
18
|
+
keyId: token.keyId,
|
|
19
|
+
claims: cloneIdentityClaims(token.claims),
|
|
20
|
+
signature: token.signature
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export function cloneIdentityAttestation(attestation) {
|
|
24
|
+
return {
|
|
25
|
+
valid: attestation.valid,
|
|
26
|
+
verifiedAt: attestation.verifiedAt,
|
|
27
|
+
reason: attestation.reason,
|
|
28
|
+
token: cloneIdentityToken(attestation.token)
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -9,6 +9,7 @@ export interface LoopTask {
|
|
|
9
9
|
objective: string;
|
|
10
10
|
repoRoot?: string;
|
|
11
11
|
verificationPlan: string[];
|
|
12
|
+
verificationTimeoutMs?: number;
|
|
12
13
|
verificationStack?: VerificationStep[];
|
|
13
14
|
mutationMode?: MutationMode;
|
|
14
15
|
executionProfile?: ExecutionProfile;
|
|
@@ -73,7 +74,7 @@ export interface ReceiptScope {
|
|
|
73
74
|
invocationRoot?: string;
|
|
74
75
|
runsRoot?: string;
|
|
75
76
|
}
|
|
76
|
-
export type ReceiptIntegrityState = "verified" | "unsigned" | "tamper_detected";
|
|
77
|
+
export type ReceiptIntegrityState = "verified" | "unsigned" | "tamper_detected" | "relocated" | "material_missing" | "selector_noncanonical";
|
|
77
78
|
export interface ReceiptIntegritySummary {
|
|
78
79
|
state: ReceiptIntegrityState;
|
|
79
80
|
keyId?: string;
|
|
@@ -101,6 +102,8 @@ export interface LoopAttempt {
|
|
|
101
102
|
summary?: string;
|
|
102
103
|
failureClass?: FailureClass;
|
|
103
104
|
intervention?: InterventionType;
|
|
105
|
+
/** Actionable diagnosis from failure classification, injected into the next attempt's prompt. */
|
|
106
|
+
diagnosticHint?: string;
|
|
104
107
|
}
|
|
105
108
|
export interface LoopEvent {
|
|
106
109
|
eventId: string;
|
|
@@ -371,4 +374,12 @@ export interface RollbackOutcomeArtifact {
|
|
|
371
374
|
error?: string;
|
|
372
375
|
}
|
|
373
376
|
export { createGovernanceSnapshot } from "./governance.js";
|
|
374
|
-
export type { GovernanceSnapshot } from "./governance.js";
|
|
377
|
+
export type { DestructiveActionPolicy, GovernanceSnapshot, PolicyProfile, TelemetryDestination } from "./governance.js";
|
|
378
|
+
export { cloneExecutionPolicy } from "./execution-policy.js";
|
|
379
|
+
export type { ExecutionPolicy, ExecutionPolicyCompileInput, ExecutionPolicyConfigInput, ExecutionPolicyDefaults, ExecutionPolicyProvenanceEntry, ExecutionPolicyRequestInput } from "./execution-policy.js";
|
|
380
|
+
export { cloneContextGraphSnapshot } from "./context-graph.js";
|
|
381
|
+
export type { ContextGraphBuildOptions, ContextGraphEdge, ContextGraphHit, ContextGraphNode, ContextGraphNodeKind, ContextGraphSnapshot, ContextQuery } from "./context-graph.js";
|
|
382
|
+
export { cloneIdentityAttestation, cloneIdentityClaims, cloneIdentityToken } from "./identity.js";
|
|
383
|
+
export type { IdentityAttestation, IdentityClaims, IdentityToken } from "./identity.js";
|
|
384
|
+
export { cloneCircuitBreakDecision, cloneTrajectoryAssessment } from "./trajectory.js";
|
|
385
|
+
export type { CircuitBreakDecision, TrajectoryAssessment, TrajectorySignal } from "./trajectory.js";
|
|
@@ -217,3 +217,7 @@ function hasText(value) {
|
|
|
217
217
|
return typeof value === "string" && value.trim().length > 0;
|
|
218
218
|
}
|
|
219
219
|
export { createGovernanceSnapshot } from "./governance.js";
|
|
220
|
+
export { cloneExecutionPolicy } from "./execution-policy.js";
|
|
221
|
+
export { cloneContextGraphSnapshot } from "./context-graph.js";
|
|
222
|
+
export { cloneIdentityAttestation, cloneIdentityClaims, cloneIdentityToken } from "./identity.js";
|
|
223
|
+
export { cloneCircuitBreakDecision, cloneTrajectoryAssessment } from "./trajectory.js";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type ChangeObservationStatus = "verified" | "mismatch" | "adapter_only" | "repo_only" | "unavailable";
|
|
2
|
+
export interface ChangeObservationEvidence {
|
|
3
|
+
available: boolean;
|
|
4
|
+
changedFiles: string[];
|
|
5
|
+
diffStats?: {
|
|
6
|
+
filesChanged: number;
|
|
7
|
+
addedLines: number;
|
|
8
|
+
deletedLines: number;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export interface ChangeObservationReconciliation {
|
|
12
|
+
status: ChangeObservationStatus;
|
|
13
|
+
summary: string;
|
|
14
|
+
adapterReported: ChangeObservationEvidence;
|
|
15
|
+
repoObserved: ChangeObservationEvidence;
|
|
16
|
+
effectiveChangedFiles: string[];
|
|
17
|
+
matchedFiles: string[];
|
|
18
|
+
adapterOnlyFiles: string[];
|
|
19
|
+
repoOnlyFiles: string[];
|
|
20
|
+
}
|
|
21
|
+
export declare function cloneChangeObservationReconciliation(input: ChangeObservationReconciliation): ChangeObservationReconciliation;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function cloneChangeObservationReconciliation(input) {
|
|
2
|
+
return {
|
|
3
|
+
status: input.status,
|
|
4
|
+
summary: input.summary,
|
|
5
|
+
adapterReported: cloneObservationEvidence(input.adapterReported),
|
|
6
|
+
repoObserved: cloneObservationEvidence(input.repoObserved),
|
|
7
|
+
effectiveChangedFiles: [...input.effectiveChangedFiles],
|
|
8
|
+
matchedFiles: [...input.matchedFiles],
|
|
9
|
+
adapterOnlyFiles: [...input.adapterOnlyFiles],
|
|
10
|
+
repoOnlyFiles: [...input.repoOnlyFiles]
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function cloneObservationEvidence(input) {
|
|
14
|
+
return {
|
|
15
|
+
available: input.available,
|
|
16
|
+
changedFiles: [...input.changedFiles],
|
|
17
|
+
...(input.diffStats
|
|
18
|
+
? {
|
|
19
|
+
diffStats: {
|
|
20
|
+
filesChanged: input.diffStats.filesChanged,
|
|
21
|
+
addedLines: input.diffStats.addedLines,
|
|
22
|
+
deletedLines: input.diffStats.deletedLines
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
: {})
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { InterventionType } from "./index.js";
|
|
2
|
+
export type TrajectoryStatus = "healthy" | "watch" | "drifting" | "stalled";
|
|
3
|
+
export type TrajectoryConfidence = "low" | "medium" | "high";
|
|
4
|
+
export type TrajectorySignalCode = "failure_oscillation" | "attempt_repetition" | "verification_stall" | "objective_drift";
|
|
5
|
+
export interface TrajectorySignal {
|
|
6
|
+
code: TrajectorySignalCode;
|
|
7
|
+
severity: "low" | "medium" | "high";
|
|
8
|
+
summary: string;
|
|
9
|
+
attemptIndexes: number[];
|
|
10
|
+
matchedTerms?: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface TrajectoryAssessment {
|
|
13
|
+
status: TrajectoryStatus;
|
|
14
|
+
confidence: TrajectoryConfidence;
|
|
15
|
+
summary: string;
|
|
16
|
+
signals: TrajectorySignal[];
|
|
17
|
+
recommendedIntervention?: InterventionType;
|
|
18
|
+
}
|
|
19
|
+
export interface CircuitBreakDecision {
|
|
20
|
+
shouldStop: boolean;
|
|
21
|
+
reason: string;
|
|
22
|
+
assessment: TrajectoryAssessment;
|
|
23
|
+
recommendedIntervention?: InterventionType;
|
|
24
|
+
}
|
|
25
|
+
export declare function cloneTrajectoryAssessment(assessment: TrajectoryAssessment): TrajectoryAssessment;
|
|
26
|
+
export declare function cloneCircuitBreakDecision(decision: CircuitBreakDecision): CircuitBreakDecision;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function cloneTrajectoryAssessment(assessment) {
|
|
2
|
+
return {
|
|
3
|
+
status: assessment.status,
|
|
4
|
+
confidence: assessment.confidence,
|
|
5
|
+
summary: assessment.summary,
|
|
6
|
+
...(assessment.recommendedIntervention
|
|
7
|
+
? { recommendedIntervention: assessment.recommendedIntervention }
|
|
8
|
+
: {}),
|
|
9
|
+
signals: assessment.signals.map((signal) => ({
|
|
10
|
+
code: signal.code,
|
|
11
|
+
severity: signal.severity,
|
|
12
|
+
summary: signal.summary,
|
|
13
|
+
attemptIndexes: [...signal.attemptIndexes],
|
|
14
|
+
...(signal.matchedTerms ? { matchedTerms: [...signal.matchedTerms] } : {})
|
|
15
|
+
}))
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function cloneCircuitBreakDecision(decision) {
|
|
19
|
+
return {
|
|
20
|
+
shouldStop: decision.shouldStop,
|
|
21
|
+
reason: decision.reason,
|
|
22
|
+
assessment: cloneTrajectoryAssessment(decision.assessment),
|
|
23
|
+
...(decision.recommendedIntervention
|
|
24
|
+
? { recommendedIntervention: decision.recommendedIntervention }
|
|
25
|
+
: {})
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type VerifierExitReason = "passed" | "non_zero_exit" | "timed_out" | "spawn_error" | "invalid_command";
|
|
2
|
+
export type VerifierStepType = "lint" | "typecheck" | "test_targeted" | "test_full" | "custom";
|
|
3
|
+
export interface VerifierStepSnapshot {
|
|
4
|
+
command: string;
|
|
5
|
+
type: VerifierStepType;
|
|
6
|
+
fastFail: boolean;
|
|
7
|
+
passed: boolean;
|
|
8
|
+
exitCode: number;
|
|
9
|
+
exitReason: VerifierExitReason;
|
|
10
|
+
startedAt: string;
|
|
11
|
+
completedAt: string;
|
|
12
|
+
durationMs: number;
|
|
13
|
+
stdout?: string;
|
|
14
|
+
stderr?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface VerifierSnapshot {
|
|
17
|
+
passed: boolean;
|
|
18
|
+
summary: string;
|
|
19
|
+
startedAt: string;
|
|
20
|
+
completedAt: string;
|
|
21
|
+
durationMs: number;
|
|
22
|
+
stepCount: number;
|
|
23
|
+
failedStepCount: number;
|
|
24
|
+
commands: string[];
|
|
25
|
+
steps: VerifierStepSnapshot[];
|
|
26
|
+
combinedOutput?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function cloneVerifierSnapshot(snapshot: VerifierSnapshot): VerifierSnapshot;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type ContextGraphBuildOptions, type ContextGraphHit, type ContextGraphSnapshot, type ContextQuery } from "../contracts/index.js";
|
|
2
|
+
export declare function buildContextGraphSnapshot(repoRoot: string, options?: ContextGraphBuildOptions): Promise<ContextGraphSnapshot>;
|
|
3
|
+
export declare function queryContextGraph(snapshot: ContextGraphSnapshot, query: ContextQuery): ContextGraphHit[];
|