@martinloop/mcp 0.2.7 → 0.3.1
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 +49 -104
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/prompts.d.ts +1 -1
- package/dist/resources.d.ts +1 -1
- package/dist/resources.js +2 -2
- package/dist/server-validation.d.ts +1 -0
- package/dist/server-validation.js +8 -0
- package/dist/server.js +87 -9
- package/dist/tools/doctor.d.ts +39 -1
- package/dist/tools/doctor.js +68 -9
- package/dist/tools/eval.js +3 -2
- package/dist/tools/get-run.d.ts +3 -0
- package/dist/tools/get-run.js +3 -1
- package/dist/tools/get-verification-results.d.ts +3 -0
- package/dist/tools/get-verification-results.js +3 -1
- package/dist/tools/plan.js +4 -2
- package/dist/tools/pr-tools.js +2 -1
- package/dist/tools/preflight.d.ts +41 -1
- package/dist/tools/preflight.js +74 -19
- package/dist/tools/run-dossier.d.ts +3 -0
- package/dist/tools/run-dossier.js +5 -2
- package/dist/tools/run-loop.d.ts +7 -2
- package/dist/tools/run-loop.js +67 -35
- package/dist/tools/run-store.js +67 -15
- package/dist/tools/tool-errors.js +1 -1
- package/dist/tools/tool-support.d.ts +8 -3
- package/dist/tools/tool-support.js +61 -18
- package/dist/tools/workflow-governance.d.ts +19 -3
- package/dist/tools/workflow-governance.js +107 -55
- package/dist/vendor/adapters/claude-cli.d.ts +45 -3
- package/dist/vendor/adapters/claude-cli.js +465 -45
- package/dist/vendor/adapters/cli-bridge.d.ts +46 -0
- package/dist/vendor/adapters/cli-bridge.js +147 -38
- package/dist/vendor/adapters/codex-launcher.d.ts +76 -0
- package/dist/vendor/adapters/codex-launcher.js +538 -0
- package/dist/vendor/adapters/index.d.ts +3 -2
- package/dist/vendor/adapters/index.js +3 -2
- package/dist/vendor/adapters/openai-compatible.d.ts +19 -4
- package/dist/vendor/adapters/openai-compatible.js +50 -19
- package/dist/vendor/adapters/runtime-support.d.ts +3 -0
- package/dist/vendor/adapters/runtime-support.js +9 -1
- package/dist/vendor/adapters/stub-direct-provider.js +3 -0
- package/dist/vendor/adapters/verifier-only.d.ts +2 -0
- package/dist/vendor/adapters/verifier-only.js +11 -4
- package/dist/vendor/contracts/index.d.ts +39 -0
- package/dist/vendor/contracts/index.js +2 -0
- package/dist/vendor/core/context-integrity.js +28 -3
- package/dist/vendor/core/grounding.d.ts +1 -0
- package/dist/vendor/core/grounding.js +6 -2
- package/dist/vendor/core/index.d.ts +24 -3
- package/dist/vendor/core/index.js +113 -21
- package/dist/vendor/core/leash.js +85 -8
- package/dist/vendor/core/persistence/index.d.ts +2 -0
- package/dist/vendor/core/persistence/index.js +1 -0
- package/dist/vendor/core/persistence/integrity.d.ts +38 -0
- package/dist/vendor/core/persistence/integrity.js +248 -0
- package/dist/vendor/core/persistence/store.d.ts +7 -0
- package/dist/vendor/core/persistence/store.js +25 -1
- package/dist/vendor/core/policy.d.ts +9 -0
- package/dist/workflow-state.d.ts +9 -0
- package/dist/workflow-state.js +46 -3
- package/package.json +2 -2
- package/server.json +2 -2
|
@@ -12,6 +12,8 @@ export interface RunContract {
|
|
|
12
12
|
export interface AttemptArtifacts {
|
|
13
13
|
/** Compiled PromptPacket written as compiled-context.json */
|
|
14
14
|
compiledContext: unknown;
|
|
15
|
+
/** Structured verification evidence captured from the authoritative MartinLoop verifier (optional) */
|
|
16
|
+
verification?: unknown;
|
|
15
17
|
/** Unified diff string from the patch (optional) */
|
|
16
18
|
diff?: string;
|
|
17
19
|
/** Raw verifier command output (optional) */
|
|
@@ -35,6 +37,11 @@ export interface AttemptArtifacts {
|
|
|
35
37
|
* is durably written before the run proceeds to the next step.
|
|
36
38
|
*/
|
|
37
39
|
export interface RunStore {
|
|
40
|
+
/**
|
|
41
|
+
* Optional runs root hint for filesystem-backed stores.
|
|
42
|
+
* Orchestration should prefer this over recomputing the default home store.
|
|
43
|
+
*/
|
|
44
|
+
runsRoot?: string;
|
|
38
45
|
/**
|
|
39
46
|
* Write contract.json for a new run. Called once at run start.
|
|
40
47
|
* The contract is immutable after this point.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { appendFile, mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { appendFile, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
+
import { writeReceiptIntegrityMaterial } from "./integrity.js";
|
|
5
6
|
// ─── FileRunStore implementation ─────────────────────────────────────────────
|
|
6
7
|
export function resolveRunsRoot(env = process.env) {
|
|
7
8
|
return env["MARTIN_RUNS_DIR"]?.trim() ??
|
|
@@ -31,6 +32,7 @@ export function artifactDir(runsRoot, runId, attemptIndex) {
|
|
|
31
32
|
export function createFileRunStore(options = {}) {
|
|
32
33
|
const runsRoot = options.runsRoot ?? resolveRunsRoot();
|
|
33
34
|
return {
|
|
35
|
+
runsRoot,
|
|
34
36
|
async initRun(contract) {
|
|
35
37
|
const dir = runDir(runsRoot, contract.runId);
|
|
36
38
|
await mkdir(dir, { recursive: true });
|
|
@@ -50,6 +52,9 @@ export function createFileRunStore(options = {}) {
|
|
|
50
52
|
const dir = artifactDir(runsRoot, runId, attemptIndex);
|
|
51
53
|
await mkdir(dir, { recursive: true });
|
|
52
54
|
await writeJsonFile(join(dir, "compiled-context.json"), artifacts.compiledContext);
|
|
55
|
+
if (artifacts.verification !== undefined) {
|
|
56
|
+
await writeJsonFile(join(dir, "verification.json"), artifacts.verification);
|
|
57
|
+
}
|
|
53
58
|
if (artifacts.diff !== undefined) {
|
|
54
59
|
await writeFile(join(dir, "diff.patch"), artifacts.diff, "utf8");
|
|
55
60
|
}
|
|
@@ -79,6 +84,25 @@ export function createFileRunStore(options = {}) {
|
|
|
79
84
|
const dir = runDir(runsRoot, runId);
|
|
80
85
|
await mkdir(dir, { recursive: true });
|
|
81
86
|
await writeJsonFile(join(dir, "loop-record.json"), loop);
|
|
87
|
+
const ledgerRaw = await readFile(join(dir, "ledger.jsonl"), "utf8").catch(() => "");
|
|
88
|
+
const ledgerEntries = ledgerRaw
|
|
89
|
+
.split(/\r?\n/u)
|
|
90
|
+
.map((line) => line.trim())
|
|
91
|
+
.filter(Boolean)
|
|
92
|
+
.map((line) => JSON.parse(line));
|
|
93
|
+
await writeReceiptIntegrityMaterial({
|
|
94
|
+
runId,
|
|
95
|
+
runsRoot,
|
|
96
|
+
loopRecord: loop,
|
|
97
|
+
ledgerEntries,
|
|
98
|
+
scope: loop.receiptScope ??
|
|
99
|
+
{
|
|
100
|
+
...(loop.task.repoRoot ? { repoRoot: loop.task.repoRoot } : {}),
|
|
101
|
+
...(loop.task.repoRoot ? { workingDirectory: loop.task.repoRoot } : {}),
|
|
102
|
+
runsRoot
|
|
103
|
+
},
|
|
104
|
+
signedAt: loop.updatedAt
|
|
105
|
+
});
|
|
82
106
|
}
|
|
83
107
|
};
|
|
84
108
|
}
|
|
@@ -38,6 +38,15 @@ export interface MartinAdapterResultLike {
|
|
|
38
38
|
verification: {
|
|
39
39
|
passed: boolean;
|
|
40
40
|
summary: string;
|
|
41
|
+
steps?: Array<{
|
|
42
|
+
command: string;
|
|
43
|
+
launched: boolean;
|
|
44
|
+
exitCode?: number;
|
|
45
|
+
timedOut: boolean;
|
|
46
|
+
fastFail?: boolean;
|
|
47
|
+
detail?: string;
|
|
48
|
+
}>;
|
|
49
|
+
warnings?: string[];
|
|
41
50
|
};
|
|
42
51
|
failure?: {
|
|
43
52
|
message: string;
|
package/dist/workflow-state.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { LoopBudget, ReceiptScope } from "./vendor/contracts/index.js";
|
|
1
2
|
type McpWorkflowStepName = "doctor" | "plan" | "preflight";
|
|
2
3
|
export interface RecordMcpWorkflowStepInput {
|
|
3
4
|
runsRoot: string;
|
|
@@ -6,6 +7,10 @@ export interface RecordMcpWorkflowStepInput {
|
|
|
6
7
|
objective?: string;
|
|
7
8
|
engine?: string;
|
|
8
9
|
verificationPlan?: string[];
|
|
10
|
+
receiptScope?: ReceiptScope;
|
|
11
|
+
allowedPaths?: string[];
|
|
12
|
+
deniedPaths?: string[];
|
|
13
|
+
budget?: LoopBudget;
|
|
9
14
|
}
|
|
10
15
|
export interface EvaluateMcpRunGateInput {
|
|
11
16
|
runsRoot: string;
|
|
@@ -13,6 +18,10 @@ export interface EvaluateMcpRunGateInput {
|
|
|
13
18
|
objective: string;
|
|
14
19
|
engine?: string;
|
|
15
20
|
verificationPlan?: string[];
|
|
21
|
+
receiptScope?: ReceiptScope;
|
|
22
|
+
allowedPaths?: string[];
|
|
23
|
+
deniedPaths?: string[];
|
|
24
|
+
budget?: LoopBudget;
|
|
16
25
|
}
|
|
17
26
|
export interface McpRunGateResult {
|
|
18
27
|
allowed: boolean;
|
package/dist/workflow-state.js
CHANGED
|
@@ -15,7 +15,12 @@ export async function recordMcpWorkflowStep(input) {
|
|
|
15
15
|
workingDirectory: normalizeWorkingDirectory(input.workingDirectory),
|
|
16
16
|
...(input.objective ? { objectiveKey: normalizeObjective(input.objective) } : {}),
|
|
17
17
|
...(input.engine ? { engine: input.engine } : {}),
|
|
18
|
-
...(input.verificationPlan ? { verificationPlanKey: hashVerificationPlan(input.verificationPlan) } : {})
|
|
18
|
+
...(input.verificationPlan ? { verificationPlanKey: hashVerificationPlan(input.verificationPlan) } : {}),
|
|
19
|
+
...(input.receiptScope ? { scopeKey: hashReceiptScope(input.receiptScope) } : {}),
|
|
20
|
+
...(input.allowedPaths || input.deniedPaths
|
|
21
|
+
? { pathScopeKey: hashPathScope(input.allowedPaths ?? [], input.deniedPaths ?? []) }
|
|
22
|
+
: {}),
|
|
23
|
+
...(input.budget ? { budgetKey: hashBudget(input.budget) } : {})
|
|
19
24
|
};
|
|
20
25
|
await writeWorkflowState(input.runsRoot, state);
|
|
21
26
|
}
|
|
@@ -26,18 +31,31 @@ export async function evaluateMcpRunGate(input) {
|
|
|
26
31
|
const objectiveKey = normalizeObjective(input.objective);
|
|
27
32
|
const engine = input.engine ?? "claude";
|
|
28
33
|
const verificationPlanKey = hashVerificationPlan(input.verificationPlan ?? []);
|
|
34
|
+
const scopeKey = hashReceiptScope(input.receiptScope ?? {
|
|
35
|
+
invocationRoot: input.workingDirectory,
|
|
36
|
+
workingDirectory: input.workingDirectory,
|
|
37
|
+
repoRoot: input.workingDirectory,
|
|
38
|
+
runsRoot: input.runsRoot
|
|
39
|
+
});
|
|
40
|
+
const pathScopeKey = hashPathScope(input.allowedPaths ?? [], input.deniedPaths ?? []);
|
|
41
|
+
const budgetKey = input.budget ? hashBudget(input.budget) : undefined;
|
|
29
42
|
const missingSteps = [];
|
|
30
|
-
if (!isFresh(mcpState["doctor"], DOCTOR_TTL_MS, (receipt) => receipt.workingDirectory === workingDirectory
|
|
43
|
+
if (!isFresh(mcpState["doctor"], DOCTOR_TTL_MS, (receipt) => receipt.workingDirectory === workingDirectory &&
|
|
44
|
+
receipt.scopeKey === scopeKey)) {
|
|
31
45
|
missingSteps.push("doctor");
|
|
32
46
|
}
|
|
33
47
|
if (!isFresh(mcpState["plan"], PLAN_TTL_MS, (receipt) => receipt.workingDirectory === workingDirectory &&
|
|
48
|
+
receipt.scopeKey === scopeKey &&
|
|
34
49
|
receipt.objectiveKey === objectiveKey)) {
|
|
35
50
|
missingSteps.push("plan");
|
|
36
51
|
}
|
|
37
52
|
if (!isFresh(mcpState["preflight"], PREFLIGHT_TTL_MS, (receipt) => receipt.workingDirectory === workingDirectory &&
|
|
38
53
|
receipt.objectiveKey === objectiveKey &&
|
|
39
54
|
receipt.engine === engine &&
|
|
40
|
-
receipt.verificationPlanKey === verificationPlanKey
|
|
55
|
+
receipt.verificationPlanKey === verificationPlanKey &&
|
|
56
|
+
receipt.scopeKey === scopeKey &&
|
|
57
|
+
receipt.pathScopeKey === pathScopeKey &&
|
|
58
|
+
(budgetKey === undefined || receipt.budgetKey === budgetKey))) {
|
|
41
59
|
missingSteps.push("preflight");
|
|
42
60
|
}
|
|
43
61
|
if (missingSteps.length === 0) {
|
|
@@ -100,3 +118,28 @@ function hashVerificationPlan(verificationPlan) {
|
|
|
100
118
|
const normalized = verificationPlan.map((step) => step.trim()).filter(Boolean);
|
|
101
119
|
return createHash("sha256").update(JSON.stringify(normalized)).digest("hex").slice(0, 12);
|
|
102
120
|
}
|
|
121
|
+
function hashReceiptScope(receiptScope) {
|
|
122
|
+
const normalized = {
|
|
123
|
+
invocationRoot: normalizeWorkingDirectory(receiptScope.invocationRoot ?? receiptScope.workingDirectory ?? ""),
|
|
124
|
+
workingDirectory: normalizeWorkingDirectory(receiptScope.workingDirectory ?? receiptScope.repoRoot ?? ""),
|
|
125
|
+
repoRoot: normalizeWorkingDirectory(receiptScope.repoRoot ?? receiptScope.workingDirectory ?? ""),
|
|
126
|
+
runsRoot: normalizeWorkingDirectory(receiptScope.runsRoot ?? "")
|
|
127
|
+
};
|
|
128
|
+
return createHash("sha256").update(JSON.stringify(normalized)).digest("hex").slice(0, 12);
|
|
129
|
+
}
|
|
130
|
+
function hashPathScope(allowedPaths, deniedPaths) {
|
|
131
|
+
const normalized = {
|
|
132
|
+
allowedPaths: [...new Set(allowedPaths.map((entry) => entry.trim()).filter(Boolean))].sort(),
|
|
133
|
+
deniedPaths: [...new Set(deniedPaths.map((entry) => entry.trim()).filter(Boolean))].sort()
|
|
134
|
+
};
|
|
135
|
+
return createHash("sha256").update(JSON.stringify(normalized)).digest("hex").slice(0, 12);
|
|
136
|
+
}
|
|
137
|
+
function hashBudget(budget) {
|
|
138
|
+
const normalized = {
|
|
139
|
+
maxUsd: Number(budget.maxUsd.toFixed(4)),
|
|
140
|
+
softLimitUsd: Number(budget.softLimitUsd.toFixed(4)),
|
|
141
|
+
maxIterations: budget.maxIterations,
|
|
142
|
+
maxTokens: budget.maxTokens
|
|
143
|
+
};
|
|
144
|
+
return createHash("sha256").update(JSON.stringify(normalized)).digest("hex").slice(0, 12);
|
|
145
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@martinloop/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"mcpName": "io.github.Keesan12/martin-loop",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"smoke:published": "node ./scripts/smoke-published-package.mjs",
|
|
56
56
|
"smoke:published:pack": "node ./scripts/smoke-published-package.mjs --package-spec=pack",
|
|
57
57
|
"verify:release": "node --test ../../scripts/tests/publish-mcp-workflow.test.mjs ../../scripts/tests/mcp-publish-reliability.test.mjs ../../scripts/tests/mcp-release-docs.test.mjs",
|
|
58
|
-
"test": "vitest run",
|
|
58
|
+
"test": "vitest run --maxWorkers=1",
|
|
59
59
|
"lint": "tsc -p tsconfig.json --noEmit",
|
|
60
60
|
"start": "node dist/server.js",
|
|
61
61
|
"inspect:live": "node ./scripts/inspect-live.mjs"
|
package/server.json
CHANGED
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"url": "https://github.com/Keesan12/martin-loop",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.3.1",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "@martinloop/mcp",
|
|
15
|
-
"version": "0.
|
|
15
|
+
"version": "0.3.1",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
}
|