@martinloop/mcp 0.5.3 → 0.5.5
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 +6 -6
- package/dist/server-validation.js +2 -0
- package/dist/server.js +30 -3
- package/dist/tools/run-loop.d.ts +1 -0
- package/dist/tools/run-loop.js +25 -4
- package/dist/tools/tool-response.d.ts +9 -1
- package/dist/tools/tool-response.js +7 -5
- package/dist/tools/tool-support.js +62 -271
- package/dist/vendor/adapters/claude-cli.d.ts +9 -0
- package/dist/vendor/adapters/claude-cli.js +19 -2
- package/dist/vendor/adapters/codex-capabilities.d.ts +12 -3
- package/dist/vendor/adapters/codex-capabilities.js +46 -18
- package/dist/vendor/adapters/codex-cli.d.ts +2 -1
- package/dist/vendor/adapters/codex-cli.js +12 -2
- package/dist/vendor/adapters/codex-host.d.ts +4 -1
- package/dist/vendor/adapters/codex-host.js +34 -16
- package/dist/vendor/adapters/codex-launcher.d.ts +1 -1
- package/dist/vendor/adapters/codex-launcher.js +1 -1
- package/dist/vendor/adapters/index.d.ts +2 -1
- package/dist/vendor/adapters/index.js +1 -0
- package/dist/vendor/contracts/agent-execution.d.ts +9 -0
- package/dist/vendor/contracts/agent-execution.js +14 -0
- package/dist/vendor/contracts/index.d.ts +9 -0
- package/dist/vendor/contracts/index.js +1 -0
- package/dist/vendor/core/grounding.js +42 -7
- package/dist/vendor/core/index.d.ts +5 -2
- package/dist/vendor/core/index.js +12 -3
- package/dist/vendor/presentation/governed-plan.d.ts +33 -0
- package/dist/vendor/presentation/governed-plan.js +146 -0
- package/dist/vendor/presentation/index.d.ts +7 -0
- package/dist/vendor/presentation/index.js +7 -0
- package/dist/vendor/presentation/motion.d.ts +12 -0
- package/dist/vendor/presentation/motion.js +123 -0
- package/dist/vendor/presentation/status.d.ts +8 -0
- package/dist/vendor/presentation/status.js +11 -0
- package/dist/vendor/presentation/table.d.ts +11 -0
- package/dist/vendor/presentation/table.js +47 -0
- package/dist/vendor/presentation/text.d.ts +6 -0
- package/dist/vendor/presentation/text.js +30 -0
- package/dist/vendor/presentation/theme.d.ts +31 -0
- package/dist/vendor/presentation/theme.js +82 -0
- package/dist/vendor/presentation/verified-handoff.d.ts +15 -0
- package/dist/vendor/presentation/verified-handoff.js +151 -0
- package/package.json +3 -2
- package/server.json +2 -2
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { renderTable } from "./table.js";
|
|
2
|
+
import { horizontalRule, terminalWidth, truncateVisible } from "./text.js";
|
|
3
|
+
import { bold, paint, } from "./theme.js";
|
|
4
|
+
function outcomeTone(outcome) {
|
|
5
|
+
if (outcome === "VERIFIED") {
|
|
6
|
+
return "success";
|
|
7
|
+
}
|
|
8
|
+
if (outcome === "STOPPED") {
|
|
9
|
+
return "danger";
|
|
10
|
+
}
|
|
11
|
+
return "warning";
|
|
12
|
+
}
|
|
13
|
+
function evidenceTone(status) {
|
|
14
|
+
if (status === "PASSED") {
|
|
15
|
+
return "success";
|
|
16
|
+
}
|
|
17
|
+
if (status === "FAILED" || status === "CONTRADICTED") {
|
|
18
|
+
return "danger";
|
|
19
|
+
}
|
|
20
|
+
return "warning";
|
|
21
|
+
}
|
|
22
|
+
function humanize(value) {
|
|
23
|
+
return value.replaceAll("_", " ").toLowerCase();
|
|
24
|
+
}
|
|
25
|
+
function formatCost(usd, provenance) {
|
|
26
|
+
if (provenance === "unavailable") {
|
|
27
|
+
return "unavailable";
|
|
28
|
+
}
|
|
29
|
+
const amount = "$" + usd.toFixed(2);
|
|
30
|
+
if (provenance === "actual") {
|
|
31
|
+
return amount + " provider-settled actual";
|
|
32
|
+
}
|
|
33
|
+
if (provenance === "calculated") {
|
|
34
|
+
return amount + " calculated from observed usage";
|
|
35
|
+
}
|
|
36
|
+
return amount + " estimated";
|
|
37
|
+
}
|
|
38
|
+
function checkSymbol(status) {
|
|
39
|
+
if (status === "PASSED") {
|
|
40
|
+
return "✓";
|
|
41
|
+
}
|
|
42
|
+
if (status === "FAILED" || status === "CONTRADICTED") {
|
|
43
|
+
return "✕";
|
|
44
|
+
}
|
|
45
|
+
return "•";
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Single source of truth for the trust-authority outcome calculation.
|
|
49
|
+
* Both terminal and Markdown renderers call this — never duplicate.
|
|
50
|
+
* Fail-closed: omitting executionMode or governanceClaimEligible downgrades
|
|
51
|
+
* VERIFIED → NEEDS_REVIEW, so legacy handoffs cannot claim full governance.
|
|
52
|
+
*/
|
|
53
|
+
function resolveHandoffAuthority(handoff) {
|
|
54
|
+
const executionMode = handoff.executionMode ?? "simulated";
|
|
55
|
+
const governanceClaimEligible = executionMode === "governed" && handoff.governanceClaimEligible === true;
|
|
56
|
+
const effectiveOutcome = handoff.outcome === "VERIFIED" && !governanceClaimEligible
|
|
57
|
+
? "NEEDS_REVIEW"
|
|
58
|
+
: handoff.outcome;
|
|
59
|
+
return { executionMode, governanceClaimEligible, effectiveOutcome };
|
|
60
|
+
}
|
|
61
|
+
export function renderVerifiedHandoff(handoff, options = {}) {
|
|
62
|
+
const environment = options.environment ?? {};
|
|
63
|
+
const width = terminalWidth(options.width);
|
|
64
|
+
const bounded = (line) => truncateVisible(line, width);
|
|
65
|
+
const { executionMode, governanceClaimEligible, effectiveOutcome } = resolveHandoffAuthority(handoff);
|
|
66
|
+
const outcome = effectiveOutcome.replace("_", " ");
|
|
67
|
+
const checks = handoff.verification.checks.map((check) => ({
|
|
68
|
+
check: check.command,
|
|
69
|
+
status: paint(checkSymbol(check.status) + " " + check.status.replace("_", " "), evidenceTone(check.status), environment),
|
|
70
|
+
}));
|
|
71
|
+
const lines = [
|
|
72
|
+
horizontalRule(width, "━"),
|
|
73
|
+
bold("MARTINLOOP VERIFIED HANDOFF", environment) +
|
|
74
|
+
" — " +
|
|
75
|
+
paint(outcome, outcomeTone(effectiveOutcome), environment),
|
|
76
|
+
horizontalRule(width, "━"),
|
|
77
|
+
"",
|
|
78
|
+
bounded("Task".padEnd(20) + handoff.task.objective),
|
|
79
|
+
bounded("Run".padEnd(20) + handoff.loopId),
|
|
80
|
+
bounded("Execution Mode".padEnd(20) + executionMode.replaceAll("_", " ")),
|
|
81
|
+
bounded("Governed Claim".padEnd(20) + (governanceClaimEligible ? "ELIGIBLE" : "INELIGIBLE")),
|
|
82
|
+
bounded("Verification".padEnd(20) + handoff.verification.status.replace("_", " ")),
|
|
83
|
+
bounded("Scope".padEnd(20) + handoff.scope.status.replaceAll("_", " ")),
|
|
84
|
+
bounded("Test Integrity".padEnd(20) + handoff.testIntegrity.verdict),
|
|
85
|
+
bounded("Receipt Integrity".padEnd(20) + handoff.receiptIntegrity.state),
|
|
86
|
+
bounded("Attempts".padEnd(20) + handoff.usage.attempts),
|
|
87
|
+
bounded("Cost".padEnd(20) +
|
|
88
|
+
formatCost(handoff.usage.actualUsd, handoff.usage.costProvenance)),
|
|
89
|
+
];
|
|
90
|
+
if (checks.length > 0) {
|
|
91
|
+
lines.push("", bold("VERIFICATION EVIDENCE", environment), renderTable(checks, [
|
|
92
|
+
{ header: "CHECK", value: (row) => row.check, minWidth: 24 },
|
|
93
|
+
{ header: "STATUS", value: (row) => row.status, minWidth: 18 },
|
|
94
|
+
], width));
|
|
95
|
+
}
|
|
96
|
+
if (handoff.stopReason) {
|
|
97
|
+
lines.push("", bold("STOP REASON", environment), bounded(" " + paint(humanize(handoff.stopReason), "danger", environment)));
|
|
98
|
+
}
|
|
99
|
+
lines.push("", bold("UNRESOLVED", environment));
|
|
100
|
+
if (handoff.unresolvedWork.length === 0) {
|
|
101
|
+
lines.push(" None recorded.");
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
lines.push(...handoff.unresolvedWork.map((item) => bounded(" - " + item)));
|
|
105
|
+
}
|
|
106
|
+
lines.push("", bold("RECOVERY", environment), bounded(" " + handoff.recovery.summary), "", bold("NEXT", environment), bounded(" " + handoff.nextAction), horizontalRule(width, "━"));
|
|
107
|
+
return lines.map(bounded).join("\n");
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Renders a VerifiedHandoffV1 as plain Markdown (no ANSI).
|
|
111
|
+
*
|
|
112
|
+
* CRITICAL: replicates the exact effectiveOutcome trust-authority check from
|
|
113
|
+
* renderVerifiedHandoff so that CLI and MCP surfaces always agree on
|
|
114
|
+
* VERIFIED / NEEDS REVIEW / STOPPED for the same input.
|
|
115
|
+
*/
|
|
116
|
+
export function renderVerifiedHandoffMarkdown(handoff, options = {}) {
|
|
117
|
+
void options; // width/environment unused in plain Markdown
|
|
118
|
+
const { executionMode, governanceClaimEligible, effectiveOutcome } = resolveHandoffAuthority(handoff);
|
|
119
|
+
const outcome = effectiveOutcome.replace("_", " ");
|
|
120
|
+
const lines = [
|
|
121
|
+
`## MartinLoop Verified Handoff — ${outcome}`,
|
|
122
|
+
"",
|
|
123
|
+
"| Field | Value |",
|
|
124
|
+
"|-------|-------|",
|
|
125
|
+
`| Task | ${handoff.task.objective} |`,
|
|
126
|
+
`| Run | ${handoff.loopId} |`,
|
|
127
|
+
`| Execution Mode | ${executionMode.replaceAll("_", " ")} |`,
|
|
128
|
+
`| Governed Claim | ${governanceClaimEligible ? "ELIGIBLE" : "INELIGIBLE"} |`,
|
|
129
|
+
`| Verification | ${handoff.verification.status.replace("_", " ")} |`,
|
|
130
|
+
`| Scope | ${handoff.scope.status.replaceAll("_", " ")} |`,
|
|
131
|
+
`| Test Integrity | ${handoff.testIntegrity.verdict} |`,
|
|
132
|
+
`| Receipt Integrity | ${handoff.receiptIntegrity.state} |`,
|
|
133
|
+
`| Attempts | ${handoff.usage.attempts} |`,
|
|
134
|
+
`| Cost | ${formatCost(handoff.usage.actualUsd, handoff.usage.costProvenance)} |`,
|
|
135
|
+
];
|
|
136
|
+
if (handoff.verification.checks.length > 0) {
|
|
137
|
+
lines.push("", "### Verification Evidence", "", "| Check | Status |", "|-------|--------|", ...handoff.verification.checks.map((check) => `| ${check.command} | ${checkSymbol(check.status)} ${check.status.replace("_", " ")} |`));
|
|
138
|
+
}
|
|
139
|
+
if (handoff.stopReason) {
|
|
140
|
+
lines.push("", "### Stop Reason", "", handoff.stopReason.replaceAll("_", " ").toLowerCase());
|
|
141
|
+
}
|
|
142
|
+
lines.push("", "### Unresolved");
|
|
143
|
+
if (handoff.unresolvedWork.length === 0) {
|
|
144
|
+
lines.push("", "None recorded.");
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
lines.push("", ...handoff.unresolvedWork.map((item) => `- ${item}`));
|
|
148
|
+
}
|
|
149
|
+
lines.push("", "### Recovery", "", handoff.recovery.summary, "", "### Next", "", handoff.nextAction);
|
|
150
|
+
return lines.join("\n");
|
|
151
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@martinloop/mcp",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.5",
|
|
4
4
|
"mcpName": "io.github.Keesan12/martin-loop",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -75,6 +75,7 @@
|
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
77
|
"@anthropic-ai/mcpb": "2.1.2",
|
|
78
|
-
"@martin/contracts": "workspace:*"
|
|
78
|
+
"@martin/contracts": "workspace:*",
|
|
79
|
+
"@martin/presentation": "workspace:*"
|
|
79
80
|
}
|
|
80
81
|
}
|
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.5.
|
|
10
|
+
"version": "0.5.5",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "@martinloop/mcp",
|
|
15
|
-
"version": "0.5.
|
|
15
|
+
"version": "0.5.5",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
}
|