../ runs index

Campaign a2a-ironclaw-v0.6.2-rc.0-v3r1 FAIL

Agent group
ironclaw (homogeneous)
ai-memory ref
v0.6.2-rc.0
Completed at
2026-04-22T01:40:00Z
Overall pass
false
Skipped reports
16

Infrastructure

Provider
digitalocean
Region
nyc3
Droplet size
s-2vcpu-4gb
Topology
4-node federation mesh (W=2/N=4)
Scenarios started
2026-04-22T01:25:08Z
Scenarios ended
2026-04-22T01:40:00Z
Dispatched by
alphaonedev
Harness SHA
d5942cb467fc
Workflow run
https://github.com/alphaonedev/ai-memory-ai2ai-gate/actions/runs/24755138265

Node roster

#RoleAgent IDPublic IPPrivate IP
1agentai:alice104.236.6.12510.251.0.2
2agentai:bob167.71.177.13710.251.0.4
3agentai:charlie167.99.59.6810.251.0.3
4memory-only167.71.84.15810.251.0.5

Baseline attestation BASELINE OK

Per the authoritative baseline spec, every agent node must emit a self-attestation before any scenario is permitted to run. This run's attestation:

Spec version: 1.4.0 — see authoritative baseline.

NodeAgentFrameworkAuthenticMCP ai-memoryxAI cfgxAI defaultAgent IDFederationUFW offiptablesdead-manF1 xAIF2a substrateF2b agent (non-gating)Config SHAPass
node-1ai:aliceironclaw ironclaw 0.26.01222bad836c8PASS
node-2ai:bobironclaw ironclaw 0.26.01c6416fe43f2PASS
node-3ai:charlieironclaw ironclaw 0.26.0b223a1593143PASS
a2a-baseline.json
{
	"baseline_pass": true,
	"per_node": [
		{
			"spec_version": "1.4.0",
			"agent_type": "ironclaw",
			"agent_id": "ai:alice",
			"node_index": "1",
			"framework_version": "ironclaw 0.26.0",
			"ai_memory_version": "0.6.2-rc.0",
			"peer_urls": "http://10.251.0.4:9077,http://10.251.0.3:9077,http://10.251.0.5:9077",
			"config_file_sha256": "1222bad836c8862b68f5c44bd63029380a2cb531961da673dee4731e1a598269",
			"config_attestation": {
				"framework_is_authentic": true,
				"mcp_server_ai_memory_registered": true,
				"llm_backend_is_xai_grok": true,
				"llm_is_default_provider": true,
				"mcp_command_is_ai_memory": true,
				"agent_id_stamped": true,
				"federation_live": true,
				"ufw_disabled": true,
				"iptables_flushed": true,
				"dead_man_switch_scheduled": true
			},
			"negative_invariants": {
				"_description": "Alternative A2A channels must be OFF so a passing scenario is only passing via ai-memory shared memory. Any true here = thesis-preserving.",
				"a2a_protocol_off": true,
				"sub_agent_or_sessions_spawn_off": true,
				"alternative_channels_off": true,
				"tool_allowlist_is_memory_only": true,
				"a2a_gate_profile_locked": true
			},
			"functional_probes": {
				"xai_grok_chat_reachable": true,
				"xai_grok_sample_reply": "READY",
				"substrate_http_canary_f2a": true,
				"substrate_http_canary_uuid": "eb076df5-b9e7-4d72-b80f-17934a5647c2",
				"agent_mcp_canary_f2b": false,
				"agent_mcp_canary_uuid": "999a281c-aa19-446f-9984-4d35c4818f5e",
				"agent_canary_response_head": "error: unrecognized subcommand 'chat'    tip: a similar subcommand exists: 'channels'  Usage: ironclaw [OPTIONS] [COMMAND]  For more information, try '--help'. ",
				"_f2b_note": "F2b is LLM-dependent and non-blocking. F2a (deterministic HTTP substrate) gates baseline_pass.",
				"mesh_connectivity_f4": true,
				"mesh_edges_ok": 3,
				"mesh_edges_total": 3,
				"mesh_edges_detail": "10.251.0.4:9077:OK,10.251.0.3:9077:OK,10.251.0.5:9077:OK",
				"_f4_note": "F4 verifies this local nodes N-1 OUTBOUND mesh edges to every peer via both GET health and POST sync_push dry_run. Aggregator ANDs across N nodes to confirm full N*(N-1) bidirectional reachability. Gates baseline_pass.",
				"ai_memory_mcp_stdio_f5": true,
				"ai_memory_mcp_stdio_init_ok": true,
				"ai_memory_mcp_stdio_tools_ok": true,
				"ai_memory_mcp_stdio_tools_found": "memory_agent_list,memory_agent_register,memory_archive_list,memory_archive_purge,memory_archive_restore,memory_archive_stats,memory_auto_tag,memory_capabilities,memory_consolidate,memory_delete,memory_detect_contradiction,memory_expand_query,memory_forget,memory_gc,memory_get,memory_get_links,memory_inbox,memory_link,memory_list,memory_list_subscriptions,memory_namespace_clear_standard,memory_namespace_get_standard,memory_namespace_set_standard,memory_notify,memory_pending_approve,memory_pending_list,memory_pending_reject,memory_promote,memory_recall,memory_search,memory_session_start,memory_stats,memory_store,memory_subscribe,memory_unsubscribe,memory_update",
				"_f5_note": "F5 spawns the ai-memory stdio MCP subprocess using the framework-configured invocation and verifies initialize + tools/list return memory_store, memory_recall, memory_list. Deterministic (no LLM). Gates baseline_pass.",
				"tls_mode": "off",
				"tls_handshake_f6": true,
				"tls_handshake_f6_reason": "",
				"mtls_enforcement_f7": true,
				"mtls_enforcement_f7_reason": "",
				"_f6_f7_note": "F6 verifies the TLS 1.3 handshake against the local serve + CA chain. F7 verifies mTLS enforcement — anonymous client rejected, whitelisted client accepted. Both gate baseline_pass when tls_mode != off / mtls respectively.",
				"agent_mcp_ai_memory_canary": true,
				"canary_uuid": "eb076df5-b9e7-4d72-b80f-17934a5647c2",
				"canary_namespace": "_baseline_canary_f2a"
			},
			"baseline_pass": true
		},
		{
			"spec_version": "1.4.0",
			"agent_type": "ironclaw",
			"agent_id": "ai:bob",
			"node_index": "2",
			"framework_version": "ironclaw 0.26.0",
			"ai_memory_version": "0.6.2-rc.0",
			"peer_urls": "http://10.251.0.2:9077,http://10.251.0.3:9077,http://10.251.0.5:9077",
			"config_file_sha256": "1c6416fe43f20161d40e596b83a80ff3f2ef1e067b3e30bc7f3957a438495144",
			"config_attestation": {
				"framework_is_authentic": true,
				"mcp_server_ai_memory_registered": true,
				"llm_backend_is_xai_grok": true,
				"llm_is_default_provider": true,
				"mcp_command_is_ai_memory": true,
				"agent_id_stamped": true,
				"federation_live": true,
				"ufw_disabled": true,
				"iptables_flushed": true,
				"dead_man_switch_scheduled": true
			},
			"negative_invariants": {
				"_description": "Alternative A2A channels must be OFF so a passing scenario is only passing via ai-memory shared memory. Any true here = thesis-preserving.",
				"a2a_protocol_off": true,
				"sub_agent_or_sessions_spawn_off": true,
				"alternative_channels_off": true,
				"tool_allowlist_is_memory_only": true,
				"a2a_gate_profile_locked": true
			},
			"functional_probes": {
				"xai_grok_chat_reachable": true,
				"xai_grok_sample_reply": "READY",
				"substrate_http_canary_f2a": true,
				"substrate_http_canary_uuid": "64a4eed3-d9c2-4a89-9a27-7d647f424130",
				"agent_mcp_canary_f2b": false,
				"agent_mcp_canary_uuid": "cf93b90f-009d-44e1-adb0-6f48995f825d",
				"agent_canary_response_head": "error: unrecognized subcommand 'chat'    tip: a similar subcommand exists: 'channels'  Usage: ironclaw [OPTIONS] [COMMAND]  For more information, try '--help'. ",
				"_f2b_note": "F2b is LLM-dependent and non-blocking. F2a (deterministic HTTP substrate) gates baseline_pass.",
				"mesh_connectivity_f4": true,
				"mesh_edges_ok": 3,
				"mesh_edges_total": 3,
				"mesh_edges_detail": "10.251.0.2:9077:OK,10.251.0.3:9077:OK,10.251.0.5:9077:OK",
				"_f4_note": "F4 verifies this local nodes N-1 OUTBOUND mesh edges to every peer via both GET health and POST sync_push dry_run. Aggregator ANDs across N nodes to confirm full N*(N-1) bidirectional reachability. Gates baseline_pass.",
				"ai_memory_mcp_stdio_f5": true,
				"ai_memory_mcp_stdio_init_ok": true,
				"ai_memory_mcp_stdio_tools_ok": true,
				"ai_memory_mcp_stdio_tools_found": "memory_agent_list,memory_agent_register,memory_archive_list,memory_archive_purge,memory_archive_restore,memory_archive_stats,memory_auto_tag,memory_capabilities,memory_consolidate,memory_delete,memory_detect_contradiction,memory_expand_query,memory_forget,memory_gc,memory_get,memory_get_links,memory_inbox,memory_link,memory_list,memory_list_subscriptions,memory_namespace_clear_standard,memory_namespace_get_standard,memory_namespace_set_standard,memory_notify,memory_pending_approve,memory_pending_list,memory_pending_reject,memory_promote,memory_recall,memory_search,memory_session_start,memory_stats,memory_store,memory_subscribe,memory_unsubscribe,memory_update",
				"_f5_note": "F5 spawns the ai-memory stdio MCP subprocess using the framework-configured invocation and verifies initialize + tools/list return memory_store, memory_recall, memory_list. Deterministic (no LLM). Gates baseline_pass.",
				"tls_mode": "off",
				"tls_handshake_f6": true,
				"tls_handshake_f6_reason": "",
				"mtls_enforcement_f7": true,
				"mtls_enforcement_f7_reason": "",
				"_f6_f7_note": "F6 verifies the TLS 1.3 handshake against the local serve + CA chain. F7 verifies mTLS enforcement — anonymous client rejected, whitelisted client accepted. Both gate baseline_pass when tls_mode != off / mtls respectively.",
				"agent_mcp_ai_memory_canary": true,
				"canary_uuid": "64a4eed3-d9c2-4a89-9a27-7d647f424130",
				"canary_namespace": "_baseline_canary_f2a"
			},
			"baseline_pass": true
		},
		{
			"spec_version": "1.4.0",
			"agent_type": "ironclaw",
			"agent_id": "ai:charlie",
			"node_index": "3",
			"framework_version": "ironclaw 0.26.0",
			"ai_memory_version": "0.6.2-rc.0",
			"peer_urls": "http://10.251.0.2:9077,http://10.251.0.4:9077,http://10.251.0.5:9077",
			"config_file_sha256": "b223a15931434866e561ed79f341983d7048192e542820dba50e14c9b96b85ad",
			"config_attestation": {
				"framework_is_authentic": true,
				"mcp_server_ai_memory_registered": true,
				"llm_backend_is_xai_grok": true,
				"llm_is_default_provider": true,
				"mcp_command_is_ai_memory": true,
				"agent_id_stamped": true,
				"federation_live": true,
				"ufw_disabled": true,
				"iptables_flushed": true,
				"dead_man_switch_scheduled": true
			},
			"negative_invariants": {
				"_description": "Alternative A2A channels must be OFF so a passing scenario is only passing via ai-memory shared memory. Any true here = thesis-preserving.",
				"a2a_protocol_off": true,
				"sub_agent_or_sessions_spawn_off": true,
				"alternative_channels_off": true,
				"tool_allowlist_is_memory_only": true,
				"a2a_gate_profile_locked": true
			},
			"functional_probes": {
				"xai_grok_chat_reachable": true,
				"xai_grok_sample_reply": "READY",
				"substrate_http_canary_f2a": true,
				"substrate_http_canary_uuid": "be881456-2a81-444a-b872-a2a3c7e0ea82",
				"agent_mcp_canary_f2b": false,
				"agent_mcp_canary_uuid": "bf07e7f0-b11e-4fd4-a68c-7c82c13cf342",
				"agent_canary_response_head": "error: unrecognized subcommand 'chat'    tip: a similar subcommand exists: 'channels'  Usage: ironclaw [OPTIONS] [COMMAND]  For more information, try '--help'. ",
				"_f2b_note": "F2b is LLM-dependent and non-blocking. F2a (deterministic HTTP substrate) gates baseline_pass.",
				"mesh_connectivity_f4": true,
				"mesh_edges_ok": 3,
				"mesh_edges_total": 3,
				"mesh_edges_detail": "10.251.0.2:9077:OK,10.251.0.4:9077:OK,10.251.0.5:9077:OK",
				"_f4_note": "F4 verifies this local nodes N-1 OUTBOUND mesh edges to every peer via both GET health and POST sync_push dry_run. Aggregator ANDs across N nodes to confirm full N*(N-1) bidirectional reachability. Gates baseline_pass.",
				"ai_memory_mcp_stdio_f5": true,
				"ai_memory_mcp_stdio_init_ok": true,
				"ai_memory_mcp_stdio_tools_ok": true,
				"ai_memory_mcp_stdio_tools_found": "memory_agent_list,memory_agent_register,memory_archive_list,memory_archive_purge,memory_archive_restore,memory_archive_stats,memory_auto_tag,memory_capabilities,memory_consolidate,memory_delete,memory_detect_contradiction,memory_expand_query,memory_forget,memory_gc,memory_get,memory_get_links,memory_inbox,memory_link,memory_list,memory_list_subscriptions,memory_namespace_clear_standard,memory_namespace_get_standard,memory_namespace_set_standard,memory_notify,memory_pending_approve,memory_pending_list,memory_pending_reject,memory_promote,memory_recall,memory_search,memory_session_start,memory_stats,memory_store,memory_subscribe,memory_unsubscribe,memory_update",
				"_f5_note": "F5 spawns the ai-memory stdio MCP subprocess using the framework-configured invocation and verifies initialize + tools/list return memory_store, memory_recall, memory_list. Deterministic (no LLM). Gates baseline_pass.",
				"tls_mode": "off",
				"tls_handshake_f6": true,
				"tls_handshake_f6_reason": "",
				"mtls_enforcement_f7": true,
				"mtls_enforcement_f7_reason": "",
				"_f6_f7_note": "F6 verifies the TLS 1.3 handshake against the local serve + CA chain. F7 verifies mTLS enforcement — anonymous client rejected, whitelisted client accepted. Both gate baseline_pass when tls_mode != off / mtls respectively.",
				"agent_mcp_ai_memory_canary": true,
				"canary_uuid": "be881456-2a81-444a-b872-a2a3c7e0ea82",
				"canary_namespace": "_baseline_canary_f2a"
			},
			"baseline_pass": true
		}
	]
}

raw file

F3 — peer A2A via shared memory F3 OK

Workflow-level probe answering "can agents communicate through ai-memory?". Writer ai:alice posted canary UUID 42c8113b-8ecd-406c-b512-d94e625fbcbd to namespace _baseline_peer_canary via node-1's local ai-memory serve HTTP. After W=2 fanout settle, probe confirmed the canary on each of the 3 peer nodes via their local GET /api/v1/memories.

f3-peer-a2a.json
{
	"probe": "F3",
	"name": "peer-a2a-via-shared-memory",
	"description": "Writer agent posts a canary via local ai-memory HTTP on node-1; verifies the row propagates to the 3 peer nodes (W=2/N=4 quorum) before scenarios run.",
	"canary_uuid": "42c8113b-8ecd-406c-b512-d94e625fbcbd",
	"canary_namespace": "_baseline_peer_canary",
	"writer_agent": "ai:alice",
	"pass": true
}

raw file

Run focus

Major failures in memory sharing and advanced features across federation.

What this campaign tested: Exercised 19 scenarios covering basic recall, handoff, bulk operations, consolidation, conflict detection, deletion, linking, registration, versioning, promotion, authentication, pubsub, namespaces, sessions, and export/import across HTTP transport in a 4-node federation mesh with primitives like MCP and serve-http.

What it demonstrated: Demonstrated reliable operation in basic HTTP-based recall and some advanced primitives like deletion and linking, but exposed critical failures in MCP recall, agent registration, pubsub subscriptions, namespace hierarchies, sessions, and data import/export.

AI NHI analysis · Claude Opus 4.7

Major failures in memory sharing and advanced features across federation.

FAIL — 12/36 pass, 6 fail, 1 skipped, 17 unreported.

For three audiences

Non-technical end users

The AI agents could not reliably share memories in several key tests, with some agents recalling zero shared items when they should have seen many. Many other tests failed to run properly or report results, showing the system has bugs preventing consistent memory sharing. Overall, agents do not yet share memories dependably across the network.

C-level decision makers

High risk posture due to failures in core memory recall via MCP and advanced features like pubsub and namespaces, rendering the system not production-ready and customer claims about reliable AI-to-AI memory federation unviable. Readiness is degraded by 17 unreported scenarios, likely due to harness issues. Versus prior runs, this shows regression in coverage and stability, necessitating immediate fixes before gating releases.

Engineers & architects

Failures include S1 (MCP recall 0<20 per agent, cross-cluster identity fail), S12 (register HTTP 400, peers don't see agent), S33 (subscribe/unsubscribe 404, namespace not in list), S35 (set-parent/child/clear 405, rules not layered/visible), S36 (session start 404), S38 (import yields 0<5 rows, 0/5 markers preserved); impacted primitives are MCP transport, agent registry, pubsub, namespace ops, sessions, export/import. Probable root causes: missing API implementations (404/405 errors), federation sync issues in identity and data propagation. Harness flaws led to 16 unparseable reports (S14,S17,S18,S23,S25,S28-S32,S34,S37,S39-S42); prioritize harness stability.

What changes going into the next campaign

Resolve harness parsing issues to eliminate unparseable scenario reports before next campaign.

Tests performed in this run

Every scenario that produced a JSON report in this campaign, in testbook order. Click a row's scenario id to jump to its full report below. See the Every test performed page for the authoritative catalog.

IDTitleResultReason
S1Per-agent write + read (MCP stdio)?ai:alice recalled 0 < 20 via MCP; ai:bob recalled 0 < 20 via MCP; ai:charlie recalled 0 < 20 via MCP; cross-cluster identity check failed — see per_ns
S1bPer-agent write + read (HTTP)PASS
S2Shared-context handoffPASS
S4Federation-aware concurrent writesPASS
S5Consolidation + curationPASS
S6Contradiction detectionPASS
S9Mutation round-tripPASS
S10Deletion propagationPASS
S11Link integrityPASS
S12Agent registration?register POST returned HTTP 400; node-2 did not see registered agent ai:dave-probe-37518964; node-3 did not see registered agent ai:dave-probe-37518964; node-4 did not see registered agent ai:dave-pro
S13Concurrent write contentionPASS
S14Partition tolerance?
S15Read-your-writesPASS
S16Tier promotionPASS
S17Stats consistency?
S18Semantic query expansion?
S22Identity spoofing resistancePASS
S23Malicious content fuzz?
S24Byzantine peerSKIPNODE2_PRIV / NODE3_PRIV not set — private peer URLs unavailable
S25Clock skew tolerance?
S28memory_search keyword?
S29memory_archive lifecycle?
S30memory_capabilities handshake?
S31memory_gc quiescence?
S32memory_inbox + notify?
S33memory_subscribe pub/sub?subscribe returned HTTP 404; bob's subscription list did not include the subscribed namespace; unsubscribe returned HTTP 404
S34memory_pending governance?
S35memory_namespace standards?set-parent returned HTTP 405; set-child returned HTTP 405; clear-standard returned HTTP 405; parent rule not layered into child's standard view; child rule missing from standard view
S36memory_session_start?session_start returned HTTP 404
S37memory_get_links bidirectional?
S38/export + /import?destination count 0 < expected 5; only 0/5 markers preserved
S39/sync/since delta?
S40/memories/bulk?
S41/metrics Prometheus?
S42/namespaces enumeration?

Scenario 1 — Per-agent write + read (MCP stdio) FAIL

Reasons: ai:alice recalled 0 < 20 via MCP | ai:bob recalled 0 < 20 via MCP | ai:charlie recalled 0 < 20 via MCP | cross-cluster identity check failed — see per_ns

scenario-1.json (report)
{
	"agent_group": "ironclaw",
	"expected_per_reader": 20,
	"pass": false,
	"per_agent": {
		"ai:alice": {
			"recall": 0
		},
		"ai:bob": {
			"recall": 0
		},
		"ai:charlie": {
			"recall": 0
		}
	},
	"per_namespace_node4": {
		"scenario1-ai:alice": {
			"count": 0,
			"wrong_agent_id": 0
		},
		"scenario1-ai:bob": {
			"count": 0,
			"wrong_agent_id": 0
		},
		"scenario1-ai:charlie": {
			"count": 0,
			"wrong_agent_id": 0
		}
	},
	"reason": "ai:alice recalled 0 < 20 via MCP; ai:bob recalled 0 < 20 via MCP; ai:charlie recalled 0 < 20 via MCP; cross-cluster identity check failed — see per_ns",
	"reasons": [
		"ai:alice recalled 0 < 20 via MCP",
		"ai:bob recalled 0 < 20 via MCP",
		"ai:charlie recalled 0 < 20 via MCP",
		"cross-cluster identity check failed — see per_ns"
	],
	"scenario": "1",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-1.log (console trace)
phase A: each agent writes 10 memories via MCP
  ai:alice on 104.236.6.125
  !! drive_agent store failed for ai:alice i=1: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:alice i=2: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:alice i=3: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:alice i=4: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:alice i=5: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:alice i=6: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:alice i=7: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:alice i=8: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:alice i=9: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:alice i=10: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  ai:bob on 167.71.177.137
  !! drive_agent store failed for ai:bob i=1: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:bob i=2: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:bob i=3: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:bob i=4: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:bob i=5: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:bob i=6: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:bob i=7: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:bob i=8: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:bob i=9: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:bob i=10: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  ai:charlie on 167.99.59.68
  !! drive_agent store failed for ai:charlie i=1: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:charlie i=2: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:charlie i=3: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:charlie i=4: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:charlie i=5: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:charlie i=6: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:charlie i=7: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:charlie i=8: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:charlie i=9: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

  !! drive_agent store failed for ai:charlie i=10: error: unrecognized subcommand 'chat'

  tip: a similar subcommand exists: 'channels'

Usage: ironclaw [OPTIONS] [COMMAND]

For more information, try '--help'.

settle 15s for W=2/N=4 convergence
phase B: each agent counts rows in the OTHER two namespaces
  ai:alice recalled 0 rows from the other two namespaces
  ai:bob recalled 0 rows from the other two namespaces
  ai:charlie recalled 0 rows from the other two namespaces
phase C: cross-cluster identity check on node-4
  ns=scenario1-ai:alice count=0 wrong_agent_id=0
  !! expected 10 rows, got 0
  ns=scenario1-ai:bob count=0 wrong_agent_id=0
  !! expected 10 rows, got 0
  ns=scenario1-ai:charlie count=0 wrong_agent_id=0
  !! expected 10 rows, got 0

raw file

Scenario 1b — Per-agent write + read (HTTP) PASS

scenario-1b.json (report)
{
	"agent_group": "ironclaw",
	"expected_per_reader": 20,
	"pass": true,
	"path": "serve-http",
	"per_agent": {
		"ai:alice": {
			"recall": 20
		},
		"ai:bob": {
			"recall": 20
		},
		"ai:charlie": {
			"recall": 20
		}
	},
	"per_namespace_node4": {
		"scenario1b-ai:alice": {
			"count": 10,
			"wrong_agent_id": 0
		},
		"scenario1b-ai:bob": {
			"count": 10,
			"wrong_agent_id": 0
		},
		"scenario1b-ai:charlie": {
			"count": 10,
			"wrong_agent_id": 0
		}
	},
	"reasons": [],
	"scenario": "1b",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-1b.log (console trace)
phase A: each agent POSTs 10 memories to local serve
  ai:alice on 104.236.6.125
  ai:bob on 167.71.177.137
  ai:charlie on 167.99.59.68
settle 15s for W=2/N=4 convergence
phase B: count rows in other two namespaces via local serve HTTP
  ai:alice sees 20 rows from the other two namespaces
  ai:bob sees 20 rows from the other two namespaces
  ai:charlie sees 20 rows from the other two namespaces
phase C: cross-cluster identity check on node-4
  ns=scenario1b-ai:alice count=10 wrong_agent_id=0
  ns=scenario1b-ai:bob count=10 wrong_agent_id=0
  ns=scenario1b-ai:charlie count=10 wrong_agent_id=0

raw file

Scenario 2 — Shared-context handoff PASS

scenario-2.json (report)
{
	"ack_uuid": "a-0c93ee1912904881943cfcb8e292b007",
	"agent_group": "ironclaw",
	"handoff_uuid": "h-9a1ffe31349b4772b359ca3c13dfb592",
	"pass": true,
	"path": "serve-http",
	"per_agent": {
		"ai:alice": {
			"sees_ack": 1
		},
		"ai:bob": {
			"sees_handoff": 1
		}
	},
	"reasons": [],
	"scenario": "2",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-2.log (console trace)
phase A: ai:alice writes handoff to ai:bob (uuid=h-9a1ffe31349b4772b359ca3c13dfb592)
settle 8s for quorum fanout
phase B: ai:bob reads handoff on node-2
  ai:bob sees 1 handoff memories from ai:alice
phase C: ai:bob writes acknowledgement (uuid=a-0c93ee1912904881943cfcb8e292b007)
settle 8s for reverse-direction fanout
phase D: ai:alice reads ack on node-1
  ai:alice sees 1 ack memories from ai:bob

raw file

Scenario 4 — Federation-aware concurrent writes PASS

scenario-4.json (report)
{
	"agent_group": "ironclaw",
	"expected_per_agent": 30,
	"pass": true,
	"per_agent": {
		"ai:alice": {
			"count": 30,
			"wrong_agent_id": 0
		},
		"ai:bob": {
			"count": 30,
			"wrong_agent_id": 0
		},
		"ai:charlie": {
			"count": 30,
			"wrong_agent_id": 0
		}
	},
	"reasons": [],
	"scenario": "4",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-4.log (console trace)
phase A: launching concurrent 30-row bursts from 3 agents
  ai:alice burst ok=30/30
  ai:bob burst ok=30/30
  ai:charlie burst ok=30/30
settle 20s for W=2 fanout convergence
phase B: querying node-4 aggregator for per-agent counts
  ai:alice: count=30 (expected 30) wrong_agent_id=0
  ai:bob: count=30 (expected 30) wrong_agent_id=0
  ai:charlie: count=30 (expected 30) wrong_agent_id=0

raw file

Scenario 5 — Consolidation + curation PASS

scenario-5.json (report)
{
	"agent_group": "ironclaw",
	"consolidate_http_code": 201,
	"consolidated_from_agents": [
		"ai:charlie",
		"ai:bob",
		"ai:alice"
	],
	"consolidated_id": "e1b88027-2cde-460e-a172-e318ed086599",
	"pass": true,
	"reasons": [],
	"scenario": "5",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-5.log (console trace)
phase A: each agent writes 3 related memories
  ai:alice on 104.236.6.125
  ai:bob on 167.71.177.137
  ai:charlie on 167.99.59.68
settle 8s for quorum fanout
phase B: collect source ids on node-1, then trigger consolidate
  source ids (count=9): ['2136d449-97c7-452c-8fb9-1e217d8befa2', '94f25cf9-d7a1-438a-bd41-58233b2cf8e1', '9d24c031-e1d0-4363-99e0-c8a3c37c6df0', '8f186771-bb08-44a2-ab3b-c092b14e8bde', '580679e7-50e0-414d-8463-5275eed45fdb']...
  consolidate HTTP 201, consolidated_id=e1b88027-2cde-460e-a172-e318ed086599
settle 10s for consolidation fanout
phase C: verifying consolidated_from_agents on node-4
  consolidated_from_agents=['ai:charlie', 'ai:bob', 'ai:alice']

raw file

Scenario 6 — Contradiction detection PASS

scenario-6.json (report)
{
	"agent_group": "ironclaw",
	"alice_id": "81f6dcf5-c511-45e2-8b26-b3ee790cc325",
	"bob_id": "8fb254b5-830d-4c2f-b35f-a0ff664cc5bc",
	"charlie_sees_both_memories": true,
	"charlie_sees_contradicts_link": true,
	"detect_http_code": 200,
	"pass": true,
	"reasons": [],
	"scenario": "6",
	"skipped": false,
	"tls_mode": "off",
	"topic": "sky-color-199703d5"
}

raw file

scenario-6.log (console trace)
alice writes claim: "sky-color-199703d5 is blue" on node-1
bob writes contradicting claim: "sky-color-199703d5 is red" on node-2
  alice.id=81f6dcf5-c511-45e2-8b26-b3ee790cc325 bob.id=8fb254b5-830d-4c2f-b35f-a0ff664cc5bc
settle 10s for quorum fanout + contradiction indexing
charlie queries /api/v1/contradictions on node-3
  HTTP 200
  sees both memories: True; sees contradicts link: True

raw file

Scenario 9 — Mutation round-trip PASS

scenario-9.json (report)
{
	"agent_group": "ironclaw",
	"charlie_view": {
		"agent_id": "ai:alice",
		"content": "v2-73b9c66d40f6436f9627da291f69438e"
	},
	"m1_id": "a099c1ae-9ee6-4865-afdd-b6a03c274df7",
	"pass": true,
	"put_http_code": 200,
	"reasons": [],
	"scenario": "9",
	"skipped": false,
	"tls_mode": "off",
	"v1_uuid": "v1-61424dd3db024db4bb40980a763caac7",
	"v2_uuid": "v2-73b9c66d40f6436f9627da291f69438e"
}

raw file

scenario-9.log (console trace)
alice writes M1 content=v1-61424dd3db024db4bb40980a763caac7 on node-1
  M1 id=a099c1ae-9ee6-4865-afdd-b6a03c274df7
settle 5s for initial replication
bob updates M1 content=v2-73b9c66d40f6436f9627da291f69438e on node-2 via PUT
  PUT returned HTTP 200
settle 8s for update fanout
charlie reads M1 on node-3 and checks content + provenance
  charlie sees content="v2-73b9c66d40f6436f9627da291f69438e" agent_id="ai:alice"

raw file

Scenario 10 — Deletion propagation PASS

scenario-10.json (report)
{
	"agent_group": "ironclaw",
	"delete_http_code": 200,
	"m1_id": "a807c967-e22b-4cd7-b351-b3fcb532159f",
	"pass": true,
	"post_delete_hits": {
		"node-2": 0,
		"node-3": 0,
		"node-4": 0
	},
	"post_delete_still_visible_peers": 0,
	"pre_delete_visible_peers": 3,
	"reasons": [],
	"scenario": "10",
	"skipped": false,
	"tls_mode": "off",
	"uuid": "d-4ee271076ce843b189cd4e0288c73b7f"
}

raw file

scenario-10.log (console trace)
alice writes M1 content=d-4ee271076ce843b189cd4e0288c73b7f on node-1
  created memory id=a807c967-e22b-4cd7-b351-b3fcb532159f
settle 8s for pre-delete fanout
pre-delete: verifying M1 is visible on all peers
  pre-delete node-2 sees 1
  pre-delete node-3 sees 1
  pre-delete node-4 sees 1
alice deletes M1 on node-1
  DELETE returned HTTP 200
settle 15s for tombstone propagation
post-delete: verifying M1 is GONE from all peers
  post-delete node-2 sees 0 (expected 0)
  post-delete node-3 sees 0 (expected 0)
  post-delete node-4 sees 0 (expected 0)

raw file

Scenario 11 — Link integrity PASS

scenario-11.json (report)
{
	"agent_group": "ironclaw",
	"charlie_sees_link": 1,
	"link_http_code": 201,
	"m1_id": "c56e5cd2-d87b-4034-9615-e3f920e70369",
	"m2_id": "4f31452a-2c30-476e-8000-9aea89a87549",
	"pass": true,
	"reasons": [],
	"relation": "related_to",
	"scenario": "11",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-11.log (console trace)
alice writes M1 on node-1
bob writes M2 on node-2
  M1=c56e5cd2-d87b-4034-9615-e3f920e70369 M2=4f31452a-2c30-476e-8000-9aea89a87549
settle 5s for pre-link replication
alice links M1 -> M2 with relation=related_to
  link POST returned HTTP 201
settle 8s for link fanout
charlie queries links of M1 on node-3
  charlie sees M1->M2 link: 1 (expected >=1)

raw file

Scenario 12 — Agent registration FAIL

Reasons: register POST returned HTTP 400 | node-2 did not see registered agent ai:dave-probe-37518964 | node-3 did not see registered agent ai:dave-probe-37518964 | node-4 did not see registered agent ai:dave-probe-37518964

scenario-12.json (report)
{
	"agent_group": "ironclaw",
	"pass": false,
	"peers_see": {
		"node_2": 0,
		"node_3": 0,
		"node_4": 0
	},
	"reason": "register POST returned HTTP 400; node-2 did not see registered agent ai:dave-probe-37518964; node-3 did not see registered agent ai:dave-probe-37518964; node-4 did not see registered agent ai:dave-probe-37518964",
	"reasons": [
		"register POST returned HTTP 400",
		"node-2 did not see registered agent ai:dave-probe-37518964",
		"node-3 did not see registered agent ai:dave-probe-37518964",
		"node-4 did not see registered agent ai:dave-probe-37518964"
	],
	"register_http_code": 400,
	"registered_agent": "ai:dave-probe-37518964",
	"scenario": "12",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-12.log (console trace)
alice registers new agent ai:dave-probe-37518964 on node-1
  POST /api/v1/agents returned HTTP 400
settle 10s for agent-list fanout
  node-2 sees ai:dave-probe-37518964: 0 (expected >=1)
  node-3 sees ai:dave-probe-37518964: 0 (expected >=1)
  node-4 sees ai:dave-probe-37518964: 0 (expected >=1)

raw file

Scenario 13 — Concurrent write contention PASS

scenario-13.json (report)
{
	"agent_group": "ironclaw",
	"m1_id": "68b22549-b5cf-4253-a729-8ac3163d2908",
	"pass": true,
	"peer_view": {
		"node_1": "vb-1a20a8214d084ddead984cc11ae3fda1",
		"node_2": "vb-1a20a8214d084ddead984cc11ae3fda1",
		"node_3": "vb-1a20a8214d084ddead984cc11ae3fda1",
		"node_4": "vb-1a20a8214d084ddead984cc11ae3fda1"
	},
	"reasons": [],
	"scenario": "13",
	"skipped": false,
	"submitted": {
		"v0": "v0-341bf387da7945f29212080c754ffa83",
		"vA_alice": "va-f5afa1099f4c4ecfa723e7d8b1d05a8c",
		"vB_bob": "vb-1a20a8214d084ddead984cc11ae3fda1"
	},
	"tls_mode": "off"
}

raw file

scenario-13.log (console trace)
alice writes M1 content=v0-341bf387da7945f29212080c754ffa83 on node-1
  M1 id=68b22549-b5cf-4253-a729-8ac3163d2908
settle 5s for initial replication
alice + bob issue concurrent PUTs (vA=va-f5afa1099f4c4ecfa723e7d8b1d05a8c from alice, vB=vb-1a20a8214d084ddead984cc11ae3fda1 from bob)
  concurrent PUT results: [(0, {'body': {'access_count': 0, 'confidence': 1.0, 'content': 'va-f5afa1099f4c4ecfa723e7d8b1d05a8c', 'created_at': '2026-04-22T01:28:56.034482668+00:00', 'expires_at': '2026-04-29T01:28:56.034482668+00:00', 'id': '68b22549-b5cf-4253-a729-8ac3163d2908', 'metadata': {'agent_id': 'ai:alice', 'scenario': '13'}, 'namespace': 'scenario13-contention', 'priority': 5, 'source': 'api', 'tags': [], 'tier': 'mid', 'title': 'm1', 'updated_at': '2026-04-22T01:29:01.478803759+00:00'}, 'http_code': 200}), (0, {'body': {'access_count': 0, 'confidence': 1.0, 'content': 'vb-1a20a8214d084ddead984cc11ae3fda1', 'created_at': '2026-04-22T01:28:56.034482668+00:00', 'expires_at': '2026-04-29T01:28:56.034482668+00:00', 'id': '68b22549-b5cf-4253-a729-8ac3163d2908', 'metadata': {'agent_id': 'ai:alice', 'scenario': '13'}, 'namespace': 'scenario13-contention', 'priority': 5, 'source': 'api', 'tags': [], 'tier': 'mid', 'title': 'm1', 'updated_at': '2026-04-22T01:29:01.488012686+00:00'}, 'http_code': 200})]
settle 10s for quorum convergence
  node-1 sees content=vb-1a20a8214d084ddead984cc11ae3fda1
  node-2 sees content=vb-1a20a8214d084ddead984cc11ae3fda1
  node-3 sees content=vb-1a20a8214d084ddead984cc11ae3fda1
  node-4 sees content=vb-1a20a8214d084ddead984cc11ae3fda1

raw file

Scenario 14 — Partition tolerance UNKNOWN

scenario-14.json (report)

          

raw file

scenario-14.log (console trace)
suspending ai-memory on node-3 (SIGSTOP)
Traceback (most recent call last):
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/14_partition_tolerance.py", line 80, in <module>
    main()
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/14_partition_tolerance.py", line 29, in main
    h.ssh_exec(h.node3_ip, "pgrep -f 'ai-memory serve' | xargs -r kill -STOP", timeout=15)
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 78, in ssh_exec
    return subprocess.run(
           ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 550, in run
    stdout, stderr = process.communicate(input, timeout=timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 1209, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 2116, in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
  File "/usr/lib/python3.12/subprocess.py", line 1253, in _check_timeout
    raise TimeoutExpired(
subprocess.TimeoutExpired: Command '['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=10', '-o', 'ServerAliveInterval=5', 'root@167.99.59.68', "pgrep -f 'ai-memory serve' | xargs -r kill -STOP"]' timed out after 15 seconds

raw file

Scenario 15 — Read-your-writes PASS

scenario-15.json (report)
{
	"agent_group": "ironclaw",
	"pass": true,
	"reasons": [],
	"scenario": "15",
	"skipped": false,
	"tls_mode": "off",
	"uuid": "ryw-a44a41a8a9fe4f2498e62a1431fa1f60",
	"writer_sees_own_write": 1
}

raw file

scenario-15.log (console trace)
alice writes + immediately reads M1 on node-1 (uuid=ryw-a44a41a8a9fe4f2498e62a1431fa1f60)
  alice sees 1 (expected 1) immediately after write

raw file

Scenario 16 — Tier promotion PASS

scenario-16.json (report)
{
	"agent_group": "ironclaw",
	"bob_sees_tier": "long",
	"m1_id": "3a905006-c7c4-465a-843d-47ac44914215",
	"pass": true,
	"promote_http_code": 200,
	"reasons": [],
	"scenario": "16",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-16.log (console trace)
alice writes M1 tier=short on node-1
  M1 id=3a905006-c7c4-465a-843d-47ac44914215
settle 5s for pre-promote replication
alice promotes M1 to tier=long
  promote returned HTTP 200
settle 8s for promotion fanout
  bob sees tier=long (expected long)

raw file

Scenario 17 — Stats consistency UNKNOWN

scenario-17.json (report)

          

raw file

scenario-17.log (console trace)
phase A: each of 3 agents writes 5 memories to scenario17-stats
  ai:alice on 104.236.6.125
  ai:bob on 167.71.177.137
  ai:charlie on 167.99.59.68
Traceback (most recent call last):
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/17_stats_consistency.py", line 67, in <module>
    main()
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/17_stats_consistency.py", line 35, in main
    h.write_memory(ip, aid, ns, title=f"stats-{aid}-{i}", content=u)
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 181, in write_memory
    return self.http_on(node_ip, "POST", "/api/v1/memories",
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 136, in http_on
    result = self.ssh_exec(node_ip, remote_cmd, timeout=timeout)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 78, in ssh_exec
    return subprocess.run(
           ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 550, in run
    stdout, stderr = process.communicate(input, timeout=timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 1209, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 2116, in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
  File "/usr/lib/python3.12/subprocess.py", line 1253, in _check_timeout
    raise TimeoutExpired(
subprocess.TimeoutExpired: Command '['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=10', '-o', 'ServerAliveInterval=5', 'root@167.99.59.68', 'curl -sS -X POST http://127.0.0.1:9077/api/v1/memories -H \'Content-Type: application/json\' -H \'X-Agent-Id: ai:charlie\' -d \'{"tier": "mid", "namespace": "scenario17-stats", "title": "stats-ai:charlie-1", "content": "stats-ai:charlie-1-029383c241094119ad2c9764eb2002c7", "priority": 5, "confidence": 1.0, "source": "api", "metadata": {"agent_id": "ai:charlie", "scenario": "17"}}\'']' timed out after 30 seconds

raw file

Scenario 18 — Semantic query expansion UNKNOWN

scenario-18.json (report)

          

raw file

scenario-18.log (console trace)
alice writes A on node-1
bob writes B on node-2
settle 15s for fanout + index rebuild
charlie queries on node-3 with semantically-related prompt
Traceback (most recent call last):
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/18_query_expansion.py", line 84, in <module>
    main()
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/18_query_expansion.py", line 46, in main
    _, resp = h.http_on(h.node3_ip, "GET", f"/api/v1/recall?{q}")
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 136, in http_on
    result = self.ssh_exec(node_ip, remote_cmd, timeout=timeout)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 78, in ssh_exec
    return subprocess.run(
           ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 550, in run
    stdout, stderr = process.communicate(input, timeout=timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 1209, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 2116, in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
  File "/usr/lib/python3.12/subprocess.py", line 1253, in _check_timeout
    raise TimeoutExpired(
subprocess.TimeoutExpired: Command '['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=10', '-o', 'ServerAliveInterval=5', 'root@167.99.59.68', "curl -sS -X GET 'http://127.0.0.1:9077/api/v1/recall?context=morning+outdoor+exercise+routine&namespace=scenario18-semantic&limit=20' -H 'Content-Type: application/json'"]' timed out after 30 seconds

raw file

Scenario 22 — Identity spoofing resistance PASS

scenario-22.json (report)
{
	"agent_group": "ironclaw",
	"pass": true,
	"reasons": [],
	"scenario": "22",
	"skipped": false,
	"tests": {
		"body_vs_header_conflict": {
			"acceptable": [
				"ai:body-wins",
				"ai:attacker"
			],
			"stored_agent_id": "ai:attacker"
		},
		"header_only": {
			"expected": "ai:alice",
			"stored_agent_id": "ai:alice"
		}
	},
	"tls_mode": "off"
}

raw file

scenario-22.log (console trace)
test 1: header-only X-Agent-Id=ai:alice
settle 2s for read-settle
  stored metadata.agent_id for header-only write: ai:alice (expected ai:alice)
test 2: body.metadata.agent_id=ai:body-wins vs X-Agent-Id=ai:attacker
settle 2s for read-settle
  stored metadata.agent_id for body+header conflict: ai:attacker

raw file

Scenario 23 — Malicious content fuzz UNKNOWN

scenario-23.json (report)

          

raw file

scenario-23.log (console trace)
payload sql: 61 bytes
payload html: 66 bytes
payload oversize: 1048576 bytes
Traceback (most recent call last):
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/23_malicious_content_fuzz.py", line 106, in <module>
    main()
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/23_malicious_content_fuzz.py", line 49, in main
    rc, write_doc = h.write_memory(
                    ^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 181, in write_memory
    return self.http_on(node_ip, "POST", "/api/v1/memories",
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 136, in http_on
    result = self.ssh_exec(node_ip, remote_cmd, timeout=timeout)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 78, in ssh_exec
    return subprocess.run(
           ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 548, in run
    with Popen(*popenargs, **kwargs) as process:
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 1026, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/lib/python3.12/subprocess.py", line 1955, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
OSError: [Errno 7] Argument list too long: 'ssh'

raw file

Scenario 24 — Byzantine peer UNKNOWN

scenario-24.json (report)
{
	"agent_group": "ironclaw",
	"pass": null,
	"reason": "NODE2_PRIV / NODE3_PRIV not set — private peer URLs unavailable",
	"scenario": "24",
	"skipped": true,
	"tls_mode": "off"
}

raw file

scenario-24.log (console trace)
skipped — NODE2_PRIV / NODE3_PRIV not set — private peer URLs unavailable

raw file

Scenario 25 — Clock skew tolerance UNKNOWN

scenario-25.json (report)

          

raw file

scenario-25.log (console trace)
shifting node-3 clock +300s (NTP disabled for the duration)
  node-3 now reports: Wed Apr 22 01:36:16 UTC 2026
alice writes on node-1 (normal clock); waiting for quorum fanout to skewed node-3
settle 15s for skewed-peer convergence
reverting node-3 clock
Traceback (most recent call last):
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/25_clock_skew.py", line 83, in <module>
    main()
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/25_clock_skew.py", line 46, in main
    seen_n3 = h.count_matching(h.node3_ip, ns, content_contains=marker, limit=20)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 209, in count_matching
    rc, resp = self.list_memories(node_ip, namespace, limit=limit)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 186, in list_memories
    return self.http_on(node_ip, "GET", f"/api/v1/memories?{q}")
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 136, in http_on
    result = self.ssh_exec(node_ip, remote_cmd, timeout=timeout)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 78, in ssh_exec
    return subprocess.run(
           ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 550, in run
    stdout, stderr = process.communicate(input, timeout=timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 1209, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 2116, in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
  File "/usr/lib/python3.12/subprocess.py", line 1253, in _check_timeout
    raise TimeoutExpired(
subprocess.TimeoutExpired: Command '['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=10', '-o', 'ServerAliveInterval=5', 'root@167.99.59.68', "curl -sS -X GET 'http://127.0.0.1:9077/api/v1/memories?namespace=scenario25-clock&limit=20' -H 'Content-Type: application/json'"]' timed out after 30 seconds

raw file

Scenario 28 — memory_search keyword UNKNOWN

scenario-28.json (report)

          

raw file

scenario-28.log (console trace)
alice writes a row containing unique token=kwsearch-c3d5607f50
settle 8s for search index populate + fanout
bob + charlie call /api/v1/search with the exact token
  node-2 keyword search returned 0 hits
Traceback (most recent call last):
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/28_memory_search.py", line 64, in <module>
    main()
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/28_memory_search.py", line 38, in main
    _, resp = h.http_on(ip, "GET", f"/api/v1/search?{q}")
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 136, in http_on
    result = self.ssh_exec(node_ip, remote_cmd, timeout=timeout)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 78, in ssh_exec
    return subprocess.run(
           ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 550, in run
    stdout, stderr = process.communicate(input, timeout=timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 1209, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 2116, in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
  File "/usr/lib/python3.12/subprocess.py", line 1253, in _check_timeout
    raise TimeoutExpired(
subprocess.TimeoutExpired: Command '['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=10', '-o', 'ServerAliveInterval=5', 'root@167.99.59.68', "curl -sS -X GET 'http://127.0.0.1:9077/api/v1/search?q=kwsearch-c3d5607f50&namespace=scenario28-search&limit=20' -H 'Content-Type: application/json'"]' timed out after 30 seconds

raw file

Scenario 29 — memory_archive lifecycle UNKNOWN

scenario-29.json (report)

          

raw file

scenario-29.log (console trace)
alice writes M1 on node-1
  M1 id=886d802c-99cc-46b3-87eb-787999423b55
settle 5s for pre-archive replication
alice archives M1 via DELETE /api/v1/memories/{id} (soft-delete → archive)
  archive returned HTTP 405
settle 5s for archive propagation
bob queries /api/v1/archive on node-2
  bob sees M1 in archive: False
charlie restores M1 via /api/v1/archive/{id}/restore on node-3
Traceback (most recent call last):
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/29_archive_lifecycle.py", line 106, in <module>
    main()
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/29_archive_lifecycle.py", line 58, in main
    _, restore_doc = h.http_on(
                     ^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 136, in http_on
    result = self.ssh_exec(node_ip, remote_cmd, timeout=timeout)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 78, in ssh_exec
    return subprocess.run(
           ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 550, in run
    stdout, stderr = process.communicate(input, timeout=timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 1209, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 2116, in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
  File "/usr/lib/python3.12/subprocess.py", line 1253, in _check_timeout
    raise TimeoutExpired(
subprocess.TimeoutExpired: Command '['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=10', '-o', 'ServerAliveInterval=5', 'root@167.99.59.68', "curl -sS -X POST http://127.0.0.1:9077/api/v1/archive/886d802c-99cc-46b3-87eb-787999423b55/restore -H 'Content-Type: application/json' -H 'X-Agent-Id: ai:charlie' -w '\n__HTTP__%{http_code}'"]' timed out after 30 seconds

raw file

Scenario 30 — memory_capabilities handshake UNKNOWN

scenario-30.json (report)

          

raw file

scenario-30.log (console trace)
  node-1 capabilities: []
  node-2 capabilities: []
Traceback (most recent call last):
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/30_capabilities_handshake.py", line 79, in <module>
    main()
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/30_capabilities_handshake.py", line 44, in main
    cap = _capabilities(h, ip)
          ^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/30_capabilities_handshake.py", line 28, in _capabilities
    _, doc = h.http_on(ip, "GET", path, include_status=True)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 136, in http_on
    result = self.ssh_exec(node_ip, remote_cmd, timeout=timeout)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 78, in ssh_exec
    return subprocess.run(
           ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 550, in run
    stdout, stderr = process.communicate(input, timeout=timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 1209, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 2116, in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
  File "/usr/lib/python3.12/subprocess.py", line 1253, in _check_timeout
    raise TimeoutExpired(
subprocess.TimeoutExpired: Command '['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=10', '-o', 'ServerAliveInterval=5', 'root@167.99.59.68', "curl -sS -X GET http://127.0.0.1:9077/api/v1/capabilities -H 'Content-Type: application/json' -w '\n__HTTP__%{http_code}'"]' timed out after 30 seconds

raw file

Scenario 31 — memory_gc quiescence UNKNOWN

scenario-31.json (report)

          

raw file

scenario-31.log (console trace)
alice writes 4 memories
settle 6s for pre-gc replication
alice forgets 2 via /api/v1/forget
  forget returned HTTP 400
settle 5s for forget propagation
bob triggers /api/v1/gc on node-2
  gc returned HTTP 200
settle 8s for post-gc settle
verify remaining 2 markers are still readable on every peer
  node-1 sees 2/2 live markers
  node-2 sees 2/2 live markers
Traceback (most recent call last):
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/31_gc_quiescence.py", line 86, in <module>
    main()
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/31_gc_quiescence.py", line 63, in main
    hits += 1 if h.count_matching(ip, ns, content_contains=marker, limit=20) >= 1 else 0
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 209, in count_matching
    rc, resp = self.list_memories(node_ip, namespace, limit=limit)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 186, in list_memories
    return self.http_on(node_ip, "GET", f"/api/v1/memories?{q}")
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 136, in http_on
    result = self.ssh_exec(node_ip, remote_cmd, timeout=timeout)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 78, in ssh_exec
    return subprocess.run(
           ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 550, in run
    stdout, stderr = process.communicate(input, timeout=timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 1209, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 2116, in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
  File "/usr/lib/python3.12/subprocess.py", line 1253, in _check_timeout
    raise TimeoutExpired(
subprocess.TimeoutExpired: Command '['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=10', '-o', 'ServerAliveInterval=5', 'root@167.99.59.68', "curl -sS -X GET 'http://127.0.0.1:9077/api/v1/memories?namespace=scenario31-gc&limit=20' -H 'Content-Type: application/json'"]' timed out after 30 seconds

raw file

Scenario 32 — memory_inbox + notify UNKNOWN

scenario-32.json (report)

          

raw file

scenario-32.log (console trace)
alice calls /api/v1/notify → target=ai:bob
  notify returned HTTP 404
settle 6s for notification fanout
bob queries his inbox on node-2
  bob inbox has 0 messages; sees marker: False
charlie queries his inbox on node-3 (must NOT see it)
Traceback (most recent call last):
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/32_inbox_notify.py", line 87, in <module>
    main()
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/32_inbox_notify.py", line 57, in main
    charlie_inbox = _inbox(h, h.node3_ip, "ai:charlie")
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/32_inbox_notify.py", line 23, in _inbox
    _, resp = h.http_on(ip, "GET", f"/api/v1/inbox?agent_id={agent_id}&limit=50",
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 136, in http_on
    result = self.ssh_exec(node_ip, remote_cmd, timeout=timeout)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 78, in ssh_exec
    return subprocess.run(
           ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 550, in run
    stdout, stderr = process.communicate(input, timeout=timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 1209, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 2116, in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
  File "/usr/lib/python3.12/subprocess.py", line 1253, in _check_timeout
    raise TimeoutExpired(
subprocess.TimeoutExpired: Command '['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=10', '-o', 'ServerAliveInterval=5', 'root@167.99.59.68', "curl -sS -X GET 'http://127.0.0.1:9077/api/v1/inbox?agent_id=ai:charlie&limit=50' -H 'Content-Type: application/json' -H 'X-Agent-Id: ai:charlie'"]' timed out after 30 seconds

raw file

Scenario 33 — memory_subscribe pub/sub FAIL

Reasons: subscribe returned HTTP 404 | bob's subscription list did not include the subscribed namespace | unsubscribe returned HTTP 404

scenario-33.json (report)
{
	"agent_group": "ironclaw",
	"m1_delivered": 1,
	"namespace": "scenario33-pubsub-0ed085",
	"ns_in_subs_after": false,
	"ns_in_subs_before": false,
	"pass": false,
	"reason": "subscribe returned HTTP 404; bob's subscription list did not include the subscribed namespace; unsubscribe returned HTTP 404",
	"reasons": [
		"subscribe returned HTTP 404",
		"bob's subscription list did not include the subscribed namespace",
		"unsubscribe returned HTTP 404"
	],
	"scenario": "33",
	"skipped": false,
	"subscribe_http_code": 404,
	"subscriptions_after_count": 0,
	"subscriptions_before_count": 0,
	"tls_mode": "off",
	"unsubscribe_http_code": 404
}

raw file

scenario-33.log (console trace)
bob subscribes to namespace scenario33-pubsub-0ed085 on node-2
  subscribe returned HTTP 404
settle 2s for subscription settle
  bob subscriptions: 0 entries; contains ns: False
alice writes M1 into the subscribed namespace
settle 6s for write fanout to subscribers
  bob sees M1 in subscribed namespace: 1
bob unsubscribes from scenario33-pubsub-0ed085
  unsubscribe returned HTTP 404
settle 2s for unsubscribe settle
  bob subscriptions after unsubscribe: ns still present = False
alice writes M2 post-unsubscribe (may still replicate via federation but subscription list excludes ns)
settle 5s for post-unsubscribe settle

raw file

Scenario 34 — memory_pending governance UNKNOWN

scenario-34.json (report)

          

raw file

scenario-34.log (console trace)
alice sets namespace standard on scenario34-pending-d9c5bb: write=approve, approver=ai:bob
  set-standard returned HTTP 405
settle 2s for standard settle
alice writes two memories into the governed namespace (should land in pending)
  p1=a88c1fdc-e1e1-4e2c-8f4a-9484d0aa8123 p2=a1717e4f-a014-4092-bc2c-4056429dbf0b
settle 4s for pending queue settle
bob lists pending on node-2
  pending queue has 0 entries
bob approves p1, rejects p2
  approve HTTP 403; reject HTTP 404
settle 5s for decision fanout
charlie reads the namespace — expects ONLY approved marker
Traceback (most recent call last):
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/34_pending_governance.py", line 111, in <module>
    main()
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/34_pending_governance.py", line 75, in main
    sees_approved = h.count_matching(h.node3_ip, ns, content_contains=approved_marker, limit=20)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 209, in count_matching
    rc, resp = self.list_memories(node_ip, namespace, limit=limit)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 186, in list_memories
    return self.http_on(node_ip, "GET", f"/api/v1/memories?{q}")
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 136, in http_on
    result = self.ssh_exec(node_ip, remote_cmd, timeout=timeout)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 78, in ssh_exec
    return subprocess.run(
           ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 550, in run
    stdout, stderr = process.communicate(input, timeout=timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 1209, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 2116, in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
  File "/usr/lib/python3.12/subprocess.py", line 1253, in _check_timeout
    raise TimeoutExpired(
subprocess.TimeoutExpired: Command '['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=10', '-o', 'ServerAliveInterval=5', 'root@167.99.59.68', "curl -sS -X GET 'http://127.0.0.1:9077/api/v1/memories?namespace=scenario34-pending-d9c5bb&limit=20' -H 'Content-Type: application/json'"]' timed out after 30 seconds

raw file

Scenario 35 — memory_namespace standards FAIL

Reasons: set-parent returned HTTP 405 | set-child returned HTTP 405 | clear-standard returned HTTP 405 | parent rule not layered into child's standard view | child rule missing from standard view

scenario-35.json (report)
{
	"agent_group": "ironclaw",
	"child_ns": "scenario35-parent-9e6eda/child",
	"clear_http_code": 405,
	"get_standard_http_code": 200,
	"parent_ns": "scenario35-parent-9e6eda",
	"pass": false,
	"post_clear_has_child_rule": false,
	"reason": "set-parent returned HTTP 405; set-child returned HTTP 405; clear-standard returned HTTP 405; parent rule not layered into child's standard view; child rule missing from standard view",
	"reasons": [
		"set-parent returned HTTP 405",
		"set-child returned HTTP 405",
		"clear-standard returned HTTP 405",
		"parent rule not layered into child's standard view",
		"child rule missing from standard view"
	],
	"scenario": "35",
	"sees_child_rule": false,
	"sees_parent_rule": false,
	"set_child_http_code": 405,
	"set_parent_http_code": 405,
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-35.log (console trace)
alice writes parent-standard-memory on node-1
alice sets namespace standard on scenario35-parent-9e6eda
  set-parent returned HTTP 405
alice writes child-standard-memory on node-1
alice sets namespace standard on scenario35-parent-9e6eda/child with parent=scenario35-parent-9e6eda
  set-child returned HTTP 405
settle 4s for standard fanout
bob gets standard for scenario35-parent-9e6eda/child on node-2 (expects layered parent+child)
  get-standard returned HTTP 200
  parent-rule visible=False; child-rule visible=False
alice clears standard on scenario35-parent-9e6eda/child
  clear returned HTTP 405
settle 3s for clear settle

raw file

Scenario 36 — memory_session_start FAIL

Reasons: session_start returned HTTP 404

scenario-36.json (report)
{
	"agent_group": "ironclaw",
	"pass": false,
	"reason": "session_start returned HTTP 404",
	"reasons": [
		"session_start returned HTTP 404"
	],
	"scenario": "36",
	"skipped": false,
	"start_http_code": 404,
	"tls_mode": "off"
}

raw file

scenario-36.log (console trace)
alice starts a session on node-1
  session_start returned HTTP 404, session_id=

raw file

Scenario 37 — memory_get_links bidirectional UNKNOWN

scenario-37.json (report)

          

raw file

scenario-37.log (console trace)
alice writes M1 + M2 + links M1→M2
  M1=41068003-acf0-4414-b17c-02b060932263 M2=027de38b-d567-44ad-b748-b2ef4cf261ce
settle 6s for link fanout
charlie queries /api/v1/links/M1 (forward)
Traceback (most recent call last):
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/37_get_links_bidirectional.py", line 82, in <module>
    main()
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/37_get_links_bidirectional.py", line 40, in main
    _, fwd = h.http_on(h.node3_ip, "GET", f"/api/v1/links/{m1}")
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 136, in http_on
    result = self.ssh_exec(node_ip, remote_cmd, timeout=timeout)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 78, in ssh_exec
    return subprocess.run(
           ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 550, in run
    stdout, stderr = process.communicate(input, timeout=timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 1209, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 2116, in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
  File "/usr/lib/python3.12/subprocess.py", line 1253, in _check_timeout
    raise TimeoutExpired(
subprocess.TimeoutExpired: Command '['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=10', '-o', 'ServerAliveInterval=5', 'root@167.99.59.68', "curl -sS -X GET http://127.0.0.1:9077/api/v1/links/41068003-acf0-4414-b17c-02b060932263 -H 'Content-Type: application/json'"]' timed out after 30 seconds

raw file

Scenario 38 — /export + /import FAIL

Reasons: destination count 0 < expected 5 | only 0/5 markers preserved

scenario-38.json (report)
{
	"agent_group": "ironclaw",
	"dst_ns": "scenario38-dst-81eb85",
	"expected_rows": 5,
	"export_http_code": 200,
	"import_http_code": 200,
	"markers_preserved": 0,
	"pass": false,
	"reason": "destination count 0 < expected 5; only 0/5 markers preserved",
	"reasons": [
		"destination count 0 < expected 5",
		"only 0/5 markers preserved"
	],
	"rows_exported": 171,
	"rows_in_destination": 0,
	"scenario": "38",
	"skipped": false,
	"src_ns": "scenario38-src-81eb85",
	"tls_mode": "off"
}

raw file

scenario-38.log (console trace)
alice writes 5 rows into scenario38-src-81eb85
settle 4s for pre-export replication
alice exports scenario38-src-81eb85 on node-1
  export returned HTTP 200, rows_exported=171
bob imports the payload into scenario38-dst-81eb85 on node-2
  import returned HTTP 200
settle 6s for import + fanout
verify row counts match on destination
  scenario38-dst-81eb85 has 0 rows (expected 5)
  markers preserved in destination: 0/5

raw file

Scenario 39 — /sync/since delta UNKNOWN

scenario-39.json (report)

          

raw file

scenario-39.log (console trace)
checkpoint = 1776821856412
suspending ai-memory on node-3
Traceback (most recent call last):
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/39_sync_since_delta.py", line 107, in <module>
    main()
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/39_sync_since_delta.py", line 34, in main
    h.ssh_exec(h.node3_ip, "pgrep -f 'ai-memory serve' | xargs -r kill -STOP", timeout=15)
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 78, in ssh_exec
    return subprocess.run(
           ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 550, in run
    stdout, stderr = process.communicate(input, timeout=timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 1209, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 2116, in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
  File "/usr/lib/python3.12/subprocess.py", line 1253, in _check_timeout
    raise TimeoutExpired(
subprocess.TimeoutExpired: Command '['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=10', '-o', 'ServerAliveInterval=5', 'root@167.99.59.68', "pgrep -f 'ai-memory serve' | xargs -r kill -STOP"]' timed out after 15 seconds

raw file

Scenario 40 — /memories/bulk UNKNOWN

scenario-40.json (report)

          

raw file

scenario-40.log (console trace)
constructing 500-row bulk payload
staging bulk payload on node-1 /tmp, then POST /api/v1/memories/bulk
  bulk POST returned HTTP 422
settle 20s for bulk fanout across 3 peers + aggregator
  node-2 count=0 (expected 500)
Traceback (most recent call last):
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/40_bulk_write.py", line 92, in <module>
    main()
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/40_bulk_write.py", line 65, in main
    _, resp = h.list_memories(ip, ns, limit=BULK_SIZE + 50)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 186, in list_memories
    return self.http_on(node_ip, "GET", f"/api/v1/memories?{q}")
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 136, in http_on
    result = self.ssh_exec(node_ip, remote_cmd, timeout=timeout)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 78, in ssh_exec
    return subprocess.run(
           ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 550, in run
    stdout, stderr = process.communicate(input, timeout=timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 1209, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 2116, in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
  File "/usr/lib/python3.12/subprocess.py", line 1253, in _check_timeout
    raise TimeoutExpired(
subprocess.TimeoutExpired: Command '['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=10', '-o', 'ServerAliveInterval=5', 'root@167.99.59.68', "curl -sS -X GET 'http://127.0.0.1:9077/api/v1/memories?namespace=scenario40-bulk-f0df71&limit=550' -H 'Content-Type: application/json'"]' timed out after 30 seconds

raw file

Scenario 41 — /metrics Prometheus UNKNOWN

scenario-41.json (report)

          

raw file

scenario-41.log (console trace)
scrape T0
  node-1 T0 parsed 7 memory counters
  node-2 T0 parsed 7 memory counters
Traceback (most recent call last):
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/41_metrics_prometheus.py", line 116, in <module>
    main()
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/41_metrics_prometheus.py", line 67, in main
    code, body = _scrape(h, ip)
                 ^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/41_metrics_prometheus.py", line 36, in _scrape
    r = h.ssh_exec(ip, cmd, timeout=30)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 78, in ssh_exec
    return subprocess.run(
           ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 550, in run
    stdout, stderr = process.communicate(input, timeout=timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 1209, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 2116, in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
  File "/usr/lib/python3.12/subprocess.py", line 1253, in _check_timeout
    raise TimeoutExpired(
subprocess.TimeoutExpired: Command '['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=10', '-o', 'ServerAliveInterval=5', 'root@167.99.59.68', "curl -sS -o /tmp/s41-metrics.txt -w '%{http_code}' http://127.0.0.1:9077/api/v1/metrics"]' timed out after 30 seconds

raw file

Scenario 42 — /namespaces enumeration UNKNOWN

scenario-42.json (report)

          

raw file

scenario-42.log (console trace)
alice writes into 3 distinct namespaces: ['scenario42-dfa23f-0', 'scenario42-dfa23f-1', 'scenario42-dfa23f-2']
settle 10s for namespace index fanout
  node-1 sees 3/3 target namespaces, counts: {'scenario42-dfa23f-0': 2, 'scenario42-dfa23f-1': 2, 'scenario42-dfa23f-2': 2}
  node-2 sees 3/3 target namespaces, counts: {'scenario42-dfa23f-0': 2, 'scenario42-dfa23f-1': 2, 'scenario42-dfa23f-2': 2}
Traceback (most recent call last):
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/42_namespaces_enumeration.py", line 73, in <module>
    main()
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/scenarios/42_namespaces_enumeration.py", line 37, in main
    _, resp = h.http_on(ip, "GET", "/api/v1/namespaces?limit=200")
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 136, in http_on
    result = self.ssh_exec(node_ip, remote_cmd, timeout=timeout)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/ai-memory-ai2ai-gate/ai-memory-ai2ai-gate/scripts/a2a_harness.py", line 78, in ssh_exec
    return subprocess.run(
           ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 550, in run
    stdout, stderr = process.communicate(input, timeout=timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 1209, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/subprocess.py", line 2116, in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
  File "/usr/lib/python3.12/subprocess.py", line 1253, in _check_timeout
    raise TimeoutExpired(
subprocess.TimeoutExpired: Command '['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=10', '-o', 'ServerAliveInterval=5', 'root@167.99.59.68', "curl -sS -X GET 'http://127.0.0.1:9077/api/v1/namespaces?limit=200' -H 'Content-Type: application/json'"]' timed out after 30 seconds

raw file

All artifacts