@@ -240,6 +240,53 @@ pub export fn boj_cartridge_version() [*:0]const u8 {
240240 return "0.1.0" ;
241241}
242242
243+ // ═══════════════════════════════════════════════════════════════════════
244+ // ADR-0006 dispatch (boj_cartridge_invoke, 5th standard symbol)
245+ // ═══════════════════════════════════════════════════════════════════════
246+
247+ const shim = @import ("cartridge_shim" );
248+
249+ /// Dispatch the cartridge.json MCP tools. Grade D Alpha — each arm
250+ /// returns a stub JSON body shaped to the tool's intended response.
251+ export fn boj_cartridge_invoke (
252+ tool_name : [* c ]const u8 ,
253+ json_args : [* c ]const u8 ,
254+ out_buf : [* c ]u8 ,
255+ in_out_len : [* c ]usize ,
256+ ) callconv (.c ) i32 {
257+ _ = json_args ;
258+ if (shim .invokeArgsNull (tool_name , out_buf , in_out_len )) return shim .RC_BAD_ARGS ;
259+
260+ const body : []const u8 = if (shim .toolIs (tool_name , "lsp_start" ))
261+ "{\" result\" :{\" status\" :\" stub\" }}"
262+ else if (shim .toolIs (tool_name , "lsp_initialize" ))
263+ "{\" result\" :{\" status\" :\" stub\" }}"
264+ else if (shim .toolIs (tool_name , "lsp_open" ))
265+ "{\" result\" :{\" status\" :\" stub\" }}"
266+ else if (shim .toolIs (tool_name , "lsp_change" ))
267+ "{\" result\" :{\" status\" :\" stub\" }}"
268+ else if (shim .toolIs (tool_name , "lsp_close" ))
269+ "{\" result\" :{\" status\" :\" stub\" }}"
270+ else if (shim .toolIs (tool_name , "lsp_hover" ))
271+ "{\" result\" :{\" status\" :\" stub\" }}"
272+ else if (shim .toolIs (tool_name , "lsp_complete" ))
273+ "{\" result\" :{\" status\" :\" stub\" }}"
274+ else if (shim .toolIs (tool_name , "lsp_goto_def" ))
275+ "{\" result\" :{\" status\" :\" stub\" }}"
276+ else if (shim .toolIs (tool_name , "lsp_references" ))
277+ "{\" result\" :{\" status\" :\" stub\" }}"
278+ else if (shim .toolIs (tool_name , "lsp_diagnostics" ))
279+ "{\" result\" :{\" status\" :\" stub\" }}"
280+ else if (shim .toolIs (tool_name , "lsp_format" ))
281+ "{\" result\" :{\" status\" :\" stub\" }}"
282+ else if (shim .toolIs (tool_name , "lsp_stop" ))
283+ "{\" result\" :{\" status\" :\" stub\" }}"
284+ else
285+ return shim .RC_UNKNOWN_TOOL ;
286+
287+ return shim .writeResult (out_buf , in_out_len , body );
288+ }
289+
243290// ═══════════════════════════════════════════════════════════════════════
244291// Tests
245292// ═══════════════════════════════════════════════════════════════════════
@@ -300,3 +347,46 @@ test "max LSP sessions enforced" {
300347 }
301348 try std .testing .expectEqual (@as (c_int , -1 ), lsp_init ());
302349}
350+
351+ // ═══════════════════════════════════════════════════════════════════════
352+ // ADR-0006 invoke dispatch tests
353+ // ═══════════════════════════════════════════════════════════════════════
354+
355+ test "invoke: each declared tool succeeds" {
356+ var buf : [256 ]u8 = undefined ;
357+ const tools = [_ ][]const u8 {
358+ "lsp_start" ,
359+ "lsp_initialize" ,
360+ "lsp_open" ,
361+ "lsp_change" ,
362+ "lsp_close" ,
363+ "lsp_hover" ,
364+ "lsp_complete" ,
365+ "lsp_goto_def" ,
366+ "lsp_references" ,
367+ "lsp_diagnostics" ,
368+ "lsp_format" ,
369+ "lsp_stop" ,
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 ("lsp_start" , "{}" , & buf , & len );
390+ try std .testing .expectEqual (@as (i32 , -3 ), rc );
391+ try std .testing .expect (len > 4 );
392+ }
0 commit comments