Skip to content

Commit 6659a81

Browse files
hyperpolymathclaude
andcommitted
feat(adr-0006): migrate 5 cartridges to 5-symbol ABI (Pattern B batch 14)
Pattern B migration (turso-mcp,typed-wasm-mcp,ums-mcp,vault-mcp,verisimdb-mcp). All 5 ADR-0005+0006 exports added; boj_cartridge_invoke dispatches cartridge.json tools to Grade-D-Alpha stub bodies via cartridge_shim. Tests passing per cartridge. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 8cc9288 commit 6659a81

10 files changed

Lines changed: 543 additions & 0 deletions

File tree

cartridges/turso-mcp/ffi/build.zig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,26 @@ pub fn build(b: *std.Build) void {
88
const optimize = b.standardOptimizeOption(.{});
99

1010
// Module
11+
// Shared ADR-0006 invoke-shim module (relative path up to boj-server trunk).
12+
13+
const shim_mod = b.addModule("cartridge_shim", .{
14+
15+
.root_source_file = b.path("../../../ffi/zig/src/cartridge_shim.zig"),
16+
17+
.target = target,
18+
19+
.optimize = optimize,
20+
21+
});
22+
1123
const ffi_mod = b.addModule("turso_mcp", .{
1224
.root_source_file = b.path("turso_mcp_ffi.zig"),
1325
.target = target,
1426
.optimize = optimize,
1527
});
1628

29+
ffi_mod.addImport("cartridge_shim", shim_mod);
30+
1731
// Shared library
1832
const lib = b.addLibrary(.{
1933
.name = "turso_mcp",

cartridges/turso-mcp/ffi/turso_mcp_ffi.zig

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,59 @@ pub export fn turso_mcp_reset() void {
208208
}
209209

210210
// ---------------------------------------------------------------------------
211+
// ═══════════════════════════════════════════════════════════════════════
212+
// Standard ABI (ADR-0005 four symbols + ADR-0006 invoke)
213+
// ═══════════════════════════════════════════════════════════════════════
214+
215+
const shim = @import("cartridge_shim");
216+
217+
const CARTRIDGE_NAME_PTR: [*:0]const u8 = "turso-mcp";
218+
const CARTRIDGE_VERSION_PTR: [*:0]const u8 = "0.1.0";
219+
220+
export fn boj_cartridge_init() callconv(.c) c_int {
221+
return 0;
222+
}
223+
224+
export fn boj_cartridge_deinit() callconv(.c) void {}
225+
226+
export fn boj_cartridge_name() callconv(.c) [*:0]const u8 {
227+
return CARTRIDGE_NAME_PTR;
228+
}
229+
230+
export fn boj_cartridge_version() callconv(.c) [*:0]const u8 {
231+
return CARTRIDGE_VERSION_PTR;
232+
}
233+
234+
/// Dispatch the cartridge.json MCP tools. Grade D Alpha stubs.
235+
export fn boj_cartridge_invoke(
236+
tool_name: [*c]const u8,
237+
json_args: [*c]const u8,
238+
out_buf: [*c]u8,
239+
in_out_len: [*c]usize,
240+
) callconv(.c) i32 {
241+
_ = json_args;
242+
if (shim.invokeArgsNull(tool_name, out_buf, in_out_len)) return shim.RC_BAD_ARGS;
243+
244+
const body: []const u8 = if (shim.toolIs(tool_name, "turso_connect"))
245+
"{\"result\":{\"status\":\"stub\"}}"
246+
else if (shim.toolIs(tool_name, "turso_query"))
247+
"{\"result\":{\"matches\":[],\"status\":\"stub\"}}"
248+
else if (shim.toolIs(tool_name, "turso_execute"))
249+
"{\"result\":{\"status\":\"stub\"}}"
250+
else if (shim.toolIs(tool_name, "turso_batch"))
251+
"{\"result\":{\"status\":\"stub\"}}"
252+
else if (shim.toolIs(tool_name, "turso_list_tables"))
253+
"{\"result\":{\"items\":[],\"count\":0,\"status\":\"stub\"}}"
254+
else if (shim.toolIs(tool_name, "turso_sync"))
255+
"{\"result\":{\"status\":\"stub\"}}"
256+
else if (shim.toolIs(tool_name, "turso_disconnect"))
257+
"{\"result\":{\"status\":\"stub\"}}"
258+
else
259+
return shim.RC_UNKNOWN_TOOL;
260+
261+
return shim.writeResult(out_buf, in_out_len, body);
262+
}
263+
211264
// Tests
212265
// ---------------------------------------------------------------------------
213266

@@ -290,3 +343,50 @@ test "action requires connection" {
290343
try std.testing.expectEqual(@as(c_int, 0), turso_mcp_action_requires_connection(0)); // list_databases
291344
try std.testing.expectEqual(@as(c_int, 0), turso_mcp_action_requires_connection(99)); // out of range
292345
}
346+
347+
// ═══════════════════════════════════════════════════════════════════════
348+
// ADR-0006 invoke dispatch tests
349+
// ═══════════════════════════════════════════════════════════════════════
350+
351+
test "boj_cartridge_name returns turso-mcp" {
352+
const n = std.mem.span(boj_cartridge_name());
353+
try std.testing.expectEqualStrings("turso-mcp", n);
354+
}
355+
356+
test "boj_cartridge_init returns 0" {
357+
try std.testing.expectEqual(@as(c_int, 0), boj_cartridge_init());
358+
}
359+
360+
test "invoke: each declared tool succeeds" {
361+
var buf: [256]u8 = undefined;
362+
const tools = [_][]const u8{
363+
"turso_connect",
364+
"turso_query",
365+
"turso_execute",
366+
"turso_batch",
367+
"turso_list_tables",
368+
"turso_sync",
369+
"turso_disconnect",
370+
};
371+
for (tools) |t| {
372+
var len: usize = buf.len;
373+
const rc = boj_cartridge_invoke(t.ptr, "{}", &buf, &len);
374+
try std.testing.expectEqual(@as(i32, 0), rc);
375+
try std.testing.expect(std.mem.indexOf(u8, buf[0..len], "result") != null);
376+
}
377+
}
378+
379+
test "invoke: unknown tool returns -1" {
380+
var buf: [64]u8 = undefined;
381+
var len: usize = buf.len;
382+
const rc = boj_cartridge_invoke("nope", "{}", &buf, &len);
383+
try std.testing.expectEqual(@as(i32, -1), rc);
384+
}
385+
386+
test "invoke: buffer too small returns -3" {
387+
var buf: [4]u8 = undefined;
388+
var len: usize = buf.len;
389+
const rc = boj_cartridge_invoke("turso_connect", "{}", &buf, &len);
390+
try std.testing.expectEqual(@as(i32, -3), rc);
391+
try std.testing.expect(len > 4);
392+
}

cartridges/typed-wasm-mcp/ffi/build.zig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,26 @@ pub fn build(b: *std.Build) void {
77
const target = b.standardTargetOptions(.{});
88
const optimize = b.standardOptimizeOption(.{});
99

10+
// Shared ADR-0006 invoke-shim module (relative path up to boj-server trunk).
11+
12+
const shim_mod = b.addModule("cartridge_shim", .{
13+
14+
.root_source_file = b.path("../../../ffi/zig/src/cartridge_shim.zig"),
15+
16+
.target = target,
17+
18+
.optimize = optimize,
19+
20+
});
21+
1022
const ffi_mod = b.addModule("typed_wasm_mcp", .{
1123
.root_source_file = b.path("typed_wasm_ffi.zig"),
1224
.target = target,
1325
.optimize = optimize,
1426
});
1527

28+
ffi_mod.addImport("cartridge_shim", shim_mod);
29+
1630
const lib = b.addLibrary(.{
1731
.name = "typed_wasm_mcp",
1832
.root_module = ffi_mod,

cartridges/typed-wasm-mcp/ffi/typed_wasm_ffi.zig

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,51 @@ export fn typed_wasm_compile_module(module_path: [*c]const u8, target: u8) i32 {
2424
return 0; // Stub
2525
}
2626

27+
// ═══════════════════════════════════════════════════════════════════════
28+
// Standard ABI (ADR-0005 four symbols + ADR-0006 invoke)
29+
// ═══════════════════════════════════════════════════════════════════════
30+
31+
const shim = @import("cartridge_shim");
32+
33+
const CARTRIDGE_NAME_PTR: [*:0]const u8 = "typed-wasm-mcp";
34+
const CARTRIDGE_VERSION_PTR: [*:0]const u8 = "0.1.0";
35+
36+
export fn boj_cartridge_init() callconv(.c) c_int {
37+
return 0;
38+
}
39+
40+
export fn boj_cartridge_deinit() callconv(.c) void {}
41+
42+
export fn boj_cartridge_name() callconv(.c) [*:0]const u8 {
43+
return CARTRIDGE_NAME_PTR;
44+
}
45+
46+
export fn boj_cartridge_version() callconv(.c) [*:0]const u8 {
47+
return CARTRIDGE_VERSION_PTR;
48+
}
49+
50+
/// Dispatch the cartridge.json MCP tools. Grade D Alpha stubs.
51+
export fn boj_cartridge_invoke(
52+
tool_name: [*c]const u8,
53+
json_args: [*c]const u8,
54+
out_buf: [*c]u8,
55+
in_out_len: [*c]usize,
56+
) callconv(.c) i32 {
57+
_ = json_args;
58+
if (shim.invokeArgsNull(tool_name, out_buf, in_out_len)) return shim.RC_BAD_ARGS;
59+
60+
const body: []const u8 = if (shim.toolIs(tool_name, "typed_wasm_validate_module"))
61+
"{\"result\":{\"status\":\"stub\"}}"
62+
else if (shim.toolIs(tool_name, "typed_wasm_check_types"))
63+
"{\"result\":{\"status\":\"stub\"}}"
64+
else if (shim.toolIs(tool_name, "typed_wasm_compile_module"))
65+
"{\"result\":{\"status\":\"stub\"}}"
66+
else
67+
return shim.RC_UNKNOWN_TOOL;
68+
69+
return shim.writeResult(out_buf, in_out_len, body);
70+
}
71+
2772
// ── Tests ──
2873

2974
test "validate rejects null path" {
@@ -38,3 +83,46 @@ test "validate returns bounded level" {
3883
test "compile rejects invalid target" {
3984
try std.testing.expectEqual(@as(i32, -1), typed_wasm_compile_module("test.wasm", 99));
4085
}
86+
87+
// ═══════════════════════════════════════════════════════════════════════
88+
// ADR-0006 invoke dispatch tests
89+
// ═══════════════════════════════════════════════════════════════════════
90+
91+
test "boj_cartridge_name returns typed-wasm-mcp" {
92+
const n = std.mem.span(boj_cartridge_name());
93+
try std.testing.expectEqualStrings("typed-wasm-mcp", n);
94+
}
95+
96+
test "boj_cartridge_init returns 0" {
97+
try std.testing.expectEqual(@as(c_int, 0), boj_cartridge_init());
98+
}
99+
100+
test "invoke: each declared tool succeeds" {
101+
var buf: [256]u8 = undefined;
102+
const tools = [_][]const u8{
103+
"typed_wasm_validate_module",
104+
"typed_wasm_check_types",
105+
"typed_wasm_compile_module",
106+
};
107+
for (tools) |t| {
108+
var len: usize = buf.len;
109+
const rc = boj_cartridge_invoke(t.ptr, "{}", &buf, &len);
110+
try std.testing.expectEqual(@as(i32, 0), rc);
111+
try std.testing.expect(std.mem.indexOf(u8, buf[0..len], "result") != null);
112+
}
113+
}
114+
115+
test "invoke: unknown tool returns -1" {
116+
var buf: [64]u8 = undefined;
117+
var len: usize = buf.len;
118+
const rc = boj_cartridge_invoke("nope", "{}", &buf, &len);
119+
try std.testing.expectEqual(@as(i32, -1), rc);
120+
}
121+
122+
test "invoke: buffer too small returns -3" {
123+
var buf: [4]u8 = undefined;
124+
var len: usize = buf.len;
125+
const rc = boj_cartridge_invoke("typed_wasm_validate_module", "{}", &buf, &len);
126+
try std.testing.expectEqual(@as(i32, -3), rc);
127+
try std.testing.expect(len > 4);
128+
}

cartridges/ums-mcp/ffi/build.zig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,26 @@ pub fn build(b: *std.Build) void {
99
const target = b.standardTargetOptions(.{});
1010
const optimize = b.standardOptimizeOption(.{});
1111

12+
// Shared ADR-0006 invoke-shim module (relative path up to boj-server trunk).
13+
14+
const shim_mod = b.addModule("cartridge_shim", .{
15+
16+
.root_source_file = b.path("../../../ffi/zig/src/cartridge_shim.zig"),
17+
18+
.target = target,
19+
20+
.optimize = optimize,
21+
22+
});
23+
1224
const ums_mod = b.addModule("ums_ffi", .{
1325
.root_source_file = b.path("ums_ffi.zig"),
1426
.target = target,
1527
.optimize = optimize,
1628
});
1729

30+
ums_mod.addImport("cartridge_shim", shim_mod);
31+
1832
// ── Tests ────────────────────────────────────────────────────────
1933
const ums_tests = b.addTest(.{
2034
.root_module = ums_mod,

0 commit comments

Comments
 (0)