@@ -186,6 +186,43 @@ pub export fn boj_cartridge_version() [*:0]const u8 {
186186 return "0.2.0" ;
187187}
188188
189+ // ═══════════════════════════════════════════════════════════════════════
190+ // ADR-0006 dispatch (boj_cartridge_invoke, 5th standard symbol)
191+ // ═══════════════════════════════════════════════════════════════════════
192+
193+ const shim = @import ("cartridge_shim" );
194+
195+ /// Dispatch the cartridge.json MCP tools. Grade D Alpha — each arm
196+ /// returns a stub JSON body shaped to the tool's intended response.
197+ export fn boj_cartridge_invoke (
198+ tool_name : [* c ]const u8 ,
199+ json_args : [* c ]const u8 ,
200+ out_buf : [* c ]u8 ,
201+ in_out_len : [* c ]usize ,
202+ ) callconv (.c ) i32 {
203+ _ = json_args ;
204+ if (shim .invokeArgsNull (tool_name , out_buf , in_out_len )) return shim .RC_BAD_ARGS ;
205+
206+ const body : []const u8 = if (shim .toolIs (tool_name , "agent_new_session" ))
207+ "{\" result\" :{\" session_id\" :0,\" status\" :\" stub\" }}"
208+ else if (shim .toolIs (tool_name , "agent_end_session" ))
209+ "{\" result\" :{\" ended\" :true,\" status\" :\" stub\" }}"
210+ else if (shim .toolIs (tool_name , "agent_transition" ))
211+ "{\" result\" :{\" transitioned\" :true,\" status\" :\" stub\" }}"
212+ else if (shim .toolIs (tool_name , "agent_state" ))
213+ "{\" result\" :{\" state\" :\" unknown\" ,\" status\" :\" stub\" }}"
214+ else if (shim .toolIs (tool_name , "agent_loop_count" ))
215+ "{\" result\" :{\" count\" :0,\" status\" :\" stub\" }}"
216+ else if (shim .toolIs (tool_name , "agent_validate_ooda" ))
217+ "{\" result\" :{\" valid\" :true,\" status\" :\" stub\" }}"
218+ else if (shim .toolIs (tool_name , "agent_reset" ))
219+ "{\" result\" :{\" reset\" :true,\" status\" :\" stub\" }}"
220+ else
221+ return shim .RC_UNKNOWN_TOOL ;
222+
223+ return shim .writeResult (out_buf , in_out_len , body );
224+ }
225+
189226// ═══════════════════════════════════════════════════════════════════════
190227// Protocol Types (from proven-agentic, added in v0.2.0)
191228// ═══════════════════════════════════════════════════════════════════════
@@ -404,3 +441,37 @@ test "validation matches transitions" {
404441 try std .testing .expectEqual (@as (c_int , 0 ), agent_validate_ooda (1 , 4 )); // Obs -> Act
405442 try std .testing .expectEqual (@as (c_int , 0 ), agent_validate_ooda (3 , 1 )); // Dec -> Obs
406443}
444+
445+ // ═══════════════════════════════════════════════════════════════════════
446+ // ADR-0006 invoke dispatch tests
447+ // ═══════════════════════════════════════════════════════════════════════
448+
449+ test "invoke: each declared tool succeeds" {
450+ var buf : [256 ]u8 = undefined ;
451+ const tools = [_ ][]const u8 {
452+ "agent_new_session" , "agent_end_session" , "agent_transition" ,
453+ "agent_state" , "agent_loop_count" , "agent_validate_ooda" ,
454+ "agent_reset" ,
455+ };
456+ for (tools ) | t | {
457+ var len : usize = buf .len ;
458+ const rc = boj_cartridge_invoke (t .ptr , "{}" , & buf , & len );
459+ try std .testing .expectEqual (@as (i32 , 0 ), rc );
460+ try std .testing .expect (std .mem .indexOf (u8 , buf [0.. len ], "result" ) != null );
461+ }
462+ }
463+
464+ test "invoke: unknown tool returns -1" {
465+ var buf : [64 ]u8 = undefined ;
466+ var len : usize = buf .len ;
467+ const rc = boj_cartridge_invoke ("nope" , "{}" , & buf , & len );
468+ try std .testing .expectEqual (@as (i32 , -1 ), rc );
469+ }
470+
471+ test "invoke: buffer too small returns -3" {
472+ var buf : [4 ]u8 = undefined ;
473+ var len : usize = buf .len ;
474+ const rc = boj_cartridge_invoke ("agent_new_session" , "{}" , & buf , & len );
475+ try std .testing .expectEqual (@as (i32 , -3 ), rc );
476+ try std .testing .expect (len > 4 );
477+ }
0 commit comments