../ runs index

Campaign a2a-ironclaw-v0.6.3-rc1-r3 FAIL

Agent group
ironclaw (homogeneous)
ai-memory ref
release/v0.6.3
Completed at
2026-04-27T17:14:43Z
Overall pass
false
Skipped reports
0

Infrastructure

Provider
digitalocean
Region
nyc3
Droplet size
s-2vcpu-4gb
Topology
4-node federation mesh (W=2/N=4)
Scenarios started
2026-04-27T16:56:30Z
Scenarios ended
2026-04-27T17:14:42Z
Dispatched by
alphaonedev
Harness SHA
1ffd755cee87
Workflow run
https://github.com/alphaonedev/ai-memory-ai2ai-gate/actions/runs/25007946890

Node roster

#RoleAgent IDPublic IPPrivate IP
1agentai:alice167.99.58.16910.10.0.3
2agentai:bob104.131.6.19810.10.0.4
3agentai:charlie159.89.39.4310.10.0.5
4memory-only167.71.243.4510.10.0.2

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.0c5747cd50f25PASS
node-2ai:bobironclaw ironclaw 0.26.07a30e095f432PASS
node-3ai:charlieironclaw ironclaw 0.26.074e57efa0d1bPASS
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": "v0.6.3",
			"peer_urls": "http://10.10.0.4:9077,http://10.10.0.5:9077,http://10.10.0.2:9077",
			"config_file_sha256": "c5747cd50f25d709ccb1c90dc28b1f3bf9f72dd2f9a31178ec1603848caed9d4",
			"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": "48384d73-52a0-4ea0-86c5-7c3ef0766bae",
				"agent_mcp_canary_f2b": false,
				"agent_mcp_canary_uuid": "a377718e-d79e-4a3e-acf4-a35d5f143166",
				"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.10.0.4:9077:OK,10.10.0.5:9077:OK,10.10.0.2: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_check_duplicate,memory_consolidate,memory_delete,memory_detect_contradiction,memory_entity_get_by_alias,memory_entity_register,memory_expand_query,memory_forget,memory_gc,memory_get,memory_get_links,memory_get_taxonomy,memory_inbox,memory_kg_invalidate,memory_kg_query,memory_kg_timeline,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.",
				"embedder_loaded_f8": true,
				"embedder_loaded_f8_reason": "",
				"_f8_note": "F8 verifies /api/v1/capabilities reports features.embedder_loaded=true — i.e. the MiniLM embedder initialised at serve startup. Gates baseline_pass unconditionally. Without this, scenario-18 silently black-holes (semantic recall returns 0 rows).",
				"agent_mcp_ai_memory_canary": true,
				"canary_uuid": "48384d73-52a0-4ea0-86c5-7c3ef0766bae",
				"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": "v0.6.3",
			"peer_urls": "http://10.10.0.3:9077,http://10.10.0.5:9077,http://10.10.0.2:9077",
			"config_file_sha256": "7a30e095f432296575ecd54f75c2f9fb95e216a20acf8b007db986ca51c0c716",
			"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": "21c3c45d-f913-4540-8774-231ccc42315a",
				"agent_mcp_canary_f2b": false,
				"agent_mcp_canary_uuid": "14400eea-a38e-44b8-9708-d15182eae2dc",
				"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.10.0.3:9077:OK,10.10.0.5:9077:OK,10.10.0.2: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_check_duplicate,memory_consolidate,memory_delete,memory_detect_contradiction,memory_entity_get_by_alias,memory_entity_register,memory_expand_query,memory_forget,memory_gc,memory_get,memory_get_links,memory_get_taxonomy,memory_inbox,memory_kg_invalidate,memory_kg_query,memory_kg_timeline,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.",
				"embedder_loaded_f8": true,
				"embedder_loaded_f8_reason": "",
				"_f8_note": "F8 verifies /api/v1/capabilities reports features.embedder_loaded=true — i.e. the MiniLM embedder initialised at serve startup. Gates baseline_pass unconditionally. Without this, scenario-18 silently black-holes (semantic recall returns 0 rows).",
				"agent_mcp_ai_memory_canary": true,
				"canary_uuid": "21c3c45d-f913-4540-8774-231ccc42315a",
				"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": "v0.6.3",
			"peer_urls": "http://10.10.0.3:9077,http://10.10.0.4:9077,http://10.10.0.2:9077",
			"config_file_sha256": "74e57efa0d1b430f5895493d8a1ad983a07954d1c6888ed324f22eb98cc6fc3c",
			"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": "293c6812-c3d2-40aa-9fe5-b377089b41b5",
				"agent_mcp_canary_f2b": false,
				"agent_mcp_canary_uuid": "ad87fa29-451b-496d-8639-92c8f75a30e8",
				"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.10.0.3:9077:OK,10.10.0.4:9077:OK,10.10.0.2: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_check_duplicate,memory_consolidate,memory_delete,memory_detect_contradiction,memory_entity_get_by_alias,memory_entity_register,memory_expand_query,memory_forget,memory_gc,memory_get,memory_get_links,memory_get_taxonomy,memory_inbox,memory_kg_invalidate,memory_kg_query,memory_kg_timeline,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.",
				"embedder_loaded_f8": true,
				"embedder_loaded_f8_reason": "",
				"_f8_note": "F8 verifies /api/v1/capabilities reports features.embedder_loaded=true — i.e. the MiniLM embedder initialised at serve startup. Gates baseline_pass unconditionally. Without this, scenario-18 silently black-holes (semantic recall returns 0 rows).",
				"agent_mcp_ai_memory_canary": true,
				"canary_uuid": "293c6812-c3d2-40aa-9fe5-b377089b41b5",
				"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 0bc79eef-1124-4a3a-a09e-a85e6dbc0346 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": "0bc79eef-1124-4a3a-a09e-a85e6dbc0346",
	"canary_namespace": "_baseline_peer_canary",
	"writer_agent": "ai:alice",
	"pass": true
}

raw file

Run focus

Core memory sharing passes, advanced KG/entity features fail in rc1

What this campaign tested: Tested 45 scenarios exercising memory write/read/delete/link/recall/consolidate across HTTP transport in 4-node federation, covering primitives like versioning, promotion, hybrid search, and KG operations.

What it demonstrated: Proved reliable basic sharing and recall in 37 scenarios, but exposed bugs in advanced features like taxonomy, KG invalidation, timelines, entity aliases, duplicate detection, and memory lifecycle.

AI NHI analysis · Claude Opus 4.7

Core memory sharing passes, advanced KG/entity features fail in rc1

FAIL — 37/45 green, 6 red (S44-49), 2 skipped

For three audiences

Non-technical end users

The AI agents can reliably share and remember simple information with each other across the network. However, more advanced ways of organizing, linking, or managing those memories don't work correctly yet. This means the system is okay for basic uses but needs improvements for complex tasks.

C-level decision makers

Core federation stable with low risk for basic sharing claims; advanced KG/entity features not production-ready, posing high deployment risk. Customer-facing viability limited to semantic tier basics; failures indicate regression or incomplete impl in v0.6.3-rc1 vs prior stability expectations. Prioritize fixes to unblock full feature set.

Engineers & architects

Failures isolate to advanced primitives: S44 taxonomy missing subtree_count and node location; S45 kg_invalidate 400 with no edges; S46 timeline missing add/invalidate events; S47 entity alias resolutions all 404; S48 check_duplicate 422 with no matches/scores; S49 lifecycle ops like promote/expire/archive/restore/purge mostly 404 or ineffective. Probable root cause is incomplete KG/entity/lifecycle support in v0.6.3-rc1 federation mode. Skips S50/51 due to missing sqlcipher and autonomous tier builds.

What changes going into the next campaign

Apply patches for KG, entity, duplicate, lifecycle, and taxonomy bugs before re-running failed scenarios.

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)PASS
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 registrationPASS
S13Concurrent write contentionPASS
S14Partition tolerancePASS
S15Read-your-writesPASS
S16Tier promotionPASS
S17Stats consistencyPASS
S18Semantic query expansionPASS
S22Identity spoofing resistancePASS
S23Malicious content fuzzPASS
S24Byzantine peerPASS
S25Clock skew tolerancePASS
S28memory_search keywordPASS
S29memory_archive lifecyclePASS
S30memory_capabilities handshakePASS
S31memory_gc quiescencePASS
S32memory_inbox + notifyPASS
S33memory_subscribe pub/subPASS
S34memory_pending governancePASS
S35memory_namespace standardsPASS
S36memory_session_startPASS
S37memory_get_links bidirectionalPASS
S38/export + /importPASS
S39/sync/since deltaPASS
S40/memories/bulkPASS
S41/metrics PrometheusPASS
S42/namespaces enumerationPASS
S43scenario-43PASS
S44scenario-44?could not locate scenario44-9736d6/alphaone in taxonomy response; root node missing subtree_count field — v0.6.3 should expose it
S45scenario-45?kg_invalidate returned HTTP 400; as_of=past missing edges; expected all 3 targets, got 0; as_of=now expected 2 edges, got 0
S46scenario-46?expected >=3 events (2 adds + 1 invalidate), got 0; no edge_added event in timeline; no edge_invalidated event in timeline
S47scenario-47?by-alias('a1-project') HTTP 404; by-alias('alphaone-proj') HTTP 404; by-alias('alpha1-proj') HTTP 404; by-alias('ao-project') HTTP 404
S48scenario-48?check_duplicate returned HTTP 422; check_duplicate returned 0 matches for a near-identical input; original memory (5f913f4e-d905-4199-87d9-7859d5028318) absent from matches; match did not carry a simi
S49scenario-49?access: access_count not incremented; promote: HTTP 404; promote: tier=None, expected 'long'; expire: HTTP 404; archive: M1 not visible in /api/v1/archive listing; restore: HTTP 404; purge: HTTP 404
S50scenario-50SKIPsqlcipher feature not advertised in /api/v1/capabilities — daemon was not built with --features sqlcipher
S51scenario-51SKIPautonomous/smart tier not available on node-1 — tier='semantic' models={'cross_encoder': 'none', 'embedding': 'sentence-transformers/all-MiniLM-L6-v2', 'embedding_dim': 384, 'llm': 'none'}

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

scenario-1.json (report)
{
	"agent_group": "ironclaw",
	"expected_per_reader": 20,
	"pass": true,
	"per_agent": {
		"ai:alice": {
			"recall": 20
		},
		"ai:bob": {
			"recall": 20
		},
		"ai:charlie": {
			"recall": 20
		}
	},
	"per_namespace_node4": {
		"scenario1-ai:alice": {
			"count": 10,
			"wrong_agent_id": 0
		},
		"scenario1-ai:bob": {
			"count": 10,
			"wrong_agent_id": 0
		},
		"scenario1-ai:charlie": {
			"count": 10,
			"wrong_agent_id": 0
		}
	},
	"reasons": [],
	"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 167.99.58.169
  ai:bob on 104.131.6.198
  ai:charlie on 159.89.39.43
settle 15s for W=2/N=4 convergence
phase B: each agent counts rows in the OTHER two namespaces
  ai:alice recalled 20 rows from the other two namespaces
  ai:bob recalled 20 rows from the other two namespaces
  ai:charlie recalled 20 rows from the other two namespaces
phase C: cross-cluster identity check on node-4
  ns=scenario1-ai:alice count=10 wrong_agent_id=0
  ns=scenario1-ai:bob count=10 wrong_agent_id=0
  ns=scenario1-ai:charlie count=10 wrong_agent_id=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 167.99.58.169
  ai:bob on 104.131.6.198
  ai:charlie on 159.89.39.43
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-8d81de8f958f4dc28cb97420f1a2786b",
	"agent_group": "ironclaw",
	"handoff_uuid": "h-802823b391764aadaba5441bdf76e5c7",
	"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-802823b391764aadaba5441bdf76e5c7)
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-8d81de8f958f4dc28cb97420f1a2786b)
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": "d49a3b2a-2935-41c7-9e3b-b4bfa9d84e90",
	"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 167.99.58.169
  ai:bob on 104.131.6.198
  ai:charlie on 159.89.39.43
settle 8s for quorum fanout
phase B: collect source ids on node-1, then trigger consolidate
  source ids (count=9): ['436c7ef4-b00d-4465-aeec-c188744c2874', 'a67c9d6d-8426-43c9-af1a-54bf62aa78e5', 'd367e665-8071-4e3b-846c-8af33691f803', '5e645b00-f47c-4673-bb77-3cef227eb575', '2dd0b253-39f2-49d7-9702-de7ba974c2fb']...
  consolidate HTTP 201, consolidated_id=d49a3b2a-2935-41c7-9e3b-b4bfa9d84e90
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": "55ff4daf-ab0c-4f66-b592-06377918d1dc",
	"bob_id": "20f7ac34-c2c1-4fb5-989b-e4a84b006c03",
	"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-ab3cf6d7"
}

raw file

scenario-6.log (console trace)
alice writes claim: "sky-color-ab3cf6d7 is blue" on node-1
bob writes contradicting claim: "sky-color-ab3cf6d7 is red" on node-2
  alice.id=55ff4daf-ab0c-4f66-b592-06377918d1dc bob.id=20f7ac34-c2c1-4fb5-989b-e4a84b006c03
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-d8b1969f865041698d524713a7b3edcf"
	},
	"m1_id": "0b8e0103-c7c5-4686-a6e2-bb1fb3af97f0",
	"pass": true,
	"put_http_code": 200,
	"reasons": [],
	"scenario": "9",
	"skipped": false,
	"tls_mode": "off",
	"v1_uuid": "v1-1c4055e491374a5a8a1138a10f88cdc6",
	"v2_uuid": "v2-d8b1969f865041698d524713a7b3edcf"
}

raw file

scenario-9.log (console trace)
alice writes M1 content=v1-1c4055e491374a5a8a1138a10f88cdc6 on node-1
  M1 id=0b8e0103-c7c5-4686-a6e2-bb1fb3af97f0
settle 5s for initial replication
bob updates M1 content=v2-d8b1969f865041698d524713a7b3edcf 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-d8b1969f865041698d524713a7b3edcf" agent_id="ai:alice"

raw file

Scenario 10 — Deletion propagation PASS

scenario-10.json (report)
{
	"agent_group": "ironclaw",
	"delete_http_code": 200,
	"m1_id": "9911ab1c-d512-4c18-8e0a-d983de611011",
	"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-99449ac13a1e433cb00df1ddcdf13b49"
}

raw file

scenario-10.log (console trace)
alice writes M1 content=d-99449ac13a1e433cb00df1ddcdf13b49 on node-1
  created memory id=9911ab1c-d512-4c18-8e0a-d983de611011
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": "ea1fe68b-5f8d-4fbe-99e2-e38584540eda",
	"m2_id": "e837ae37-a87f-4ad1-a8a4-b0c884c8b583",
	"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=ea1fe68b-5f8d-4fbe-99e2-e38584540eda M2=e837ae37-a87f-4ad1-a8a4-b0c884c8b583
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 PASS

scenario-12.json (report)
{
	"agent_group": "ironclaw",
	"pass": true,
	"peers_see": {
		"node_2": 1,
		"node_3": 1,
		"node_4": 1
	},
	"reasons": [],
	"register_http_code": 201,
	"registered_agent": "ai:dave-probe-fe0fcfe0",
	"scenario": "12",
	"skipped": false,
	"tls_mode": "off"
}

raw file

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

raw file

Scenario 13 — Concurrent write contention PASS

scenario-13.json (report)
{
	"agent_group": "ironclaw",
	"m1_id": "2e948ea3-3aa6-4766-8534-359f968a8ba0",
	"pass": true,
	"peer_view": {
		"node_1": "va-0582db94426e408baa7ea3b96b5b0534",
		"node_2": "va-0582db94426e408baa7ea3b96b5b0534",
		"node_3": "va-0582db94426e408baa7ea3b96b5b0534",
		"node_4": "va-0582db94426e408baa7ea3b96b5b0534"
	},
	"reasons": [],
	"scenario": "13",
	"skipped": false,
	"submitted": {
		"v0": "v0-3d643be00ae14868bf427e2f761789ae",
		"vA_alice": "va-0582db94426e408baa7ea3b96b5b0534",
		"vB_bob": "vb-84726d29b9bb45f598f7442c65753523"
	},
	"tls_mode": "off"
}

raw file

scenario-13.log (console trace)
alice writes M1 content=v0-3d643be00ae14868bf427e2f761789ae on node-1
  M1 id=2e948ea3-3aa6-4766-8534-359f968a8ba0
settle 5s for initial replication
alice + bob issue concurrent PUTs (vA=va-0582db94426e408baa7ea3b96b5b0534 from alice, vB=vb-84726d29b9bb45f598f7442c65753523 from bob)
  concurrent PUT results: [(0, {'body': {'access_count': 0, 'confidence': 1.0, 'content': 'va-0582db94426e408baa7ea3b96b5b0534', 'created_at': '2026-04-27T17:02:20.240442423+00:00', 'expires_at': '2026-05-04T17:02:20.240442423+00:00', 'id': '2e948ea3-3aa6-4766-8534-359f968a8ba0', 'metadata': {'agent_id': 'ai:alice', 'scenario': '13'}, 'namespace': 'scenario13-contention', 'priority': 5, 'source': 'api', 'tags': [], 'tier': 'mid', 'title': 'm1', 'updated_at': '2026-04-27T17:02:26.429393618+00:00'}, 'http_code': 200}), (0, {'body': {'access_count': 0, 'confidence': 1.0, 'content': 'vb-84726d29b9bb45f598f7442c65753523', 'created_at': '2026-04-27T17:02:20.240442423+00:00', 'expires_at': '2026-05-04T17:02:20.240442423+00:00', 'id': '2e948ea3-3aa6-4766-8534-359f968a8ba0', 'metadata': {'agent_id': 'ai:alice', 'scenario': '13'}, 'namespace': 'scenario13-contention', 'priority': 5, 'source': 'api', 'tags': [], 'tier': 'mid', 'title': 'm1', 'updated_at': '2026-04-27T17:02:26.405231279+00:00'}, 'http_code': 200})]
settle 10s for quorum convergence
  node-1 sees content=va-0582db94426e408baa7ea3b96b5b0534
  node-2 sees content=va-0582db94426e408baa7ea3b96b5b0534
  node-3 sees content=va-0582db94426e408baa7ea3b96b5b0534
  node-4 sees content=va-0582db94426e408baa7ea3b96b5b0534

raw file

Scenario 14 — Partition tolerance PASS

scenario-14.json (report)
{
	"agent_group": "ironclaw",
	"expected_post_recovery": 20,
	"node3_saw": 20,
	"partition_target": "node-3",
	"pass": true,
	"reasons": [],
	"scenario": "14",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-14.log (console trace)
suspending ai-memory on node-3 (SIGSTOP)
  !! ssh timeout (15s): root@159.89.39.43 pgrep -f 'ai-memory serve' | xargs -r kill -STOP
settle 2s for process-suspend observe
writing 10 memories each from alice + bob during node-3 outage
resuming ai-memory on node-3 (SIGCONT)
settle 20s for post-partition catchup
checking node-3 caught up
  node-3 sees 20 memories in scenario14-partition (expected 20)

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-90980926cb064caca261e2de8313c64a",
	"writer_sees_own_write": 1
}

raw file

scenario-15.log (console trace)
alice writes + immediately reads M1 on node-1 (uuid=ryw-90980926cb064caca261e2de8313c64a)
  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": "c8d3b8ae-0516-4496-b51a-f788cae30203",
	"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=c8d3b8ae-0516-4496-b51a-f788cae30203
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 PASS

scenario-17.json (report)
{
	"agent_group": "ironclaw",
	"expected_count": 15,
	"pass": true,
	"per_peer": {
		"node_1": 15,
		"node_2": 15,
		"node_3": 15,
		"node_4": 15
	},
	"reasons": [],
	"scenario": "17",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-17.log (console trace)
phase A: each of 3 agents writes 5 memories to scenario17-stats
  ai:alice on 167.99.58.169
  ai:bob on 104.131.6.198
  ai:charlie on 159.89.39.43
settle 15s for W=2 fanout
phase B: querying count on every peer
  node-1 count=15 (expected 15)
  node-2 count=15 (expected 15)
  node-3 count=15 (expected 15)
  node-4 count=15 (expected 15)

raw file

Scenario 18 — Semantic query expansion PASS

scenario-18.json (report)
{
	"agent_group": "ironclaw",
	"diag_list_alice_present": 1,
	"diag_list_bob_present": 1,
	"diag_node3_embedding_probe": "dawn-walk|1536|BYTES | ridge-strides|1536|BYTES",
	"pass": true,
	"query": "morning outdoor exercise routine",
	"reasons": [],
	"recall_mode": "hybrid",
	"rows_in_recall": 2,
	"scenario": "18",
	"skipped": false,
	"tls_mode": "off",
	"writers": [
		{
			"agent": "ai:alice",
			"marker": "alice-sunrise-000ceb01",
			"seen_by_charlie": 1
		},
		{
			"agent": "ai:bob",
			"marker": "bob-daybreak-ba5ef226",
			"seen_by_charlie": 1
		}
	]
}

raw file

scenario-18.log (console trace)
alice writes A on node-1
bob writes B on node-2
polling node-3 for both writes to propagate (max 30 s)
  both writes visible after 1 s
settle 3s for embedder + HNSW catch-up
  node-3 DB embedding probe: 'dawn-walk|1536|BYTES | ridge-strides|1536|BYTES'
charlie queries on node-3 with semantically-related prompt
  recall mode=hybrid returned 2 rows
  charlie sees alice's memory: 1 (expected >=1)
  charlie sees bob's memory: 1 (expected >=1)

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 PASS

scenario-23.json (report)
{
	"agent_group": "ironclaw",
	"pass": true,
	"payloads": {
		"html": {
			"input_bytes": 66,
			"roundtrip_bytes": 66,
			"write_http": 201
		},
		"oversize": {
			"input_bytes": 1048576,
			"roundtrip_bytes": 0,
			"write_http": 400
		},
		"sql": {
			"input_bytes": 61,
			"roundtrip_bytes": 61,
			"write_http": 201
		},
		"unicode": {
			"input_bytes": 19,
			"roundtrip_bytes": 19,
			"write_http": 201
		}
	},
	"payloads_note": "accept+faithful OR 4xx reject both acceptable for oversize",
	"reasons": [],
	"scenario": "23",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-23.log (console trace)
payload sql: 61 bytes
payload html: 66 bytes
payload oversize: 1048576 bytes
  oversize: server rejected oversize with HTTP 400 (acceptable)
payload unicode: 19 bytes

raw file

Scenario 24 — Byzantine peer PASS

scenario-24.json (report)
{
	"agent_group": "ironclaw",
	"byzantine_marker": "bz-f98a1bc10c854e3e9c79c9ded9e8f87b",
	"pass": true,
	"reasons": [],
	"scenario": "24",
	"skipped": false,
	"stored_metadata_agent_id": "REJECTED_BY_SERVER",
	"sync_push_http_code": "422",
	"tls_mode": "off"
}

raw file

scenario-24.log (console trace)
node-2 sends sync_push to node-3 claiming sender_agent_id=ai:alice
  sync_push returned HTTP 422
settle 5s for server-side sync apply
  node-3 stored metadata.agent_id=ABSENT (declared: ai:alice)
  sync_push rejected HTTP 422 — stricter-than-spec, acceptable

raw file

Scenario 25 — Clock skew tolerance PASS

scenario-25.json (report)
{
	"agent_group": "ironclaw",
	"clock_offset_seconds": 300,
	"marker": "ck-4640ba743d2e4a559f61e4fa8a4ce9cb",
	"pass": true,
	"reasons": [],
	"scenario": "25",
	"seen_on": {
		"node_1": 1,
		"node_3": 1
	},
	"skipped": false,
	"target_node": "node-3",
	"tls_mode": "off"
}

raw file

scenario-25.log (console trace)
shifting node-3 clock +300s (NTP disabled for the duration)
  node-3 now reports: Mon Apr 27 17:10:14 UTC 2026
alice writes on node-1 (normal clock); waiting for quorum fanout to skewed node-3
settle 15s for skewed-peer convergence
  node-3 (+300s clock) sees marker: 1 (expected >=1)
  node-1 sees marker: 1 (expected >=1)
reverting node-3 clock

raw file

Scenario 28 — memory_search keyword PASS

scenario-28.json (report)
{
	"agent_group": "ironclaw",
	"pass": true,
	"peer_hits": {
		"node_2": 1,
		"node_3": 1
	},
	"reasons": [],
	"scenario": "28",
	"skipped": false,
	"tls_mode": "off",
	"token": "kwsearch531fa80feb"
}

raw file

scenario-28.log (console trace)
alice writes a row containing unique token=kwsearch531fa80feb
settle 8s for search index populate + fanout
bob + charlie call /api/v1/search with the exact token
  node-2 keyword search returned 1 hits
  node-3 keyword search returned 1 hits

raw file

Scenario 29 — memory_archive lifecycle PASS

scenario-29.json (report)
{
	"agent_group": "ironclaw",
	"archive_http_code": 200,
	"bob_sees_archived": true,
	"m1_id": "79fa161d-498b-4d20-9628-42dc0d7e602a",
	"node4_active_rows": 1,
	"pass": true,
	"reasons": [],
	"restore_http_code": 200,
	"scenario": "29",
	"skipped": false,
	"stats_shape_ok": true,
	"tls_mode": "off"
}

raw file

scenario-29.log (console trace)
alice writes M1 on node-1
  M1 id=79fa161d-498b-4d20-9628-42dc0d7e602a
settle 5s for pre-archive replication
alice archives M1 via POST /api/v1/archive (ai-memory-mcp PR #361)
  archive (POST) returned HTTP 200
settle 5s for archive propagation
bob queries /api/v1/archive on node-2
  bob sees M1 in archive: True
charlie restores M1 via /api/v1/archive/{id}/restore on node-3
  restore returned HTTP 200
settle 5s for restore propagation
node-4 aggregator: M1 must be active again
  node-4 active rows matching marker: 1
fetch /api/v1/archive/stats on node-4

raw file

Scenario 30 — memory_capabilities handshake PASS

scenario-30.json (report)
{
	"agent_group": "ironclaw",
	"pass": true,
	"peer_views": {
		"node_1": {
			"_path": "/api/v1/capabilities",
			"approval": {
				"default_timeout_seconds": 30,
				"pending_requests": 0,
				"subscribers": 0
			},
			"compaction": {
				"enabled": false,
				"interval_minutes": null,
				"last_run_at": null,
				"last_run_stats": null
			},
			"features": {
				"auto_consolidation": false,
				"auto_tagging": false,
				"contradiction_analysis": false,
				"cross_encoder_reranking": false,
				"embedder_loaded": true,
				"hybrid_recall": true,
				"keyword_search": true,
				"memory_reflection": false,
				"query_expansion": false,
				"semantic_search": true
			},
			"hooks": {
				"by_event": {},
				"registered_count": 0
			},
			"models": {
				"cross_encoder": "none",
				"embedding": "sentence-transformers/all-MiniLM-L6-v2",
				"embedding_dim": 384,
				"llm": "none"
			},
			"permissions": {
				"active_rules": 0,
				"mode": "ask",
				"rule_summary": []
			},
			"schema_version": "2",
			"tier": "semantic",
			"transcripts": {
				"enabled": false,
				"total_count": 0,
				"total_size_mb": 0
			},
			"version": "0.6.3-rc1"
		},
		"node_2": {
			"_path": "/api/v1/capabilities",
			"approval": {
				"default_timeout_seconds": 30,
				"pending_requests": 0,
				"subscribers": 0
			},
			"compaction": {
				"enabled": false,
				"interval_minutes": null,
				"last_run_at": null,
				"last_run_stats": null
			},
			"features": {
				"auto_consolidation": false,
				"auto_tagging": false,
				"contradiction_analysis": false,
				"cross_encoder_reranking": false,
				"embedder_loaded": true,
				"hybrid_recall": true,
				"keyword_search": true,
				"memory_reflection": false,
				"query_expansion": false,
				"semantic_search": true
			},
			"hooks": {
				"by_event": {},
				"registered_count": 0
			},
			"models": {
				"cross_encoder": "none",
				"embedding": "sentence-transformers/all-MiniLM-L6-v2",
				"embedding_dim": 384,
				"llm": "none"
			},
			"permissions": {
				"active_rules": 0,
				"mode": "ask",
				"rule_summary": []
			},
			"schema_version": "2",
			"tier": "semantic",
			"transcripts": {
				"enabled": false,
				"total_count": 0,
				"total_size_mb": 0
			},
			"version": "0.6.3-rc1"
		},
		"node_3": {
			"_path": "/api/v1/capabilities",
			"approval": {
				"default_timeout_seconds": 30,
				"pending_requests": 0,
				"subscribers": 0
			},
			"compaction": {
				"enabled": false,
				"interval_minutes": null,
				"last_run_at": null,
				"last_run_stats": null
			},
			"features": {
				"auto_consolidation": false,
				"auto_tagging": false,
				"contradiction_analysis": false,
				"cross_encoder_reranking": false,
				"embedder_loaded": true,
				"hybrid_recall": true,
				"keyword_search": true,
				"memory_reflection": false,
				"query_expansion": false,
				"semantic_search": true
			},
			"hooks": {
				"by_event": {},
				"registered_count": 0
			},
			"models": {
				"cross_encoder": "none",
				"embedding": "sentence-transformers/all-MiniLM-L6-v2",
				"embedding_dim": 384,
				"llm": "none"
			},
			"permissions": {
				"active_rules": 0,
				"mode": "ask",
				"rule_summary": []
			},
			"schema_version": "2",
			"tier": "semantic",
			"transcripts": {
				"enabled": false,
				"total_count": 0,
				"total_size_mb": 0
			},
			"version": "0.6.3-rc1"
		},
		"node_4": {
			"_path": "/api/v1/capabilities",
			"approval": {
				"default_timeout_seconds": 30,
				"pending_requests": 0,
				"subscribers": 0
			},
			"compaction": {
				"enabled": false,
				"interval_minutes": null,
				"last_run_at": null,
				"last_run_stats": null
			},
			"features": {
				"auto_consolidation": false,
				"auto_tagging": false,
				"contradiction_analysis": false,
				"cross_encoder_reranking": false,
				"embedder_loaded": true,
				"hybrid_recall": true,
				"keyword_search": true,
				"memory_reflection": false,
				"query_expansion": false,
				"semantic_search": true
			},
			"hooks": {
				"by_event": {},
				"registered_count": 0
			},
			"models": {
				"cross_encoder": "none",
				"embedding": "sentence-transformers/all-MiniLM-L6-v2",
				"embedding_dim": 384,
				"llm": "none"
			},
			"permissions": {
				"active_rules": 0,
				"mode": "ask",
				"rule_summary": []
			},
			"schema_version": "2",
			"tier": "semantic",
			"transcripts": {
				"enabled": false,
				"total_count": 0,
				"total_size_mb": 0
			},
			"version": "0.6.3-rc1"
		}
	},
	"reasons": [],
	"scenario": "30",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-30.log (console trace)
  node-1 capabilities: ['approval', 'compaction', 'features', 'hooks', 'models', 'permissions', 'schema_version', 'tier', 'transcripts', 'version', '_path']
  node-2 capabilities: ['approval', 'compaction', 'features', 'hooks', 'models', 'permissions', 'schema_version', 'tier', 'transcripts', 'version', '_path']
  node-3 capabilities: ['approval', 'compaction', 'features', 'hooks', 'models', 'permissions', 'schema_version', 'tier', 'transcripts', 'version', '_path']
  node-4 capabilities: ['approval', 'compaction', 'features', 'hooks', 'models', 'permissions', 'schema_version', 'tier', 'transcripts', 'version', '_path']

raw file

Scenario 31 — memory_gc quiescence PASS

scenario-31.json (report)
{
	"agent_group": "ironclaw",
	"expected_live": 2,
	"forget_http_code": 400,
	"gc_http_code": 200,
	"live_markers_per_peer": {
		"node_1": 2,
		"node_2": 2,
		"node_3": 2,
		"node_4": 2
	},
	"pass": true,
	"reasons": [],
	"scenario": "31",
	"skipped": false,
	"tls_mode": "off"
}

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
  node-3 sees 2/2 live markers
  node-4 sees 2/2 live markers

raw file

Scenario 32 — memory_inbox + notify PASS

scenario-32.json (report)
{
	"agent_group": "ironclaw",
	"bob_inbox_count": 1,
	"bob_sees_marker": true,
	"charlie_inbox_count": 0,
	"charlie_sees_marker": false,
	"marker": "inb-6aa83dd038cb40c5be95ebe802717f1d",
	"notify_http_code": 201,
	"pass": true,
	"reasons": [],
	"scenario": "32",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-32.log (console trace)
alice calls /api/v1/notify → target=ai:bob
  notify returned HTTP 201
settle 6s for notification fanout
bob queries his inbox on node-2
  bob inbox has 1 messages; sees marker: True
charlie queries his inbox on node-3 (must NOT see it)
  charlie inbox has 0 messages; sees marker: False

raw file

Scenario 33 — memory_subscribe pub/sub PASS

scenario-33.json (report)
{
	"agent_group": "ironclaw",
	"m1_delivered": 1,
	"namespace": "scenario33-pubsub-fb6e70",
	"ns_in_subs_after": false,
	"ns_in_subs_before": true,
	"pass": true,
	"reasons": [],
	"scenario": "33",
	"skipped": false,
	"subscribe_http_code": 201,
	"subscriptions_after_count": 0,
	"subscriptions_before_count": 1,
	"tls_mode": "off",
	"unsubscribe_http_code": 200
}

raw file

scenario-33.log (console trace)
bob subscribes to namespace scenario33-pubsub-fb6e70 on node-2
  subscribe returned HTTP 201
settle 2s for subscription settle
  bob subscriptions: 1 entries; contains ns: True
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-fb6e70
  unsubscribe returned HTTP 200
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 PASS

scenario-34.json (report)
{
	"agent_group": "ironclaw",
	"approve_http_code": 200,
	"charlie_sees": {
		"approved": 1,
		"rejected": 0
	},
	"namespace": "scenario34-pending-a1ab45",
	"pass": true,
	"pending_queue_count": 2,
	"reasons": [],
	"reject_http_code": 200,
	"scenario": "34",
	"set_standard_http_code": 201,
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-34.log (console trace)
alice sets namespace standard on scenario34-pending-a1ab45: write=approve, approver=ai:bob
  set-standard returned HTTP 201
settle 2s for standard settle
alice writes two memories into the governed namespace (should land in pending)
  p1=7dd19679-a5b1-4ad3-969a-d929bb60ac3b p2=58eb0ca4-8552-450c-9e85-041ae14f9a2e
settle 4s for pending queue settle
bob lists pending on node-2
  pending queue has 2 entries
bob approves p1, rejects p2
  approve HTTP 200; reject HTTP 200
settle 5s for decision fanout
charlie reads the namespace — expects ONLY approved marker
  charlie sees approved=1 rejected=0

raw file

Scenario 35 — memory_namespace standards PASS

scenario-35.json (report)
{
	"agent_group": "ironclaw",
	"child_ns": "scenario35-parent-e546bf/child",
	"clear_http_code": 200,
	"get_standard_http_code": 200,
	"parent_ns": "scenario35-parent-e546bf",
	"pass": true,
	"post_clear_has_child_rule": false,
	"reasons": [],
	"scenario": "35",
	"sees_child_rule": true,
	"sees_parent_rule": true,
	"set_child_http_code": 201,
	"set_parent_http_code": 201,
	"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-e546bf
  set-parent returned HTTP 201
alice writes child-standard-memory on node-1
alice sets namespace standard on scenario35-parent-e546bf/child with parent=scenario35-parent-e546bf
  set-child returned HTTP 201
settle 4s for standard fanout
bob gets standard for scenario35-parent-e546bf/child on node-2 (expects layered parent+child)
  get-standard returned HTTP 200
  parent-rule visible=True; child-rule visible=True
alice clears standard on scenario35-parent-e546bf/child
  clear returned HTTP 200
settle 3s for clear settle

raw file

Scenario 36 — memory_session_start PASS

scenario-36.json (report)
{
	"agent_group": "ironclaw",
	"pass": true,
	"reasons": [],
	"scenario": "36",
	"session_id": "f78a549e-db9a-4fdf-9a91-f59fdffc92c2",
	"session_tagged_rows_on_bob": 2,
	"skipped": false,
	"start_http_code": 200,
	"tls_mode": "off"
}

raw file

scenario-36.log (console trace)
alice starts a session on node-1
  session_start returned HTTP 200, session_id=f78a549e-db9a-4fdf-9a91-f59fdffc92c2
alice writes 2 memories tagged with session_id
settle 6s for session-tagged fanout
bob lists on node-2 filtered by session_id=f78a549e-db9a-4fdf-9a91-f59fdffc92c2
  bob sees 2 rows tagged session_id=f78a549e-db9a-4fdf-9a91-f59fdffc92c2 (expected 2)

raw file

Scenario 37 — memory_get_links bidirectional PASS

scenario-37.json (report)
{
	"agent_group": "ironclaw",
	"forward_has_target": true,
	"m1": "350ae889-0e69-4047-a2ca-9a61d68f0a79",
	"m2": "14073db5-738d-4d3f-910a-dc6e42f795a3",
	"pass": true,
	"reasons": [],
	"reverse_has_source": true,
	"scenario": "37",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-37.log (console trace)
alice writes M1 + M2 + links M1→M2
  M1=350ae889-0e69-4047-a2ca-9a61d68f0a79 M2=14073db5-738d-4d3f-910a-dc6e42f795a3
settle 6s for link fanout
charlie queries /api/v1/links/M1 (forward)
charlie queries /api/v1/links/M2 (reverse)

raw file

Scenario 38 — /export + /import PASS

scenario-38.json (report)
{
	"agent_group": "ironclaw",
	"dst_ns": "scenario38-dst-a1e900",
	"expected_rows": 5,
	"export_http_code": 200,
	"import_http_code": 200,
	"markers_preserved": 5,
	"pass": true,
	"reasons": [],
	"rows_exported": 5,
	"rows_in_destination": 5,
	"scenario": "38",
	"skipped": false,
	"src_ns": "scenario38-src-a1e900",
	"tls_mode": "off"
}

raw file

scenario-38.log (console trace)
alice writes 5 rows into scenario38-src-a1e900
settle 4s for pre-export replication
alice exports on node-1 (endpoint has no namespace filter; filter client-side)
  export returned HTTP 200, total_rows=232
  rewrote 5 memories from scenario38-src-a1e900 -> scenario38-dst-a1e900
bob imports the payload into scenario38-dst-a1e900 on node-2
  import returned HTTP 200
settle 6s for import + fanout
verify row counts match on destination
  scenario38-dst-a1e900 has 5 rows (expected 5)
  markers preserved in destination: 5/5

raw file

Scenario 39 — /sync/since delta PASS

scenario-39.json (report)
{
	"agent_group": "ironclaw",
	"checkpoint": "2026-04-27T17:08:50+00:00",
	"diag_curl_body_head": "{\"count\":6,\"earliest_updated_at\":\"2026-04-27T17:09:24.168161965+00:00\",\"latest_updated_at\":\"2026-04-27T17:09:31.658992065+00:00\",\"limit\":500,\"memories\":[{\"access_count\":0,\"confidence\":1.0,\"content\":\"marker=delta-0-546ac84b8f9c4ccf9d50eb445030312e\",\"created_at\":\"2026-04-27T17:09:24.168161965+00:00\",\"",
	"diag_curl_exit": 0,
	"diag_curl_http_code": 200,
	"diag_curl_stderr": "",
	"diag_earliest_updated_at": "2026-04-27T17:09:24.168161965+00:00",
	"diag_latest_updated_at": "2026-04-27T17:09:31.658992065+00:00",
	"diag_node3_health_reachable": true,
	"diag_updated_since": "2026-04-27T17:08:50+00:00",
	"expected_markers": 6,
	"markers_present": 6,
	"namespace": "scenario39-delta-79045a",
	"pass": true,
	"reasons": [],
	"rows_returned": 6,
	"rows_returned_raw": 6,
	"scenario": "39",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-39.log (console trace)
checkpoint = 2026-04-27T17:08:50+00:00
suspending ai-memory on node-3
  !! ssh timeout (30s): root@159.89.39.43 pgrep -f 'ai-memory serve' | xargs -r kill -STOP
alice + bob write 6 rows while node-3 is out
resuming ai-memory on node-3
settle 15s for process resume + federation catchup
  node-3 → node-1 health reachable: True (after 1 probes)
node-3 asks node-1 /api/v1/sync/since?since=2026-04-27T17:08:50+00:00
  curl exit=0 http_code=200 body_len=2898 stderr=''
  /sync/since raw=6 ns-filtered=6; 6/6 match our markers
  diag: updated_since=2026-04-27T17:08:50+00:00 earliest=2026-04-27T17:09:24.168161965+00:00 latest=2026-04-27T17:09:31.658992065+00:00

raw file

Scenario 40 — /memories/bulk PASS

scenario-40.json (report)
{
	"agent_group": "ironclaw",
	"bulk_http_code": "200",
	"bulk_size": 500,
	"namespace": "scenario40-bulk-450923",
	"pass": true,
	"per_peer_count": {
		"node_2": 500,
		"node_3": 500,
		"node_4": 500
	},
	"reasons": [],
	"scenario": "40",
	"skipped": false,
	"tls_mode": "off"
}

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 200
settle 20s for bulk fanout across 3 peers + aggregator
  node-2 count=500 (expected 500)
  node-3 count=500 (expected 500)
  node-4 count=500 (expected 500)

raw file

Scenario 41 — /metrics Prometheus PASS

scenario-41.json (report)
{
	"activity_namespace": "scenario41-activity-73f475",
	"agent_group": "ironclaw",
	"pass": true,
	"per_peer": {
		"node_1": {
			"counters_t0": 10,
			"counters_t1": 10,
			"regressed_keys": 0
		},
		"node_2": {
			"counters_t0": 10,
			"counters_t1": 10,
			"regressed_keys": 0
		},
		"node_3": {
			"counters_t0": 7,
			"counters_t1": 7,
			"regressed_keys": 0
		}
	},
	"reasons": [],
	"scenario": "41",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-41.log (console trace)
scrape T0
  node-1 T0 parsed 10 memory counters
  node-2 T0 parsed 10 memory counters
  node-3 T0 parsed 7 memory counters
settle 5s for counter update
scrape T1
  node-1 T1 parsed 10 memory counters
  node-2 T1 parsed 10 memory counters
  node-3 T1 parsed 7 memory counters

raw file

Scenario 42 — /namespaces enumeration PASS

scenario-42.json (report)
{
	"agent_group": "ironclaw",
	"namespaces": [
		"scenario42-7c2613-0",
		"scenario42-7c2613-1",
		"scenario42-7c2613-2"
	],
	"pass": true,
	"per_peer": {
		"node_1": {
			"scenario42-7c2613-0": 2,
			"scenario42-7c2613-1": 2,
			"scenario42-7c2613-2": 2
		},
		"node_2": {
			"scenario42-7c2613-0": 2,
			"scenario42-7c2613-1": 2,
			"scenario42-7c2613-2": 2
		},
		"node_3": {
			"scenario42-7c2613-0": 2,
			"scenario42-7c2613-1": 2,
			"scenario42-7c2613-2": 2
		},
		"node_4": {
			"scenario42-7c2613-0": 2,
			"scenario42-7c2613-1": 2,
			"scenario42-7c2613-2": 2
		}
	},
	"reasons": [],
	"scenario": "42",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-42.log (console trace)
alice writes into 3 distinct namespaces: ['scenario42-7c2613-0', 'scenario42-7c2613-1', 'scenario42-7c2613-2']
settle 10s for namespace index fanout
  node-1 sees 3/3 target namespaces, counts: {'scenario42-7c2613-0': 2, 'scenario42-7c2613-1': 2, 'scenario42-7c2613-2': 2}
  node-2 sees 3/3 target namespaces, counts: {'scenario42-7c2613-0': 2, 'scenario42-7c2613-1': 2, 'scenario42-7c2613-2': 2}
  node-3 sees 3/3 target namespaces, counts: {'scenario42-7c2613-0': 2, 'scenario42-7c2613-1': 2, 'scenario42-7c2613-2': 2}
  node-4 sees 3/3 target namespaces, counts: {'scenario42-7c2613-0': 2, 'scenario42-7c2613-1': 2, 'scenario42-7c2613-2': 2}

raw file

Scenario 43 — scenario-43 PASS

scenario-43.json (report)
{
	"agent_group": "ironclaw",
	"pass": true,
	"per_peer": {
		"node_1": {
			"missing_v1": [],
			"missing_v2": [],
			"responded": true,
			"schema_version": "2"
		},
		"node_2": {
			"missing_v1": [],
			"missing_v2": [],
			"responded": true,
			"schema_version": "2"
		},
		"node_3": {
			"missing_v1": [],
			"missing_v2": [],
			"responded": true,
			"schema_version": "2"
		},
		"node_4": {
			"missing_v1": [],
			"missing_v2": [],
			"responded": true,
			"schema_version": "2"
		}
	},
	"reasons": [],
	"scenario": "43",
	"skipped": false,
	"tls_mode": "off",
	"v1_fields": [
		"tier",
		"version",
		"features",
		"models"
	],
	"v2_blocks": [
		"permissions",
		"hooks",
		"compaction",
		"approval",
		"transcripts"
	]
}

raw file

scenario-43.log (console trace)
  node-1 schema_version='2' missing_v1=[] missing_v2=[]
  node-2 schema_version='2' missing_v1=[] missing_v2=[]
  node-3 schema_version='2' missing_v1=[] missing_v2=[]
  node-4 schema_version='2' missing_v1=[] missing_v2=[]

raw file

Scenario 44 — scenario-44 FAIL

Reasons: could not locate scenario44-9736d6/alphaone in taxonomy response | root node missing subtree_count field — v0.6.3 should expose it

scenario-44.json (report)
{
	"agent_group": "ironclaw",
	"children_returned": 0,
	"memories_written": 30,
	"pass": false,
	"reason": "could not locate scenario44-9736d6/alphaone in taxonomy response; root node missing subtree_count field — v0.6.3 should expose it",
	"reasons": [
		"could not locate scenario44-9736d6/alphaone in taxonomy response",
		"root node missing subtree_count field — v0.6.3 should expose it"
	],
	"root": "scenario44-9736d6/alphaone",
	"root_subtree_count": null,
	"scenario": "44",
	"skipped": false,
	"sum_children_counts": 0,
	"taxonomy_http_code": 200,
	"tls_mode": "off"
}

raw file

scenario-44.log (console trace)
writing 30 memories across 6 subtrees rooted at scenario44-9736d6/alphaone
  wrote 30/30
settle 8s for taxonomy index fanout
GET /api/v1/taxonomy?root=scenario44-9736d6/alphaone&depth=8&limit=20 on node-1
  HTTP 200
  root node found: False
  children returned: 0 (limit was 20)
  sum(count) over returned children: 0
  root subtree_count: None

raw file

Scenario 45 — scenario-45 FAIL

Reasons: kg_invalidate returned HTTP 400 | as_of=past missing edges; expected all 3 targets, got 0 | as_of=now expected 2 edges, got 0

scenario-45.json (report)
{
	"agent_group": "ironclaw",
	"as_of_now": "2026-04-27T17:13:04Z",
	"as_of_past": "2026-04-27T16:12:51Z",
	"invalidate_http_code": 400,
	"m0_id": "993a371b-933e-4f31-a27c-dc0be704fb4e",
	"now_edges": 0,
	"now_query_http_code": 200,
	"pass": false,
	"past_edges": 0,
	"past_query_http_code": 200,
	"reason": "kg_invalidate returned HTTP 400; as_of=past missing edges; expected all 3 targets, got 0; as_of=now expected 2 edges, got 0",
	"reasons": [
		"kg_invalidate returned HTTP 400",
		"as_of=past missing edges; expected all 3 targets, got 0",
		"as_of=now expected 2 edges, got 0"
	],
	"scenario": "45",
	"skipped": false,
	"target_ids": [
		"613bc04d-f22e-4ac5-bb3b-346d19dea59d",
		"55fad96f-bc23-4570-9120-9f0afd86b600",
		"0079fef3-687b-4b9d-b313-64f000e6e85c"
	],
	"tls_mode": "off"
}

raw file

scenario-45.log (console trace)
seed: write M0 + T1/T2/T3 on node-1
  M0=993a371b-933e-4f31-a27c-dc0be704fb4e targets=['613bc04d-f22e-4ac5-bb3b-346d19dea59d', '55fad96f-bc23-4570-9120-9f0afd86b600', '0079fef3-687b-4b9d-b313-64f000e6e85c']
settle 4s for seed propagation
creating 3 edges with valid_from=2026-04-27T16:12:51Z
  edge M0->T1 HTTP 400
  edge M0->T2 HTTP 400
  edge M0->T3 HTTP 400
settle 4s for edge fanout
invalidating edge M0->T2 (target 55fad96f-bc23-4570-9120-9f0afd86b600)
  invalidate HTTP 400
settle 4s for invalidation fanout
kg_query as_of=2026-04-27T16:12:51Z (past) — expecting 3 edges
  HTTP 200 edge count=0
kg_query as_of=2026-04-27T17:13:04Z (now) — expecting 2 edges (T2 invalidated)
  HTTP 200 edge count=0

raw file

Scenario 46 — scenario-46 FAIL

Reasons: expected >=3 events (2 adds + 1 invalidate), got 0 | no edge_added event in timeline | no edge_invalidated event in timeline

scenario-46.json (report)
{
	"agent_group": "ironclaw",
	"chronological": true,
	"event_count": 0,
	"m0_id": "2ba5a97b-815c-4142-8fb1-57c10af73242",
	"pass": false,
	"reason": "expected >=3 events (2 adds + 1 invalidate), got 0; no edge_added event in timeline; no edge_invalidated event in timeline",
	"reasons": [
		"expected >=3 events (2 adds + 1 invalidate), got 0",
		"no edge_added event in timeline",
		"no edge_invalidated event in timeline"
	],
	"scenario": "46",
	"skipped": false,
	"timeline_http_code": 200,
	"tls_mode": "off",
	"types": []
}

raw file

scenario-46.log (console trace)
seed: write source M0 + 2 targets on node-1
  M0=2ba5a97b-815c-4142-8fb1-57c10af73242 T1=908d5d43-6c78-4a47-bebf-46f6b81aec9d T2=9b021768-8343-4c86-88fc-613ba64e0a35
settle 3s for seed settle
create edge M0->T1 (event 1: edge_added)
create edge M0->T2 (event 2: edge_added)
invalidate M0->T1 (event 3: edge_invalidated)
settle 4s for timeline indexer
GET /api/v1/kg/timeline?source_id=2ba5a97b-815c-4142-8fb1-57c10af73242 on node-1
  HTTP 200
  0 events, types=[]

raw file

Scenario 47 — scenario-47 FAIL

Reasons: by-alias('a1-project') HTTP 404 | by-alias('alphaone-proj') HTTP 404 | by-alias('alpha1-proj') HTTP 404 | by-alias('ao-project') HTTP 404

scenario-47.json (report)
{
	"agent_group": "ironclaw",
	"alias_resolutions": {
		"a1-project": {
			"entity_id": "",
			"http_code": 404
		},
		"alpha1-proj": {
			"entity_id": "",
			"http_code": 404
		},
		"alphaone-proj": {
			"entity_id": "",
			"http_code": 404
		},
		"ao-project": {
			"entity_id": "",
			"http_code": 404
		}
	},
	"aliases_on_entity": [
		"a1-project",
		"alphaone-proj",
		"alpha1-proj",
		"ao-project"
	],
	"canonical": "AlphaOne-Project-7188dc",
	"first_entity_id": "33523935-f76d-45d3-b20e-ac4dd6cdb43f",
	"first_register_http_code": 201,
	"namespace": "scenario47-ent-7188dc",
	"pass": false,
	"reason": "by-alias('a1-project') HTTP 404; by-alias('alphaone-proj') HTTP 404; by-alias('alpha1-proj') HTTP 404; by-alias('ao-project') HTTP 404",
	"reasons": [
		"by-alias('a1-project') HTTP 404",
		"by-alias('alphaone-proj') HTTP 404",
		"by-alias('alpha1-proj') HTTP 404",
		"by-alias('ao-project') HTTP 404"
	],
	"scenario": "47",
	"second_entity_id": "33523935-f76d-45d3-b20e-ac4dd6cdb43f",
	"second_register_http_code": 200,
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-47.log (console trace)
register canonical='AlphaOne-Project-7188dc' ns=scenario47-ent-7188dc aliases=['a1-project', 'alphaone-proj']
  HTTP 201 entity_id='33523935-f76d-45d3-b20e-ac4dd6cdb43f'
register again, same canonical, different aliases=['alpha1-proj', 'ao-project']
  HTTP 200 entity_id='33523935-f76d-45d3-b20e-ac4dd6cdb43f' aliases-on-entity=['a1-project', 'alphaone-proj', 'alpha1-proj', 'ao-project']
settle 4s for entity propagation
  by-alias('a1-project') HTTP 404 -> ''
  by-alias('alphaone-proj') HTTP 404 -> ''
  by-alias('alpha1-proj') HTTP 404 -> ''
  by-alias('ao-project') HTTP 404 -> ''

raw file

Scenario 48 — scenario-48 FAIL

Reasons: check_duplicate returned HTTP 422 | check_duplicate returned 0 matches for a near-identical input | original memory (5f913f4e-d905-4199-87d9-7859d5028318) absent from matches | match did not carry a similarity score field

scenario-48.json (report)
{
	"agent_group": "ironclaw",
	"check_http_code": 422,
	"match_count": 0,
	"original_id": "5f913f4e-d905-4199-87d9-7859d5028318",
	"original_in_matches": false,
	"pass": false,
	"reason": "check_duplicate returned HTTP 422; check_duplicate returned 0 matches for a near-identical input; original memory (5f913f4e-d905-4199-87d9-7859d5028318) absent from matches; match did not carry a similarity score field",
	"reasons": [
		"check_duplicate returned HTTP 422",
		"check_duplicate returned 0 matches for a near-identical input",
		"original memory (5f913f4e-d905-4199-87d9-7859d5028318) absent from matches",
		"match did not carry a similarity score field"
	],
	"scenario": "48",
	"similarity_score": null,
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-48.log (console trace)
alice writes the original memory on node-1
  original id=5f913f4e-d905-4199-87d9-7859d5028318
settle 6s for indexing + embedding before duplicate check
alice calls /api/v1/check_duplicate with near-match content
  HTTP 422
  matches returned: 0
  original-as-match found=False score=None

raw file

Scenario 49 — scenario-49 FAIL

Reasons: access: access_count not incremented | promote: HTTP 404 | promote: tier=None, expected 'long' | expire: HTTP 404 | archive: M1 not visible in /api/v1/archive listing | restore: HTTP 404 | purge: HTTP 404

scenario-49.json (report)
{
	"agent_group": "ironclaw",
	"audit": {
		"access": {
			"access_count": 0
		},
		"archive": {
			"http_code": 200,
			"in_archive_listing": false
		},
		"consolidate": {
			"consolidated_id": "17a26a23-456b-4b76-83c7-44739a8f3e28",
			"http_code": 201,
			"sibling_count": 3
		},
		"expire": {
			"http_code": 404,
			"marker_set": false,
			"still_visible": true
		},
		"promote": {
			"http_code": 404,
			"tier_after": null
		},
		"purge": {
			"http_code": 404,
			"still_in_archive": false
		},
		"restore": {
			"active_after_restore": true,
			"http_code": 404
		},
		"store": {
			"exists": true,
			"tier": "mid"
		}
	},
	"m1_id": "0bc09794-45ff-4309-ba53-ac58c1131cf0",
	"namespace": "scenario49-lifecycle-7f5061",
	"pass": false,
	"reason": "access: access_count not incremented; promote: HTTP 404; promote: tier=None, expected 'long'; expire: HTTP 404; archive: M1 not visible in /api/v1/archive listing; restore: HTTP 404; purge: HTTP 404",
	"reasons": [
		"access: access_count not incremented",
		"promote: HTTP 404",
		"promote: tier=None, expected 'long'",
		"expire: HTTP 404",
		"archive: M1 not visible in /api/v1/archive listing",
		"restore: HTTP 404",
		"purge: HTTP 404"
	],
	"scenario": "49",
	"skipped": false,
	"tls_mode": "off"
}

raw file

scenario-49.log (console trace)
step 1: store M1 at tier=mid
  M1=0bc09794-45ff-4309-ba53-ac58c1131cf0
settle 3s for post-store
step 2: access M1 (3x to bump counter)
settle 2s for access counter flush
step 3: write 2 sibling memories + consolidate
settle 3s for siblings settle
settle 4s for consolidation index
step 4: promote M1 to tier=long
settle 3s for promote settle
step 5: expire M1 via /api/v1/memories/{id}/forget
settle 3s for forget settle
step 6: archive M1 via POST /api/v1/archive
settle 4s for archive settle
step 7: restore M1
settle 3s for restore settle
step 8: archive again then hard-purge
settle 2s for re-archive settle
settle 3s for purge settle

raw file

Scenario 50 — scenario-50 UNKNOWN

scenario-50.json (report)
{
	"agent_group": "ironclaw",
	"capabilities_features": {
		"auto_consolidation": false,
		"auto_tagging": false,
		"contradiction_analysis": false,
		"cross_encoder_reranking": false,
		"embedder_loaded": true,
		"hybrid_recall": true,
		"keyword_search": true,
		"memory_reflection": false,
		"query_expansion": false,
		"semantic_search": true
	},
	"pass": null,
	"reason": "sqlcipher feature not advertised in /api/v1/capabilities — daemon was not built with --features sqlcipher",
	"scenario": "50",
	"skipped": true,
	"tls_mode": "off"
}

raw file

scenario-50.log (console trace)
skipped — sqlcipher feature not advertised in /api/v1/capabilities — daemon was not built with --features sqlcipher

raw file

Scenario 51 — scenario-51 UNKNOWN

scenario-51.json (report)
{
	"agent_group": "ironclaw",
	"capabilities_models": {
		"cross_encoder": "none",
		"embedding": "sentence-transformers/all-MiniLM-L6-v2",
		"embedding_dim": 384,
		"llm": "none"
	},
	"capabilities_tier": "semantic",
	"pass": null,
	"reason": "autonomous/smart tier not available on node-1 — tier='semantic' models={'cross_encoder': 'none', 'embedding': 'sentence-transformers/all-MiniLM-L6-v2', 'embedding_dim': 384, 'llm': 'none'}",
	"scenario": "51",
	"skipped": true,
	"tls_mode": "off"
}

raw file

scenario-51.log (console trace)
skipped — autonomous/smart tier not available on node-1 — tier='semantic' models={'cross_encoder': 'none', 'embedding': 'sentence-transformers/all-MiniLM-L6-v2', 'embedding_dim': 384, 'llm': 'none'}

raw file

All artifacts