@pi-in-go/pigpen-a2a 0.1.0

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.
Files changed (52) hide show
  1. package/CREDITS.md +26 -0
  2. package/LICENSE +21 -0
  3. package/README.md +97 -0
  4. package/extensions/a2a/auth.go +120 -0
  5. package/extensions/a2a/auth_test.go +133 -0
  6. package/extensions/a2a/bench_test.go +70 -0
  7. package/extensions/a2a/binary_test.go +225 -0
  8. package/extensions/a2a/cancelqueued_test.go +142 -0
  9. package/extensions/a2a/card_cache_test.go +42 -0
  10. package/extensions/a2a/client.go +499 -0
  11. package/extensions/a2a/client_test.go +402 -0
  12. package/extensions/a2a/config.go +282 -0
  13. package/extensions/a2a/config_test.go +194 -0
  14. package/extensions/a2a/e2e_test.go +311 -0
  15. package/extensions/a2a/executor.go +318 -0
  16. package/extensions/a2a/extension.go +382 -0
  17. package/extensions/a2a/extension_test.go +396 -0
  18. package/extensions/a2a/fakehost_test.go +548 -0
  19. package/extensions/a2a/fakepig_test.go +212 -0
  20. package/extensions/a2a/gaps_test.go +59 -0
  21. package/extensions/a2a/go.mod +15 -0
  22. package/extensions/a2a/go.sum +14 -0
  23. package/extensions/a2a/interop_test.go +163 -0
  24. package/extensions/a2a/procattr_other.go +25 -0
  25. package/extensions/a2a/procattr_windows.go +26 -0
  26. package/extensions/a2a/resubscribe_test.go +113 -0
  27. package/extensions/a2a/review_test.go +293 -0
  28. package/extensions/a2a/server.go +267 -0
  29. package/extensions/a2a/server_test.go +792 -0
  30. package/extensions/a2a/survivors_test.go +302 -0
  31. package/extensions/a2a/worker.go +388 -0
  32. package/extensions/a2a/worker_test.go +257 -0
  33. package/package.json +41 -0
  34. package/port/PORT.md +126 -0
  35. package/port/a2a-go-LICENSE +201 -0
  36. package/port/golden/flag-without-auth-refused.jsonl +5 -0
  37. package/port/golden/listener-off.jsonl +4 -0
  38. package/port/golden/send-missing-message.jsonl +18 -0
  39. package/port/golden/send-without-remotes.jsonl +18 -0
  40. package/port/golden/task-unknown-action.jsonl +18 -0
  41. package/port/golden/tools-visible-to-model.jsonl +11 -0
  42. package/port/interop/kagent/main.go +73 -0
  43. package/port/mutation-run.txt +222 -0
  44. package/port/mutations.json +656 -0
  45. package/port/red.txt +105 -0
  46. package/port/scenarios/flag-without-auth-refused.json +8 -0
  47. package/port/scenarios/listener-off.json +7 -0
  48. package/port/scenarios/send-missing-message.json +11 -0
  49. package/port/scenarios/send-without-remotes.json +11 -0
  50. package/port/scenarios/task-unknown-action.json +11 -0
  51. package/port/scenarios/tools-visible-to-model.json +8 -0
  52. package/provenance.json +18 -0
@@ -0,0 +1,18 @@
1
+ {"kind":"header","scenario":"send-missing-message","lane":"pig-go-self","host":"pig 0.3.1+1.0.1","extension":"sha256:766f7013020ffc915c35c324d2997a21f7274842e4e3a5c598801682e171d7fd","normalizer":"v3"}
2
+ {"step":"01-prompt","ch":"response","data":{"command":"prompt","data":{"disposition":"started"},"success":true}}
3
+ {"step":"01-prompt","ch":"host","data":{"type":"agent_start"}}
4
+ {"step":"01-prompt","ch":"host","data":{"type":"turn_start"}}
5
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":"","role":"system"},"type":"message_end"}}
6
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":[{"text":"ask the peer","type":"text"}],"role":"user"},"type":"message_end"}}
7
+ {"step":"01-prompt","ch":"llm","data":{"messages":[{"role":"user","text":"ask the peer"}],"system":{"inserted":"Use a2a_agents to discover which remote agents exist before calling a2a_send.\n- The remote agent is another agent, not a tool: send it a self-contained request. Data you send leaves this machine.\n- ","removed":""},"tools":[{"description":"Read the contents of a file. Supports text files and images (jpg, png, gif, webp, bmp). Images are sent as attachments. For text files, output is truncated to 2000 lines or 50KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.","name":"read","parameters":{"properties":{"limit":{"description":"Maximum number of lines to read","type":"number"},"offset":{"description":"Line number to start reading from (1-indexed)","type":"number"},"path":{"description":"Path to the file to read (relative or absolute)","type":"string"}},"required":["path"],"type":"object"}},{"description":"Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last 2000 lines or 50KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.","name":"bash","parameters":{"properties":{"command":{"description":"Shell command to execute","type":"string"},"timeout":{"description":"Timeout in seconds (optional, no default timeout)","type":"number"}},"required":["command"],"type":"object"}},{"description":"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.","name":"edit","parameters":{"properties":{"edits":{"description":"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.","items":{"properties":{"newText":{"description":"Replacement text for this targeted edit.","type":"string"},"oldText":{"description":"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.","type":"string"}},"required":["oldText","newText"],"type":"object"},"type":"array"},"path":{"description":"Path to the file to edit (relative or absolute)","type":"string"}},"required":["path","edits"],"type":"object"}},{"description":"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.","name":"write","parameters":{"properties":{"content":{"description":"Content to write to the file","type":"string"},"path":{"description":"Path to the file to write (relative or absolute)","type":"string"}},"required":["path","content"],"type":"object"}},{"description":"List the remote A2A (Agent2Agent) agents configured for this PiG, with each agent's card: name, description and skills.","name":"a2a_agents","parameters":{"additionalProperties":false,"properties":{},"type":"object"}},{"description":"Send a task to a remote A2A agent and wait for its answer. Returns the task state, ids and the agent's reply. Reuse contextId to continue the same conversation.","name":"a2a_send","parameters":{"additionalProperties":false,"properties":{"agent":{"description":"Name of a configured remote (see a2a_agents).","type":"string"},"contextId":{"description":"Continue this conversation (from an earlier a2a_send).","type":"string"},"message":{"description":"The task or question, as plain text.","type":"string"},"taskId":{"description":"Continue this task, when it is waiting for input.","type":"string"}},"required":["agent","message"],"type":"object"}},{"description":"Get, list or cancel tasks on a remote A2A agent.","name":"a2a_task","parameters":{"additionalProperties":false,"properties":{"action":{"enum":["get","cancel","list"],"type":"string"},"agent":{"description":"Name of a configured remote.","type":"string"},"taskId":{"description":"Required for get and cancel.","type":"string"}},"required":["agent","action"],"type":"object"}}]}}
8
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":[{"arguments":{"agent":"peer"},"name":"a2a_send","type":"toolCall"}],"role":"assistant","stopReason":"toolUse"},"type":"message_end"}}
9
+ {"step":"01-prompt","ch":"host","data":{"args":{"agent":"peer"},"toolName":"a2a_send","type":"tool_execution_start"}}
10
+ {"step":"01-prompt","ch":"host","data":{"isError":true,"result":{"content":[{"text":"Validation failed for tool \"a2a_send\":\n - message: must have required properties message\n\nReceived arguments:\n{\n \"agent\": \"peer\"\n}","type":"text"}],"details":{}},"toolName":"a2a_send","type":"tool_execution_end"}}
11
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":[{"text":"Validation failed for tool \"a2a_send\":\n - message: must have required properties message\n\nReceived arguments:\n{\n \"agent\": \"peer\"\n}","type":"text"}],"details":{},"isError":true,"role":"toolResult","toolName":"a2a_send"},"type":"message_end"}}
12
+ {"step":"01-prompt","ch":"host","data":{"type":"turn_end"}}
13
+ {"step":"01-prompt","ch":"host","data":{"type":"turn_start"}}
14
+ {"step":"01-prompt","ch":"llm","data":{"messages":[{"role":"user","text":"ask the peer"},{"role":"assistant","text":"","toolCalls":[{"arguments":"{\"agent\":\"peer\"}","name":"a2a_send"}]},{"role":"tool","text":"Validation failed for tool \"a2a_send\":\n - message: must have required properties message\n\nReceived arguments:\n{\n \"agent\": \"peer\"\n}"}],"system":{"inserted":"Use a2a_agents to discover which remote agents exist before calling a2a_send.\n- The remote agent is another agent, not a tool: send it a self-contained request. Data you send leaves this machine.\n- ","removed":""},"tools":[{"description":"Read the contents of a file. Supports text files and images (jpg, png, gif, webp, bmp). Images are sent as attachments. For text files, output is truncated to 2000 lines or 50KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.","name":"read","parameters":{"properties":{"limit":{"description":"Maximum number of lines to read","type":"number"},"offset":{"description":"Line number to start reading from (1-indexed)","type":"number"},"path":{"description":"Path to the file to read (relative or absolute)","type":"string"}},"required":["path"],"type":"object"}},{"description":"Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last 2000 lines or 50KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.","name":"bash","parameters":{"properties":{"command":{"description":"Shell command to execute","type":"string"},"timeout":{"description":"Timeout in seconds (optional, no default timeout)","type":"number"}},"required":["command"],"type":"object"}},{"description":"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.","name":"edit","parameters":{"properties":{"edits":{"description":"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.","items":{"properties":{"newText":{"description":"Replacement text for this targeted edit.","type":"string"},"oldText":{"description":"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.","type":"string"}},"required":["oldText","newText"],"type":"object"},"type":"array"},"path":{"description":"Path to the file to edit (relative or absolute)","type":"string"}},"required":["path","edits"],"type":"object"}},{"description":"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.","name":"write","parameters":{"properties":{"content":{"description":"Content to write to the file","type":"string"},"path":{"description":"Path to the file to write (relative or absolute)","type":"string"}},"required":["path","content"],"type":"object"}},{"description":"List the remote A2A (Agent2Agent) agents configured for this PiG, with each agent's card: name, description and skills.","name":"a2a_agents","parameters":{"additionalProperties":false,"properties":{},"type":"object"}},{"description":"Send a task to a remote A2A agent and wait for its answer. Returns the task state, ids and the agent's reply. Reuse contextId to continue the same conversation.","name":"a2a_send","parameters":{"additionalProperties":false,"properties":{"agent":{"description":"Name of a configured remote (see a2a_agents).","type":"string"},"contextId":{"description":"Continue this conversation (from an earlier a2a_send).","type":"string"},"message":{"description":"The task or question, as plain text.","type":"string"},"taskId":{"description":"Continue this task, when it is waiting for input.","type":"string"}},"required":["agent","message"],"type":"object"}},{"description":"Get, list or cancel tasks on a remote A2A agent.","name":"a2a_task","parameters":{"additionalProperties":false,"properties":{"action":{"enum":["get","cancel","list"],"type":"string"},"agent":{"description":"Name of a configured remote.","type":"string"},"taskId":{"description":"Required for get and cancel.","type":"string"}},"required":["agent","action"],"type":"object"}}]}}
15
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":[{"text":"done","type":"text"}],"role":"assistant","stopReason":"stop"},"type":"message_end"}}
16
+ {"step":"01-prompt","ch":"host","data":{"type":"turn_end"}}
17
+ {"step":"01-prompt","ch":"host","data":{"type":"agent_end"}}
18
+ {"step":"99-shutdown","ch":"exit","data":{"code":0}}
@@ -0,0 +1,18 @@
1
+ {"kind":"header","scenario":"send-without-remotes","lane":"pig-go-self","host":"pig 0.3.1+1.0.1","extension":"sha256:766f7013020ffc915c35c324d2997a21f7274842e4e3a5c598801682e171d7fd","normalizer":"v3"}
2
+ {"step":"01-prompt","ch":"response","data":{"command":"prompt","data":{"disposition":"started"},"success":true}}
3
+ {"step":"01-prompt","ch":"host","data":{"type":"agent_start"}}
4
+ {"step":"01-prompt","ch":"host","data":{"type":"turn_start"}}
5
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":"","role":"system"},"type":"message_end"}}
6
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":[{"text":"ask the peer","type":"text"}],"role":"user"},"type":"message_end"}}
7
+ {"step":"01-prompt","ch":"llm","data":{"messages":[{"role":"user","text":"ask the peer"}],"system":{"inserted":"Use a2a_agents to discover which remote agents exist before calling a2a_send.\n- The remote agent is another agent, not a tool: send it a self-contained request. Data you send leaves this machine.\n- ","removed":""},"tools":[{"description":"Read the contents of a file. Supports text files and images (jpg, png, gif, webp, bmp). Images are sent as attachments. For text files, output is truncated to 2000 lines or 50KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.","name":"read","parameters":{"properties":{"limit":{"description":"Maximum number of lines to read","type":"number"},"offset":{"description":"Line number to start reading from (1-indexed)","type":"number"},"path":{"description":"Path to the file to read (relative or absolute)","type":"string"}},"required":["path"],"type":"object"}},{"description":"Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last 2000 lines or 50KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.","name":"bash","parameters":{"properties":{"command":{"description":"Shell command to execute","type":"string"},"timeout":{"description":"Timeout in seconds (optional, no default timeout)","type":"number"}},"required":["command"],"type":"object"}},{"description":"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.","name":"edit","parameters":{"properties":{"edits":{"description":"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.","items":{"properties":{"newText":{"description":"Replacement text for this targeted edit.","type":"string"},"oldText":{"description":"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.","type":"string"}},"required":["oldText","newText"],"type":"object"},"type":"array"},"path":{"description":"Path to the file to edit (relative or absolute)","type":"string"}},"required":["path","edits"],"type":"object"}},{"description":"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.","name":"write","parameters":{"properties":{"content":{"description":"Content to write to the file","type":"string"},"path":{"description":"Path to the file to write (relative or absolute)","type":"string"}},"required":["path","content"],"type":"object"}},{"description":"List the remote A2A (Agent2Agent) agents configured for this PiG, with each agent's card: name, description and skills.","name":"a2a_agents","parameters":{"additionalProperties":false,"properties":{},"type":"object"}},{"description":"Send a task to a remote A2A agent and wait for its answer. Returns the task state, ids and the agent's reply. Reuse contextId to continue the same conversation.","name":"a2a_send","parameters":{"additionalProperties":false,"properties":{"agent":{"description":"Name of a configured remote (see a2a_agents).","type":"string"},"contextId":{"description":"Continue this conversation (from an earlier a2a_send).","type":"string"},"message":{"description":"The task or question, as plain text.","type":"string"},"taskId":{"description":"Continue this task, when it is waiting for input.","type":"string"}},"required":["agent","message"],"type":"object"}},{"description":"Get, list or cancel tasks on a remote A2A agent.","name":"a2a_task","parameters":{"additionalProperties":false,"properties":{"action":{"enum":["get","cancel","list"],"type":"string"},"agent":{"description":"Name of a configured remote.","type":"string"},"taskId":{"description":"Required for get and cancel.","type":"string"}},"required":["agent","action"],"type":"object"}}]}}
8
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":[{"arguments":{"agent":"peer","message":"hello peer"},"name":"a2a_send","type":"toolCall"}],"role":"assistant","stopReason":"toolUse"},"type":"message_end"}}
9
+ {"step":"01-prompt","ch":"host","data":{"args":{"agent":"peer","message":"hello peer"},"toolName":"a2a_send","type":"tool_execution_start"}}
10
+ {"step":"01-prompt","ch":"host","data":{"isError":true,"result":{"content":[{"text":"a2a: no remotes are configured; add a \"remotes\" object to a2a.json","type":"text"}],"details":{}},"toolName":"a2a_send","type":"tool_execution_end"}}
11
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":[{"text":"a2a: no remotes are configured; add a \"remotes\" object to a2a.json","type":"text"}],"details":{},"isError":true,"role":"toolResult","toolName":"a2a_send"},"type":"message_end"}}
12
+ {"step":"01-prompt","ch":"host","data":{"type":"turn_end"}}
13
+ {"step":"01-prompt","ch":"host","data":{"type":"turn_start"}}
14
+ {"step":"01-prompt","ch":"llm","data":{"messages":[{"role":"user","text":"ask the peer"},{"role":"assistant","text":"","toolCalls":[{"arguments":"{\"agent\":\"peer\",\"message\":\"hello peer\"}","name":"a2a_send"}]},{"role":"tool","text":"a2a: no remotes are configured; add a \"remotes\" object to a2a.json"}],"system":{"inserted":"Use a2a_agents to discover which remote agents exist before calling a2a_send.\n- The remote agent is another agent, not a tool: send it a self-contained request. Data you send leaves this machine.\n- ","removed":""},"tools":[{"description":"Read the contents of a file. Supports text files and images (jpg, png, gif, webp, bmp). Images are sent as attachments. For text files, output is truncated to 2000 lines or 50KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.","name":"read","parameters":{"properties":{"limit":{"description":"Maximum number of lines to read","type":"number"},"offset":{"description":"Line number to start reading from (1-indexed)","type":"number"},"path":{"description":"Path to the file to read (relative or absolute)","type":"string"}},"required":["path"],"type":"object"}},{"description":"Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last 2000 lines or 50KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.","name":"bash","parameters":{"properties":{"command":{"description":"Shell command to execute","type":"string"},"timeout":{"description":"Timeout in seconds (optional, no default timeout)","type":"number"}},"required":["command"],"type":"object"}},{"description":"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.","name":"edit","parameters":{"properties":{"edits":{"description":"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.","items":{"properties":{"newText":{"description":"Replacement text for this targeted edit.","type":"string"},"oldText":{"description":"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.","type":"string"}},"required":["oldText","newText"],"type":"object"},"type":"array"},"path":{"description":"Path to the file to edit (relative or absolute)","type":"string"}},"required":["path","edits"],"type":"object"}},{"description":"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.","name":"write","parameters":{"properties":{"content":{"description":"Content to write to the file","type":"string"},"path":{"description":"Path to the file to write (relative or absolute)","type":"string"}},"required":["path","content"],"type":"object"}},{"description":"List the remote A2A (Agent2Agent) agents configured for this PiG, with each agent's card: name, description and skills.","name":"a2a_agents","parameters":{"additionalProperties":false,"properties":{},"type":"object"}},{"description":"Send a task to a remote A2A agent and wait for its answer. Returns the task state, ids and the agent's reply. Reuse contextId to continue the same conversation.","name":"a2a_send","parameters":{"additionalProperties":false,"properties":{"agent":{"description":"Name of a configured remote (see a2a_agents).","type":"string"},"contextId":{"description":"Continue this conversation (from an earlier a2a_send).","type":"string"},"message":{"description":"The task or question, as plain text.","type":"string"},"taskId":{"description":"Continue this task, when it is waiting for input.","type":"string"}},"required":["agent","message"],"type":"object"}},{"description":"Get, list or cancel tasks on a remote A2A agent.","name":"a2a_task","parameters":{"additionalProperties":false,"properties":{"action":{"enum":["get","cancel","list"],"type":"string"},"agent":{"description":"Name of a configured remote.","type":"string"},"taskId":{"description":"Required for get and cancel.","type":"string"}},"required":["agent","action"],"type":"object"}}]}}
15
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":[{"text":"done","type":"text"}],"role":"assistant","stopReason":"stop"},"type":"message_end"}}
16
+ {"step":"01-prompt","ch":"host","data":{"type":"turn_end"}}
17
+ {"step":"01-prompt","ch":"host","data":{"type":"agent_end"}}
18
+ {"step":"99-shutdown","ch":"exit","data":{"code":0}}
@@ -0,0 +1,18 @@
1
+ {"kind":"header","scenario":"task-unknown-action","lane":"pig-go-self","host":"pig 0.3.1+1.0.1","extension":"sha256:766f7013020ffc915c35c324d2997a21f7274842e4e3a5c598801682e171d7fd","normalizer":"v3"}
2
+ {"step":"01-prompt","ch":"response","data":{"command":"prompt","data":{"disposition":"started"},"success":true}}
3
+ {"step":"01-prompt","ch":"host","data":{"type":"agent_start"}}
4
+ {"step":"01-prompt","ch":"host","data":{"type":"turn_start"}}
5
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":"","role":"system"},"type":"message_end"}}
6
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":[{"text":"poke the peer","type":"text"}],"role":"user"},"type":"message_end"}}
7
+ {"step":"01-prompt","ch":"llm","data":{"messages":[{"role":"user","text":"poke the peer"}],"system":{"inserted":"Use a2a_agents to discover which remote agents exist before calling a2a_send.\n- The remote agent is another agent, not a tool: send it a self-contained request. Data you send leaves this machine.\n- ","removed":""},"tools":[{"description":"Read the contents of a file. Supports text files and images (jpg, png, gif, webp, bmp). Images are sent as attachments. For text files, output is truncated to 2000 lines or 50KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.","name":"read","parameters":{"properties":{"limit":{"description":"Maximum number of lines to read","type":"number"},"offset":{"description":"Line number to start reading from (1-indexed)","type":"number"},"path":{"description":"Path to the file to read (relative or absolute)","type":"string"}},"required":["path"],"type":"object"}},{"description":"Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last 2000 lines or 50KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.","name":"bash","parameters":{"properties":{"command":{"description":"Shell command to execute","type":"string"},"timeout":{"description":"Timeout in seconds (optional, no default timeout)","type":"number"}},"required":["command"],"type":"object"}},{"description":"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.","name":"edit","parameters":{"properties":{"edits":{"description":"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.","items":{"properties":{"newText":{"description":"Replacement text for this targeted edit.","type":"string"},"oldText":{"description":"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.","type":"string"}},"required":["oldText","newText"],"type":"object"},"type":"array"},"path":{"description":"Path to the file to edit (relative or absolute)","type":"string"}},"required":["path","edits"],"type":"object"}},{"description":"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.","name":"write","parameters":{"properties":{"content":{"description":"Content to write to the file","type":"string"},"path":{"description":"Path to the file to write (relative or absolute)","type":"string"}},"required":["path","content"],"type":"object"}},{"description":"List the remote A2A (Agent2Agent) agents configured for this PiG, with each agent's card: name, description and skills.","name":"a2a_agents","parameters":{"additionalProperties":false,"properties":{},"type":"object"}},{"description":"Send a task to a remote A2A agent and wait for its answer. Returns the task state, ids and the agent's reply. Reuse contextId to continue the same conversation.","name":"a2a_send","parameters":{"additionalProperties":false,"properties":{"agent":{"description":"Name of a configured remote (see a2a_agents).","type":"string"},"contextId":{"description":"Continue this conversation (from an earlier a2a_send).","type":"string"},"message":{"description":"The task or question, as plain text.","type":"string"},"taskId":{"description":"Continue this task, when it is waiting for input.","type":"string"}},"required":["agent","message"],"type":"object"}},{"description":"Get, list or cancel tasks on a remote A2A agent.","name":"a2a_task","parameters":{"additionalProperties":false,"properties":{"action":{"enum":["get","cancel","list"],"type":"string"},"agent":{"description":"Name of a configured remote.","type":"string"},"taskId":{"description":"Required for get and cancel.","type":"string"}},"required":["agent","action"],"type":"object"}}]}}
8
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":[{"arguments":{"action":"explode","agent":"peer","taskId":"t"},"name":"a2a_task","type":"toolCall"}],"role":"assistant","stopReason":"toolUse"},"type":"message_end"}}
9
+ {"step":"01-prompt","ch":"host","data":{"args":{"action":"explode","agent":"peer","taskId":"t"},"toolName":"a2a_task","type":"tool_execution_start"}}
10
+ {"step":"01-prompt","ch":"host","data":{"isError":true,"result":{"content":[{"text":"Validation failed for tool \"a2a_task\":\n - action: must be equal to one of the allowed values\n\nReceived arguments:\n{\n \"action\": \"explode\",\n \"agent\": \"peer\",\n \"taskId\": \"t\"\n}","type":"text"}],"details":{}},"toolName":"a2a_task","type":"tool_execution_end"}}
11
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":[{"text":"Validation failed for tool \"a2a_task\":\n - action: must be equal to one of the allowed values\n\nReceived arguments:\n{\n \"action\": \"explode\",\n \"agent\": \"peer\",\n \"taskId\": \"t\"\n}","type":"text"}],"details":{},"isError":true,"role":"toolResult","toolName":"a2a_task"},"type":"message_end"}}
12
+ {"step":"01-prompt","ch":"host","data":{"type":"turn_end"}}
13
+ {"step":"01-prompt","ch":"host","data":{"type":"turn_start"}}
14
+ {"step":"01-prompt","ch":"llm","data":{"messages":[{"role":"user","text":"poke the peer"},{"role":"assistant","text":"","toolCalls":[{"arguments":"{\"action\":\"explode\",\"agent\":\"peer\",\"taskId\":\"t\"}","name":"a2a_task"}]},{"role":"tool","text":"Validation failed for tool \"a2a_task\":\n - action: must be equal to one of the allowed values\n\nReceived arguments:\n{\n \"action\": \"explode\",\n \"agent\": \"peer\",\n \"taskId\": \"t\"\n}"}],"system":{"inserted":"Use a2a_agents to discover which remote agents exist before calling a2a_send.\n- The remote agent is another agent, not a tool: send it a self-contained request. Data you send leaves this machine.\n- ","removed":""},"tools":[{"description":"Read the contents of a file. Supports text files and images (jpg, png, gif, webp, bmp). Images are sent as attachments. For text files, output is truncated to 2000 lines or 50KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.","name":"read","parameters":{"properties":{"limit":{"description":"Maximum number of lines to read","type":"number"},"offset":{"description":"Line number to start reading from (1-indexed)","type":"number"},"path":{"description":"Path to the file to read (relative or absolute)","type":"string"}},"required":["path"],"type":"object"}},{"description":"Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last 2000 lines or 50KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.","name":"bash","parameters":{"properties":{"command":{"description":"Shell command to execute","type":"string"},"timeout":{"description":"Timeout in seconds (optional, no default timeout)","type":"number"}},"required":["command"],"type":"object"}},{"description":"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.","name":"edit","parameters":{"properties":{"edits":{"description":"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.","items":{"properties":{"newText":{"description":"Replacement text for this targeted edit.","type":"string"},"oldText":{"description":"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.","type":"string"}},"required":["oldText","newText"],"type":"object"},"type":"array"},"path":{"description":"Path to the file to edit (relative or absolute)","type":"string"}},"required":["path","edits"],"type":"object"}},{"description":"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.","name":"write","parameters":{"properties":{"content":{"description":"Content to write to the file","type":"string"},"path":{"description":"Path to the file to write (relative or absolute)","type":"string"}},"required":["path","content"],"type":"object"}},{"description":"List the remote A2A (Agent2Agent) agents configured for this PiG, with each agent's card: name, description and skills.","name":"a2a_agents","parameters":{"additionalProperties":false,"properties":{},"type":"object"}},{"description":"Send a task to a remote A2A agent and wait for its answer. Returns the task state, ids and the agent's reply. Reuse contextId to continue the same conversation.","name":"a2a_send","parameters":{"additionalProperties":false,"properties":{"agent":{"description":"Name of a configured remote (see a2a_agents).","type":"string"},"contextId":{"description":"Continue this conversation (from an earlier a2a_send).","type":"string"},"message":{"description":"The task or question, as plain text.","type":"string"},"taskId":{"description":"Continue this task, when it is waiting for input.","type":"string"}},"required":["agent","message"],"type":"object"}},{"description":"Get, list or cancel tasks on a remote A2A agent.","name":"a2a_task","parameters":{"additionalProperties":false,"properties":{"action":{"enum":["get","cancel","list"],"type":"string"},"agent":{"description":"Name of a configured remote.","type":"string"},"taskId":{"description":"Required for get and cancel.","type":"string"}},"required":["agent","action"],"type":"object"}}]}}
15
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":[{"text":"done","type":"text"}],"role":"assistant","stopReason":"stop"},"type":"message_end"}}
16
+ {"step":"01-prompt","ch":"host","data":{"type":"turn_end"}}
17
+ {"step":"01-prompt","ch":"host","data":{"type":"agent_end"}}
18
+ {"step":"99-shutdown","ch":"exit","data":{"code":0}}
@@ -0,0 +1,11 @@
1
+ {"kind":"header","scenario":"tools-visible-to-model","lane":"pig-go-self","host":"pig 0.3.1+1.0.1","extension":"sha256:766f7013020ffc915c35c324d2997a21f7274842e4e3a5c598801682e171d7fd","normalizer":"v3"}
2
+ {"step":"01-prompt","ch":"response","data":{"command":"prompt","data":{"disposition":"started"},"success":true}}
3
+ {"step":"01-prompt","ch":"host","data":{"type":"agent_start"}}
4
+ {"step":"01-prompt","ch":"host","data":{"type":"turn_start"}}
5
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":"","role":"system"},"type":"message_end"}}
6
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":[{"text":"hello","type":"text"}],"role":"user"},"type":"message_end"}}
7
+ {"step":"01-prompt","ch":"llm","data":{"messages":[{"role":"user","text":"hello"}],"system":{"inserted":"Use a2a_agents to discover which remote agents exist before calling a2a_send.\n- The remote agent is another agent, not a tool: send it a self-contained request. Data you send leaves this machine.\n- ","removed":""},"tools":[{"description":"Read the contents of a file. Supports text files and images (jpg, png, gif, webp, bmp). Images are sent as attachments. For text files, output is truncated to 2000 lines or 50KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.","name":"read","parameters":{"properties":{"limit":{"description":"Maximum number of lines to read","type":"number"},"offset":{"description":"Line number to start reading from (1-indexed)","type":"number"},"path":{"description":"Path to the file to read (relative or absolute)","type":"string"}},"required":["path"],"type":"object"}},{"description":"Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last 2000 lines or 50KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.","name":"bash","parameters":{"properties":{"command":{"description":"Shell command to execute","type":"string"},"timeout":{"description":"Timeout in seconds (optional, no default timeout)","type":"number"}},"required":["command"],"type":"object"}},{"description":"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.","name":"edit","parameters":{"properties":{"edits":{"description":"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.","items":{"properties":{"newText":{"description":"Replacement text for this targeted edit.","type":"string"},"oldText":{"description":"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.","type":"string"}},"required":["oldText","newText"],"type":"object"},"type":"array"},"path":{"description":"Path to the file to edit (relative or absolute)","type":"string"}},"required":["path","edits"],"type":"object"}},{"description":"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.","name":"write","parameters":{"properties":{"content":{"description":"Content to write to the file","type":"string"},"path":{"description":"Path to the file to write (relative or absolute)","type":"string"}},"required":["path","content"],"type":"object"}},{"description":"List the remote A2A (Agent2Agent) agents configured for this PiG, with each agent's card: name, description and skills.","name":"a2a_agents","parameters":{"additionalProperties":false,"properties":{},"type":"object"}},{"description":"Send a task to a remote A2A agent and wait for its answer. Returns the task state, ids and the agent's reply. Reuse contextId to continue the same conversation.","name":"a2a_send","parameters":{"additionalProperties":false,"properties":{"agent":{"description":"Name of a configured remote (see a2a_agents).","type":"string"},"contextId":{"description":"Continue this conversation (from an earlier a2a_send).","type":"string"},"message":{"description":"The task or question, as plain text.","type":"string"},"taskId":{"description":"Continue this task, when it is waiting for input.","type":"string"}},"required":["agent","message"],"type":"object"}},{"description":"Get, list or cancel tasks on a remote A2A agent.","name":"a2a_task","parameters":{"additionalProperties":false,"properties":{"action":{"enum":["get","cancel","list"],"type":"string"},"agent":{"description":"Name of a configured remote.","type":"string"},"taskId":{"description":"Required for get and cancel.","type":"string"}},"required":["agent","action"],"type":"object"}}]}}
8
+ {"step":"01-prompt","ch":"host","data":{"message":{"content":[{"text":"ok","type":"text"}],"role":"assistant","stopReason":"stop"},"type":"message_end"}}
9
+ {"step":"01-prompt","ch":"host","data":{"type":"turn_end"}}
10
+ {"step":"01-prompt","ch":"host","data":{"type":"agent_end"}}
11
+ {"step":"99-shutdown","ch":"exit","data":{"code":0}}
@@ -0,0 +1,73 @@
1
+ // Command kagent-a2a-echo serves an A2A agent with kagent's own A2A server package
2
+ // (github.com/kagent-dev/kagent/go/adk/pkg/a2a/server, Apache-2.0), the code kagent agents use to
3
+ // speak A2A. scripts/interop-kagent.mjs copies that package from a kagent checkout and changes one
4
+ // thing: its hard-coded readiness listener (":8081") binds an ephemeral port, so it can run next to
5
+ // another service. Every A2A handler is unmodified. The executor echoes the message; the message "sleep" waits for cancellation.
6
+ // It exists for the pigpen a2a interop test.
7
+ package main
8
+
9
+ import (
10
+ "context"
11
+ "flag"
12
+ "iter"
13
+ "log/slog"
14
+ "os"
15
+ "strings"
16
+
17
+ a2atype "github.com/a2aproject/a2a-go/v2/a2a"
18
+ "github.com/a2aproject/a2a-go/v2/a2asrv"
19
+ a2aserver "kagentinterop/server"
20
+ )
21
+
22
+ type echo struct{}
23
+
24
+ func (echo) Execute(ctx context.Context, ec *a2asrv.ExecutorContext) iter.Seq2[a2atype.Event, error] {
25
+ return func(yield func(a2atype.Event, error) bool) {
26
+ var text strings.Builder
27
+ for _, p := range ec.Message.Parts {
28
+ text.WriteString(p.Text())
29
+ }
30
+ if ec.StoredTask == nil && !yield(a2atype.NewSubmittedTask(ec, ec.Message), nil) {
31
+ return
32
+ }
33
+ if !yield(a2atype.NewStatusUpdateEvent(ec, a2atype.TaskStateWorking, nil), nil) {
34
+ return
35
+ }
36
+ if text.String() == "sleep" {
37
+ <-ctx.Done()
38
+ return
39
+ }
40
+ if !yield(a2atype.NewArtifactEvent(ec, a2atype.NewTextPart("kagent echo: "+text.String())), nil) {
41
+ return
42
+ }
43
+ yield(a2atype.NewStatusUpdateEvent(ec, a2atype.TaskStateCompleted, nil), nil)
44
+ }
45
+ }
46
+
47
+ func (echo) Cancel(ctx context.Context, ec *a2asrv.ExecutorContext) iter.Seq2[a2atype.Event, error] {
48
+ return func(yield func(a2atype.Event, error) bool) {
49
+ yield(a2atype.NewStatusUpdateEvent(ec, a2atype.TaskStateCanceled, nil), nil)
50
+ }
51
+ }
52
+
53
+ func main() {
54
+ port := flag.String("port", "8083", "port")
55
+ flag.Parse()
56
+ logger := slog.New(slog.NewTextHandler(os.Stderr, nil))
57
+ card := a2atype.AgentCard{
58
+ Name: "kagent-echo", Description: "kagent A2A server package with an echo executor", Version: "1",
59
+ SupportedInterfaces: []*a2atype.AgentInterface{a2atype.NewAgentInterface("http://kagent-controller.kagent.svc.cluster.local:8083/api/a2a/kagent/echo", a2atype.TransportProtocolJSONRPC)},
60
+ Capabilities: a2atype.AgentCapabilities{Streaming: true},
61
+ DefaultInputModes: []string{"text"}, DefaultOutputModes: []string{"text"},
62
+ Skills: []a2atype.AgentSkill{{ID: "echo", Name: "Echo", Description: "echoes", Tags: []string{"echo"}}},
63
+ }
64
+ srv, err := a2aserver.NewA2AServer(card, echo{}, logger, a2aserver.ServerConfig{Host: "127.0.0.1", Port: *port})
65
+ if err != nil {
66
+ logger.Error("new server", "error", err)
67
+ os.Exit(1)
68
+ }
69
+ if err := srv.Run(); err != nil {
70
+ logger.Error("run", "error", err)
71
+ os.Exit(1)
72
+ }
73
+ }
@@ -0,0 +1,222 @@
1
+ # review re-run (rev-pigpen-a2a): every mutant in mutations.json applied to a copy of extensions/a2a, go test -count=1 (unit and fake-host;
2
+ # e2e, Binary and kagent tests skipped), 8 jobs, 109 mutants, 2026-09-30, pig 0.3.0+0.87.1. Runner: exact find/replace, one occurrence each.
3
+ # result: 109 killed, 0 survived
4
+ KILLED listener-starts-without-config
5
+ first failing test: TestWorkerChildNeverListens
6
+ KILLED worker-child-may-listen
7
+ first failing test: TestWorkerProcessDoesNotOpenAListener
8
+ KILLED flag-not-highest-precedence
9
+ first failing test: TestPrecedenceFlagOverEnvOverFile
10
+ KILLED env-not-over-file
11
+ first failing test: TestPrecedenceFlagOverEnvOverFile
12
+ KILLED unknown-keys-and-inline-secrets-accepted
13
+ first failing test: TestInlineSecretsAreRejected
14
+ KILLED listener-without-tokens-allowed
15
+ first failing test: TestListenerNeedsAuthentication
16
+ KILLED insecure-no-auth-off-loopback
17
+ first failing test: TestInsecureNoAuthOnlyOnLoopback
18
+ KILLED insecure-and-tokens-both
19
+ first failing test: TestInsecureNoAuthWithTokensIsAmbiguous
20
+ KILLED short-tokens-allowed
21
+ first failing test: TestTokenConfigValidation
22
+ KILLED duplicate-token-values-allowed
23
+ first failing test: TestTwoVariablesWithOneValueAreRejected
24
+ KILLED duplicate-token-names-allowed
25
+ first failing test: TestTokenConfigValidation
26
+ KILLED tenant-not-validated
27
+ first failing test: TestTokenConfigValidation
28
+ KILLED missing-token-env-allowed
29
+ first failing test: TestTokenEnvNotSetIsSaidPlainly
30
+ KILLED listen-not-host-port
31
+ first failing test: TestMalformedListenAddressSaysHostPort
32
+ KILLED worker-gets-pig-default-tools
33
+ first failing test: TestReview_WorkerHasNoToolsUnlessConfigured
34
+ KILLED remote-url-scheme-unchecked
35
+ first failing test: TestRemoteDefaultsAndValidation
36
+ KILLED remote-name-unchecked
37
+ first failing test: TestRemoteDefaultsAndValidation
38
+ KILLED basic-scheme-accepted
39
+ first failing test: TestAuthenticateRejects
40
+ KILLED extra-fields-accepted
41
+ first failing test: TestAuthenticateRejects
42
+ KILLED token-comparison-inverted
43
+ first failing test: TestAuthenticateBearer
44
+ KILLED insecure-flag-ignored
45
+ first failing test: TestInsecureNoAuthGivesOneAnonymousPrincipal
46
+ KILLED tenant-key-uses-token-name
47
+ first failing test: TestPrincipalKeysIsolate
48
+ KILLED key-namespaces-collide
49
+ first failing test: TestPrincipalKeysIsolate
50
+ KILLED everything-public
51
+ first failing test: TestWrapRejectsWith401AndChallenge
52
+ KILLED no-bearer-challenge
53
+ first failing test: TestWrapRejectsWith401AndChallenge
54
+ KILLED empty-authenticator-allowed
55
+ first failing test: TestNoTokensNoInsecureFlagIsAnError
56
+ KILLED file-parts-dropped
57
+ first failing test: TestTextPlusFilePartIsRefusedNotTrimmed
58
+ KILLED empty-prompt-accepted
59
+ first failing test: TestEmptyMessageIsRejected
60
+ KILLED prompt-size-unbounded
61
+ first failing test: TestOversizedPromptIsRefusedBelowTheBodyLimit
62
+ KILLED timeout-never-fires
63
+ first failing test: TestTaskTimeoutFailsTheTask
64
+ KILLED worker-error-detail-leaks
65
+ first failing test: TestWorkerErrorDetailIsNotSentToThePeer
66
+ KILLED context-not-serialised
67
+ first failing test: TestCancelBeforeTheWorkerStartsBehindTheSameContext
68
+ KILLED concurrency-limit-ignored
69
+ first failing test: TestCancelBeforeTheWorkerStartsBehindTheConcurrencyLimit
70
+ KILLED cancel-does-not-stop-worker
71
+ first failing test: TestCancelBeforeTheWorkerStartsBehindTheConcurrencyLimit
72
+ KILLED failure-reason-dropped
73
+ first failing test: TestWorkerFailureBecomesAFailedTask
74
+ KILLED principal-not-checked
75
+ first failing test: TestExecutorRefusesAForgedUser
76
+ KILLED version-not-enforced
77
+ first failing test: TestProtocolVersionIsPinned
78
+ KILLED absent-version-accepted
79
+ first failing test: TestProtocolVersionIsPinned
80
+ KILLED minor-versions-accepted
81
+ first failing test: TestCardWithoutAProtocol10InterfaceIsRefused
82
+ KILLED mixed-version-values-accepted
83
+ first failing test: TestMixedVersionHeaderIsRefused
84
+ KILLED tenant-not-enforced
85
+ first failing test: TestRequestTenantMustMatchTheTokensTenant
86
+ KILLED user-not-attached
87
+ first failing test: TestCancelBeforeTheWorkerStartsBehindTheConcurrencyLimit
88
+ KILLED body-size-unbounded
89
+ first failing test: TestBodyLimitAppliesEvenWithASmallPrompt
90
+ KILLED card-requires-auth
91
+ first failing test: TestAgentCardIsPublicAndPinnedToProtocol10
92
+ KILLED card-drops-streaming
93
+ first failing test: TestAgentCardIsPublicAndPinnedToProtocol10
94
+ KILLED card-claims-push
95
+ first failing test: TestAgentCardIsPublicAndPinnedToProtocol10
96
+ KILLED card-ignores-external-url
97
+ first failing test: TestAgentCardAdvertisesExternalURL
98
+ KILLED card-without-security-requirement
99
+ first failing test: TestAgentCardIsPublicAndPinnedToProtocol10
100
+ KILLED plain-http-on-tls
101
+ first failing test: TestTLSListener
102
+ KILLED second-start-allowed
103
+ first failing test: TestSecondStartIsAnError
104
+ KILLED worker-keeps-extensions
105
+ first failing test: TestWorkerPassesFlagsSessionAndCwd
106
+ KILLED worker-not-marked
107
+ first failing test: TestWorkerEnvironmentIsAllowlisted
108
+ KILLED worker-inherits-secrets
109
+ first failing test: TestWorkerEnvironmentIsAllowlisted
110
+ KILLED passenv-ignored
111
+ first failing test: TestReview_WorkerKillsWhatATurnLeftBehind
112
+ KILLED session-id-ignores-principal
113
+ first failing test: TestSessionIDIsStableScopedAndSafe
114
+ KILLED session-id-ignores-context
115
+ first failing test: TestSessionIDIsStableScopedAndSafe
116
+ KILLED session-dir-shared
117
+ first failing test: TestWorkerPassesFlagsSessionAndCwd
118
+ KILLED worker-cwd-not-set
119
+ first failing test: TestWorkerPassesFlagsSessionAndCwd
120
+ KILLED tools-allowlist-dropped
121
+ first failing test: TestReview_WorkerHasNoToolsUnlessConfigured
122
+ KILLED session-not-kept
123
+ first failing test: TestWorkerPassesFlagsSessionAndCwd
124
+ KILLED abort-not-sent
125
+ first failing test: TestWorkerCancelAbortsThenReaps
126
+ KILLED no-kill-after-grace
127
+ first failing test: TestWorkerEscalatesToKillWhenTermIsIgnored
128
+ KILLED no-terminate
129
+ first failing test: TestWorkerAsksForTermBeforeKill
130
+ KILLED model-error-text-copied
131
+ first failing test: TestModelFailureMessageIsExactlyGeneric
132
+ KILLED model-error-not-a-failure
133
+ first failing test: TestModelFailureMessageIsExactlyGeneric
134
+ KILLED streamed-and-final-text-duplicated
135
+ first failing test: TestWorkerPassesFlagsSessionAndCwd
136
+ KILLED empty-prompt-sent
137
+ first failing test: TestWorkerRefusesEmptyPrompt
138
+ KILLED tool-updates-dropped
139
+ first failing test: TestWorkerStreamsUpdatesAndFinalText
140
+ KILLED ui-request-hangs
141
+ first failing test: TestWorkerFailsATurnThatNeedsInteractiveInput
142
+ KILLED rejected-prompt-ignored
143
+ first failing test: TestWorkerReportsARejectedPromptWithoutTheReason
144
+ KILLED any-protocol-version-accepted
145
+ first failing test: TestCardWithoutAProtocol10InterfaceIsRefused
146
+ KILLED credentials-follow-the-card
147
+ first failing test: TestCredentialsAreNotSentToAHostTheCardNamed
148
+ KILLED transport-host-not-checked
149
+ first failing test: TestCredentialTransportRefusesAnotherHost
150
+ KILLED redirects-followed-with-credentials
151
+ first failing test: TestRemoteRedirectsAreNotFollowed
152
+ KILLED bearer-not-sent
153
+ first failing test: TestBearerAndCustomHeadersComeFromEnvironment
154
+ KILLED missing-bearer-env-tolerated
155
+ first failing test: TestMissingTokenEnvironmentIsAnErrorBeforeAnyRequest
156
+ KILLED custom-headers-dropped
157
+ first failing test: TestBearerAndCustomHeadersComeFromEnvironment
158
+ KILLED remote-not-cancelled-on-abort
159
+ first failing test: TestCancellingTheCallCancelsTheRemoteTask
160
+ KILLED timeout-ignored
161
+ first failing test: undefined
162
+ KILLED unknown-agent-unnamed
163
+ first failing test: TestUnknownAgentNamesTheKnownOnes
164
+ KILLED names-unsorted
165
+ first failing test: TestRemotesNamesAreSorted
166
+ KILLED empty-message-sent
167
+ first failing test: TestSendRefusesAnEmptyMessageBeforeAnyRequest
168
+ KILLED input-required-called-terminal
169
+ first failing test: TestSummaryOfAnInputRequiredTaskIsNotTerminal
170
+ KILLED failure-text-hidden
171
+ first failing test: TestFailedAndInputRequiredStates
172
+ KILLED auth-error-shows-token-context
173
+ first failing test: TestAuthFailureIsExplainedWithoutTheToken
174
+ KILLED switch-drops-listener
175
+ first failing test: TestSessionSwitchKeepsTheListenerReloadRestartsIt
176
+ KILLED shutdown-keeps-listener
177
+ first failing test: TestConfiguredListenerServesAndShutdownStopsIt
178
+ KILLED config-error-silent
179
+ first failing test: TestInvalidConfigurationIsReportedNotFatal
180
+ KILLED start-failure-silent
181
+ first failing test: TestListenFailureIsReportedToTheUser
182
+ KILLED flag-not-read
183
+ first failing test: TestFlagOverridesTheConfigurationFile
184
+ KILLED agent-dir-ignored
185
+ first failing test: TestConfigIsReadFromTheAgentDirectory
186
+ KILLED stop-does-not-reload-config
187
+ first failing test: TestToolAfterShutdownUsesTheRewrittenConfiguration
188
+ KILLED status-hides-remotes
189
+ first failing test: TestReloadAppliesChangedConfiguration
190
+ KILLED tool-required-not-enforced
191
+ first failing test: TestToolsRejectBadArguments
192
+ KILLED tool-empty-message-allowed
193
+ first failing test: TestToolsRejectBadArguments
194
+ KILLED tool-errors-not-errors
195
+ first failing test: TestToolsWithoutRemotesSayWhy
196
+ KILLED unfinished-task-not-flagged
197
+ first failing test: TestSummaryOfAnInputRequiredTaskIsNotTerminal
198
+ KILLED task-action-unchecked
199
+ first failing test: TestToolsRejectBadArguments
200
+ KILLED send-drops-context
201
+ first failing test: TestSendToolPassesTheContextIDThrough
202
+ KILLED tls-load-failure-ignored
203
+ first failing test: TestUnreadableTLSKeyPairFailsStart
204
+ KILLED subscribe-ownership-unchecked
205
+ first failing test: TestSubscribeToALiveTaskDeliversTheRest
206
+ KILLED queued-cancel-ignored-at-slot
207
+ first failing test: TestCancelBeforeTheWorkerStartsBehindTheConcurrencyLimit
208
+ KILLED queued-cancel-ignored-at-context-lock
209
+ first failing test: TestCancelBeforeTheWorkerStartsBehindTheSameContext
210
+ KILLED shutdown-does-not-close-the-port
211
+ first failing test: TestShutdownClosesThePortEvenRightAfterStart
212
+ KILLED insecure-host-unchecked
213
+ first failing test: TestReview_InsecureLoopbackListenerRefusesAForeignHostHeader
214
+ KILLED transport-scheme-not-checked
215
+ first failing test: TestReview_CredentialsAreNotDowngradedToPlainHTTP
216
+ KILLED card-scheme-downgrade-accepted
217
+ first failing test: TestReview_CredentialsAreNotDowngradedToPlainHTTP
218
+ KILLED context-lock-shared-across-tenants
219
+ first failing test: TestReview_SameContextIDInTwoTenantsRunsConcurrently
220
+ KILLED left-behind-child-survives
221
+ first failing test: TestReview_WorkerKillsWhatATurnLeftBehind
222
+ 109 mutation(s), 0 not killed