@martinloop/mcp 0.3.9 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -141
- package/dist/discovery-metadata.d.ts +1 -1
- package/dist/discovery-metadata.js +1 -1
- package/dist/resources.d.ts +1 -2
- package/dist/resources.js +47 -95
- package/dist/server-validation.d.ts +1 -1
- package/dist/server-validation.js +16 -11
- package/dist/server.d.ts +23 -0
- package/dist/server.js +152 -7
- package/dist/tools/preflight.d.ts +2 -0
- package/dist/tools/preflight.js +42 -2
- package/dist/tools/run-dossier.d.ts +3 -1
- package/dist/tools/run-dossier.js +40 -2
- package/dist/tools/run-loop.d.ts +1 -4
- package/dist/tools/run-loop.js +6 -15
- package/dist/tools/tool-support.d.ts +2 -1
- package/dist/tools/tool-support.js +1 -12
- package/dist/vendor/adapters/claude-cli.js +38 -35
- package/dist/vendor/adapters/cli-bridge.d.ts +9 -1
- package/dist/vendor/adapters/cli-bridge.js +54 -13
- package/dist/vendor/adapters/codex-launcher.d.ts +61 -1
- package/dist/vendor/adapters/codex-launcher.js +118 -19
- package/dist/vendor/adapters/index.d.ts +1 -3
- package/dist/vendor/adapters/index.js +1 -3
- package/dist/vendor/adapters/openai-compatible.js +51 -12
- package/dist/vendor/contracts/adapter-capabilities.d.ts +1 -1
- package/dist/vendor/contracts/context-handoff.d.ts +100 -0
- package/dist/vendor/contracts/context-handoff.js +11 -0
- package/dist/vendor/contracts/context-manifest.d.ts +195 -0
- package/dist/vendor/contracts/context-manifest.js +17 -0
- package/dist/vendor/contracts/context-shadow.d.ts +75 -0
- package/dist/vendor/contracts/context-shadow.js +8 -0
- package/dist/vendor/contracts/delivery.d.ts +47 -0
- package/dist/vendor/contracts/delivery.js +18 -0
- package/dist/vendor/contracts/exits.d.ts +126 -0
- package/dist/vendor/contracts/exits.js +32 -0
- package/dist/vendor/contracts/index.d.ts +41 -2
- package/dist/vendor/contracts/index.js +24 -0
- package/dist/vendor/contracts/mission.d.ts +102 -0
- package/dist/vendor/contracts/mission.js +64 -0
- package/dist/vendor/contracts/operator.d.ts +3 -1
- package/dist/vendor/contracts/operator.js +2 -1
- package/dist/vendor/contracts/verified-handoff.d.ts +100 -0
- package/dist/vendor/contracts/verified-handoff.js +35 -0
- package/dist/vendor/core/context-chain-gate.d.ts +89 -0
- package/dist/vendor/core/context-chain-gate.js +173 -0
- package/dist/vendor/core/context-compiler.d.ts +53 -0
- package/dist/vendor/core/context-compiler.js +261 -0
- package/dist/vendor/core/context-handoff.d.ts +42 -0
- package/dist/vendor/core/context-handoff.js +167 -0
- package/dist/vendor/core/context-shadow.d.ts +39 -0
- package/dist/vendor/core/context-shadow.js +200 -0
- package/dist/vendor/core/delivery/index.d.ts +6 -0
- package/dist/vendor/core/delivery/index.js +4 -0
- package/dist/vendor/core/delivery/message-client.d.ts +18 -0
- package/dist/vendor/core/delivery/message-client.js +38 -0
- package/dist/vendor/core/delivery/message-ledger.d.ts +35 -0
- package/dist/vendor/core/delivery/message-ledger.js +97 -0
- package/dist/vendor/core/delivery/message-schema.d.ts +16 -0
- package/dist/vendor/core/delivery/message-schema.js +111 -0
- package/dist/vendor/core/delivery/update-check.d.ts +19 -0
- package/dist/vendor/core/delivery/update-check.js +107 -0
- package/dist/vendor/core/exit-signal.d.ts +88 -0
- package/dist/vendor/core/exit-signal.js +339 -0
- package/dist/vendor/core/exits.d.ts +41 -0
- package/dist/vendor/core/exits.js +258 -0
- package/dist/vendor/core/index.d.ts +44 -1
- package/dist/vendor/core/index.js +1088 -662
- package/dist/vendor/core/mission/aggregate.d.ts +27 -0
- package/dist/vendor/core/mission/aggregate.js +42 -0
- package/dist/vendor/core/mission/index.d.ts +2 -0
- package/dist/vendor/core/mission/index.js +1 -0
- package/dist/vendor/core/persistence/compiler.d.ts +8 -0
- package/dist/vendor/core/persistence/compiler.js +156 -0
- package/dist/vendor/core/persistence/context-handoff-store.d.ts +68 -0
- package/dist/vendor/core/persistence/context-handoff-store.js +112 -0
- package/dist/vendor/core/persistence/index.d.ts +4 -0
- package/dist/vendor/core/persistence/index.js +2 -0
- package/dist/vendor/core/persistence/ledger.d.ts +1 -1
- package/dist/vendor/core/persistence/mission-store.d.ts +56 -0
- package/dist/vendor/core/persistence/mission-store.js +281 -0
- package/dist/vendor/core/policy.d.ts +2 -0
- package/dist/vendor/core/policy.js +5 -2
- package/dist/vendor/core/rollback.js +15 -1
- package/dist/vendor/core/savings.d.ts +13 -0
- package/dist/vendor/core/savings.js +22 -0
- package/dist/vendor/core/termination-store.d.ts +15 -0
- package/dist/vendor/core/termination-store.js +44 -0
- package/dist/vendor/core/verified-handoff.d.ts +67 -0
- package/dist/vendor/core/verified-handoff.js +210 -0
- package/package.json +3 -13
- package/server.json +3 -3
- package/dist/vendor/adapters/stub-agent-cli.d.ts +0 -8
- package/dist/vendor/adapters/stub-agent-cli.js +0 -40
- package/dist/vendor/adapters/verifier-only.d.ts +0 -9
- package/dist/vendor/adapters/verifier-only.js +0 -63
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: MartinLoop contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Mapping: granular TestIntegrityStatus → public TestIntegrityVerdict
|
|
6
|
+
//
|
|
7
|
+
// A new enum value MUST appear here or TypeScript compilation will fail,
|
|
8
|
+
// ensuring the mapping is always exhaustive.
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
export function toTestIntegrityVerdict(status) {
|
|
11
|
+
switch (status) {
|
|
12
|
+
case "UNCHANGED":
|
|
13
|
+
case "AUTHORIZED_CHANGE":
|
|
14
|
+
return "VERIFIED";
|
|
15
|
+
case "PREVENTED":
|
|
16
|
+
case "DETECTED_AND_ROLLED_BACK":
|
|
17
|
+
case "DETECTED_NEEDS_REVIEW":
|
|
18
|
+
return "TAMPERING_DETECTED";
|
|
19
|
+
case "NOT_EVALUATED":
|
|
20
|
+
return "NOT_EVALUATED";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Outcome resolution — deterministic, no hidden defaults
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
const STOPPED_LIFECYCLE_STATES = new Set([
|
|
27
|
+
"budget_exit",
|
|
28
|
+
"diminishing_returns",
|
|
29
|
+
"stuck_exit",
|
|
30
|
+
"human_escalation",
|
|
31
|
+
]);
|
|
32
|
+
export function verifierActuallyPassed(evidence, expected) {
|
|
33
|
+
if (!evidence?.passed || !evidence.binding || !evidence.steps) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
if (evidence.binding.runId !== expected.runId ||
|
|
37
|
+
evidence.binding.workspaceId !== expected.workspaceId ||
|
|
38
|
+
evidence.binding.cwd !== expected.cwd ||
|
|
39
|
+
JSON.stringify(evidence.binding.commands) !== JSON.stringify(expected.commands)) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
if (evidence.steps.length !== expected.commands.length) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return evidence.steps.every((step, index) => step.command === expected.commands[index] &&
|
|
46
|
+
step.launched === true &&
|
|
47
|
+
step.completed === true &&
|
|
48
|
+
step.crashed === false &&
|
|
49
|
+
step.timedOut !== true &&
|
|
50
|
+
step.exitCode === 0);
|
|
51
|
+
}
|
|
52
|
+
export function resolveVerifiedHandoffOutcome(input) {
|
|
53
|
+
if (STOPPED_LIFECYCLE_STATES.has(input.lifecycleState) ||
|
|
54
|
+
input.executionStatus === "write_blocked" ||
|
|
55
|
+
input.executionStatus === "sandbox_blocked" ||
|
|
56
|
+
input.executionStatus === "policy_rejected") {
|
|
57
|
+
return "STOPPED";
|
|
58
|
+
}
|
|
59
|
+
if (input.executionStatus === "failed" ||
|
|
60
|
+
input.evidenceContradicted === true ||
|
|
61
|
+
(input.mutationRequired === true &&
|
|
62
|
+
(input.changedFileCount ?? 0) === 0 &&
|
|
63
|
+
input.definitionOfDonePreSatisfied !== true)) {
|
|
64
|
+
return "NEEDS_REVIEW";
|
|
65
|
+
}
|
|
66
|
+
const evidenceTrustworthy = input.receiptIntegrity === "verified";
|
|
67
|
+
const scopeAcceptable = input.scopeStatus === undefined ||
|
|
68
|
+
input.scopeStatus === "WITHIN_SCOPE" ||
|
|
69
|
+
input.scopeStatus === "NOT_EVALUATED";
|
|
70
|
+
const testIntegrityAcceptable = input.testIntegrityStatus === undefined ||
|
|
71
|
+
input.testIntegrityStatus === "UNCHANGED" ||
|
|
72
|
+
input.testIntegrityStatus === "AUTHORIZED_CHANGE" ||
|
|
73
|
+
input.testIntegrityStatus === "NOT_EVALUATED";
|
|
74
|
+
if (input.verificationStatus === "passed" &&
|
|
75
|
+
evidenceTrustworthy &&
|
|
76
|
+
scopeAcceptable &&
|
|
77
|
+
testIntegrityAcceptable &&
|
|
78
|
+
input.unresolvedWorkCount === 0) {
|
|
79
|
+
return "VERIFIED";
|
|
80
|
+
}
|
|
81
|
+
return "NEEDS_REVIEW";
|
|
82
|
+
}
|
|
83
|
+
function toEvidenceStatus(status) {
|
|
84
|
+
switch (status) {
|
|
85
|
+
case "passed":
|
|
86
|
+
return "PASSED";
|
|
87
|
+
case "failed":
|
|
88
|
+
return "FAILED";
|
|
89
|
+
case "contradicted":
|
|
90
|
+
return "CONTRADICTED";
|
|
91
|
+
case "not_run":
|
|
92
|
+
return "NOT_RUN";
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function toCheck(step) {
|
|
96
|
+
const status = !step.launched
|
|
97
|
+
? "NOT_RUN"
|
|
98
|
+
: step.timedOut
|
|
99
|
+
? "FAILED"
|
|
100
|
+
: step.exitCode === 0
|
|
101
|
+
? "PASSED"
|
|
102
|
+
: "FAILED";
|
|
103
|
+
return {
|
|
104
|
+
command: step.command,
|
|
105
|
+
status,
|
|
106
|
+
...(step.exitCode !== undefined ? { exitCode: step.exitCode } : {}),
|
|
107
|
+
...(step.timedOut !== undefined ? { timedOut: step.timedOut } : {}),
|
|
108
|
+
...(step.detail ? { detail: step.detail } : {}),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
// Main builder
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
export function buildVerifiedHandoff(input) {
|
|
115
|
+
const generatedAt = input.generatedAt ?? new Date().toISOString();
|
|
116
|
+
const changedFiles = input.changedFiles ?? [];
|
|
117
|
+
const unresolvedWork = input.unresolvedWork ?? [];
|
|
118
|
+
const scope = {
|
|
119
|
+
status: input.scope?.status ?? "NOT_EVALUATED",
|
|
120
|
+
allowedPaths: input.scope?.allowedPaths ?? input.loop.task.allowedPaths ?? [],
|
|
121
|
+
deniedPaths: input.scope?.deniedPaths ?? input.loop.task.deniedPaths ?? [],
|
|
122
|
+
changedFiles: input.scope?.changedFiles ?? changedFiles,
|
|
123
|
+
violations: input.scope?.violations ?? [],
|
|
124
|
+
};
|
|
125
|
+
const testIntegrityStatus = input.testIntegrity?.status ?? "NOT_EVALUATED";
|
|
126
|
+
const testIntegrity = {
|
|
127
|
+
verdict: toTestIntegrityVerdict(testIntegrityStatus),
|
|
128
|
+
status: testIntegrityStatus,
|
|
129
|
+
protectedPaths: input.testIntegrity?.protectedPaths ?? [],
|
|
130
|
+
changedProtectedPaths: input.testIntegrity?.changedProtectedPaths ?? [],
|
|
131
|
+
findings: input.testIntegrity?.findings ?? [],
|
|
132
|
+
summary: input.testIntegrity?.summary ??
|
|
133
|
+
"Test integrity was not evaluated for this run.",
|
|
134
|
+
};
|
|
135
|
+
const outcome = resolveVerifiedHandoffOutcome({
|
|
136
|
+
lifecycleState: input.loop.lifecycleState,
|
|
137
|
+
executionStatus: input.executionStatus,
|
|
138
|
+
verificationStatus: input.verification.status,
|
|
139
|
+
receiptIntegrity: input.receiptIntegrity.state,
|
|
140
|
+
scopeStatus: scope.status,
|
|
141
|
+
testIntegrityStatus: testIntegrity.status,
|
|
142
|
+
mutationRequired: input.mutationRequired ?? input.loop.task.mutationMode === "edit",
|
|
143
|
+
changedFileCount: scope.changedFiles.length,
|
|
144
|
+
definitionOfDonePreSatisfied: input.definitionOfDonePreSatisfied,
|
|
145
|
+
evidenceContradicted: input.evidenceContradicted ?? input.verification.status === "contradicted",
|
|
146
|
+
unresolvedWorkCount: unresolvedWork.length,
|
|
147
|
+
});
|
|
148
|
+
const handoffId = `vh_${createHash("sha256")
|
|
149
|
+
.update(`${input.loop.loopId}:${generatedAt}`)
|
|
150
|
+
.digest("hex")
|
|
151
|
+
.slice(0, 16)}`;
|
|
152
|
+
return {
|
|
153
|
+
schemaVersion: "1.0.0",
|
|
154
|
+
handoffId,
|
|
155
|
+
loopId: input.loop.loopId,
|
|
156
|
+
generatedAt,
|
|
157
|
+
task: {
|
|
158
|
+
title: input.loop.task.title,
|
|
159
|
+
objective: input.loop.task.objective,
|
|
160
|
+
},
|
|
161
|
+
definitionOfDone: {
|
|
162
|
+
acceptanceCriteria: input.loop.task.acceptanceCriteria ?? [],
|
|
163
|
+
verificationPlan: input.loop.task.verificationPlan,
|
|
164
|
+
},
|
|
165
|
+
outcome,
|
|
166
|
+
sourceStatus: {
|
|
167
|
+
status: input.loop.status,
|
|
168
|
+
lifecycleState: input.loop.lifecycleState,
|
|
169
|
+
},
|
|
170
|
+
verification: {
|
|
171
|
+
status: toEvidenceStatus(input.verification.status),
|
|
172
|
+
summary: input.verification.summary,
|
|
173
|
+
checks: input.verification.steps.map(toCheck),
|
|
174
|
+
warnings: input.verification.warnings,
|
|
175
|
+
},
|
|
176
|
+
requirements: input.requirements ?? [],
|
|
177
|
+
scope,
|
|
178
|
+
testIntegrity,
|
|
179
|
+
unresolvedWork,
|
|
180
|
+
...(input.stopReason ? { stopReason: input.stopReason } : {}),
|
|
181
|
+
recovery: {
|
|
182
|
+
rollbackBoundaryAvailable: input.recovery?.rollbackBoundaryAvailable ?? false,
|
|
183
|
+
rollbackAttempted: input.recovery?.rollbackAttempted ?? false,
|
|
184
|
+
...(input.recovery?.rollbackSucceeded !== undefined
|
|
185
|
+
? { rollbackSucceeded: input.recovery.rollbackSucceeded }
|
|
186
|
+
: {}),
|
|
187
|
+
...(input.recovery?.isolatedRef
|
|
188
|
+
? { isolatedRef: input.recovery.isolatedRef }
|
|
189
|
+
: {}),
|
|
190
|
+
...(input.recovery?.nextCommand
|
|
191
|
+
? { nextCommand: input.recovery.nextCommand }
|
|
192
|
+
: {}),
|
|
193
|
+
summary: input.recovery?.summary ??
|
|
194
|
+
"No explicit recovery evidence was supplied to the handoff builder.",
|
|
195
|
+
},
|
|
196
|
+
usage: {
|
|
197
|
+
attempts: input.loop.attempts.length,
|
|
198
|
+
actualUsd: input.loop.cost.actualUsd,
|
|
199
|
+
...(input.loop.cost.estimatedUsd !== undefined
|
|
200
|
+
? { estimatedUsd: input.loop.cost.estimatedUsd }
|
|
201
|
+
: {}),
|
|
202
|
+
tokensIn: input.loop.cost.tokensIn,
|
|
203
|
+
tokensOut: input.loop.cost.tokensOut,
|
|
204
|
+
costProvenance: input.loop.cost.provenance ??
|
|
205
|
+
"unavailable",
|
|
206
|
+
},
|
|
207
|
+
receiptIntegrity: input.receiptIntegrity,
|
|
208
|
+
nextAction: input.nextAction,
|
|
209
|
+
};
|
|
210
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@martinloop/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"mcpName": "io.github.Keesan12/martin-loop",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
7
|
-
"description": "
|
|
7
|
+
"description": "MCP server for AI coding agents — verifier gates, stop limits, and Verified Handoffs.",
|
|
8
8
|
"license": "Apache-2.0",
|
|
9
9
|
"author": "MartinLoop contributors",
|
|
10
10
|
"homepage": "https://martinloop.com/",
|
|
@@ -18,18 +18,11 @@
|
|
|
18
18
|
},
|
|
19
19
|
"keywords": [
|
|
20
20
|
"mcp",
|
|
21
|
-
"mcp-server",
|
|
22
21
|
"model-context-protocol",
|
|
23
22
|
"martin-loop",
|
|
24
23
|
"ai-agent",
|
|
25
|
-
"ai-governance",
|
|
26
|
-
"agent-governance",
|
|
27
24
|
"claude",
|
|
28
|
-
"claude-code",
|
|
29
25
|
"codex",
|
|
30
|
-
"cursor",
|
|
31
|
-
"budget-guardrails",
|
|
32
|
-
"verifier-gates",
|
|
33
26
|
"martin_doctor",
|
|
34
27
|
"martin_triage_runs",
|
|
35
28
|
"martin_run_dossier",
|
|
@@ -66,9 +59,7 @@
|
|
|
66
59
|
"test": "vitest run --maxWorkers=1",
|
|
67
60
|
"lint": "tsc -p tsconfig.json --noEmit",
|
|
68
61
|
"start": "node dist/server.js",
|
|
69
|
-
"inspect:live": "node ./scripts/inspect-live.mjs"
|
|
70
|
-
"mcpb:build": "node ./mcpb/build-mcpb.mjs",
|
|
71
|
-
"mcpb:validate": "mcpb validate ./dist-mcpb/martinloop"
|
|
62
|
+
"inspect:live": "node ./scripts/inspect-live.mjs"
|
|
72
63
|
},
|
|
73
64
|
"dependencies": {
|
|
74
65
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
@@ -80,7 +71,6 @@
|
|
|
80
71
|
"ts-morph": "^21.0.0"
|
|
81
72
|
},
|
|
82
73
|
"devDependencies": {
|
|
83
|
-
"@anthropic-ai/mcpb": "2.1.2",
|
|
84
74
|
"@martin/contracts": "workspace:*"
|
|
85
75
|
}
|
|
86
76
|
}
|
package/server.json
CHANGED
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.Keesan12/martin-loop",
|
|
4
4
|
"title": "Martin Loop",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "MCP server for AI coding agents — verifier gates, stop limits, and Verified Handoffs.",
|
|
6
6
|
"repository": {
|
|
7
7
|
"url": "https://github.com/Keesan12/martin-loop",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.5.0",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "@martinloop/mcp",
|
|
15
|
-
"version": "0.
|
|
15
|
+
"version": "0.5.0",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { MartinAdapter, MartinAdapterRequest, MartinAdapterResult } from "../core/index.js";
|
|
2
|
-
export interface StubAgentCliAdapterOptions {
|
|
3
|
-
command: string[];
|
|
4
|
-
profile?: string;
|
|
5
|
-
label?: string;
|
|
6
|
-
responder?: (request: MartinAdapterRequest) => Promise<MartinAdapterResult> | MartinAdapterResult;
|
|
7
|
-
}
|
|
8
|
-
export declare function createStubAgentCliAdapter(options: StubAgentCliAdapterOptions): MartinAdapter;
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { createAdapterCapabilities } from "./runtime-support.js";
|
|
2
|
-
export function createStubAgentCliAdapter(options) {
|
|
3
|
-
const metadata = {
|
|
4
|
-
command: options.command.join(" "),
|
|
5
|
-
providerId: "agent-cli",
|
|
6
|
-
model: options.profile ?? options.command[0] ?? "default",
|
|
7
|
-
transport: "cli",
|
|
8
|
-
capabilities: createAdapterCapabilities(),
|
|
9
|
-
...(options.profile ? { profile: options.profile } : {})
|
|
10
|
-
};
|
|
11
|
-
return {
|
|
12
|
-
adapterId: `agent-cli:${options.command.join(":")}`,
|
|
13
|
-
kind: "agent-cli",
|
|
14
|
-
label: options.label ?? `Stub agent CLI (${options.command.join(" ")})`,
|
|
15
|
-
metadata,
|
|
16
|
-
async execute(request) {
|
|
17
|
-
if (options.responder) {
|
|
18
|
-
return await options.responder(request);
|
|
19
|
-
}
|
|
20
|
-
return {
|
|
21
|
-
status: "failed",
|
|
22
|
-
summary: `Stub agent CLI ${options.command.join(" ")} did not execute a live session.`,
|
|
23
|
-
usage: {
|
|
24
|
-
actualUsd: 0,
|
|
25
|
-
tokensIn: 0,
|
|
26
|
-
tokensOut: 0,
|
|
27
|
-
provenance: "unavailable"
|
|
28
|
-
},
|
|
29
|
-
verification: {
|
|
30
|
-
passed: false,
|
|
31
|
-
summary: "No CLI execution was attempted."
|
|
32
|
-
},
|
|
33
|
-
failure: {
|
|
34
|
-
message: `Agent CLI ${options.command.join(" ")} is not configured for live execution.`,
|
|
35
|
-
classHint: "environment_mismatch"
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { MartinAdapter } from "../core/index.js";
|
|
2
|
-
import { type SpawnLike } from "./cli-bridge.js";
|
|
3
|
-
export interface VerifierOnlyAdapterOptions {
|
|
4
|
-
workingDirectory?: string;
|
|
5
|
-
verifyTimeoutMs?: number;
|
|
6
|
-
label?: string;
|
|
7
|
-
spawnImpl?: SpawnLike;
|
|
8
|
-
}
|
|
9
|
-
export declare function createVerifierOnlyAdapter(options?: VerifierOnlyAdapterOptions): MartinAdapter;
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { readGitChangedFiles, runVerification } from "./cli-bridge.js";
|
|
2
|
-
import { createAdapterCapabilities, normalizeUsage } from "./runtime-support.js";
|
|
3
|
-
export function createVerifierOnlyAdapter(options = {}) {
|
|
4
|
-
const workingDirectory = options.workingDirectory ?? process.cwd();
|
|
5
|
-
const verifyTimeoutMs = options.verifyTimeoutMs ?? 120_000;
|
|
6
|
-
return {
|
|
7
|
-
adapterId: "direct:verifier:verify-only",
|
|
8
|
-
kind: "direct-provider",
|
|
9
|
-
label: options.label ?? "Verifier-only adapter",
|
|
10
|
-
metadata: {
|
|
11
|
-
providerId: "verifier",
|
|
12
|
-
model: "verify-only",
|
|
13
|
-
transport: "cli",
|
|
14
|
-
capabilities: createAdapterCapabilities({
|
|
15
|
-
usageSettlement: true,
|
|
16
|
-
diffArtifacts: true
|
|
17
|
-
})
|
|
18
|
-
},
|
|
19
|
-
async execute(request) {
|
|
20
|
-
const shouldTrackVerifierWrites = request.context.verificationPlan.length > 0 ||
|
|
21
|
-
(request.context.verificationStack?.length ?? 0) > 0;
|
|
22
|
-
const baselineChangedFiles = shouldTrackVerifierWrites
|
|
23
|
-
? new Set(await readGitChangedFiles(workingDirectory, 5_000, options.spawnImpl))
|
|
24
|
-
: new Set();
|
|
25
|
-
const verification = await runVerification(request.context.verificationPlan, workingDirectory, verifyTimeoutMs, request.context.verificationStack, options.spawnImpl);
|
|
26
|
-
const changedFiles = shouldTrackVerifierWrites
|
|
27
|
-
? (await readGitChangedFiles(workingDirectory, 5_000, options.spawnImpl)).filter((file) => !baselineChangedFiles.has(file))
|
|
28
|
-
: [];
|
|
29
|
-
const execution = { changedFiles };
|
|
30
|
-
if (verification.passed) {
|
|
31
|
-
return {
|
|
32
|
-
status: "completed",
|
|
33
|
-
summary: changedFiles.length > 0
|
|
34
|
-
? `Verifier-only run completed but modified files: ${changedFiles.join(", ")}`
|
|
35
|
-
: "Verifier-only run completed without file edits.",
|
|
36
|
-
usage: normalizeUsage({
|
|
37
|
-
actualUsd: 0,
|
|
38
|
-
tokensIn: 0,
|
|
39
|
-
tokensOut: 0,
|
|
40
|
-
provenance: "actual"
|
|
41
|
-
}),
|
|
42
|
-
verification,
|
|
43
|
-
execution
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
return {
|
|
47
|
-
status: "failed",
|
|
48
|
-
summary: "Verifier-only run failed.",
|
|
49
|
-
usage: normalizeUsage({
|
|
50
|
-
actualUsd: 0,
|
|
51
|
-
tokensIn: 0,
|
|
52
|
-
tokensOut: 0,
|
|
53
|
-
provenance: "actual"
|
|
54
|
-
}),
|
|
55
|
-
verification,
|
|
56
|
-
execution,
|
|
57
|
-
failure: {
|
|
58
|
-
message: verification.summary
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
}
|