From 795a3dbe293fd2ad2832644ff5e965aa1bd9efc6 Mon Sep 17 00:00:00 2001 From: FlowmemoryAI <283694809+FlowmemoryAI@users.noreply.github.com> Date: Wed, 13 May 2026 12:27:19 -0500 Subject: [PATCH] Add launch contract event spine --- .../public/data/flowmemory-dashboard-v0.json | 347 ++++++++++++++++ apps/dashboard/src/data/types.ts | 55 +++ apps/dashboard/src/styles.css | 168 +++++++- apps/dashboard/src/test/dashboardData.test.ts | 3 + apps/dashboard/src/views/FlowMemoryView.tsx | 146 ++++++- docs/CURRENT_STATE.md | 14 +- .../2026-05-13-contract-event-spine-v0.md | 54 +++ docs/FLOW_MEMORY_V0.md | 37 +- docs/ROADMAP.md | 3 + docs/ROOTFLOW_V0.md | 21 +- docs/V0_LAUNCH_ACCEPTANCE.md | 2 + ...OOTFLOW_FLOW_MEMORY_V0_ACCEPTANCE_AUDIT.md | 19 +- docs/reviews/V0_BOUNDARY_CLAIMS_AUDIT.md | 52 +++ .../dashboard/flowmemory-dashboard-v0.json | 347 ++++++++++++++++ .../launch-core/flowmemory-launch-v0.json | 373 +++++++++++++++++- .../launch-core/rootflow-transitions.json | 72 +++- schemas/flowmemory/README.md | 5 + schemas/flowmemory/memory-signal.schema.json | 83 +++- .../rootflow-transition.schema.json | 25 +- .../flowmemory/src/generate-launch-core.ts | 76 ++++ services/flowmemory/src/types.ts | 55 +++ services/flowmemory/test/flowmemory.test.ts | 17 + 22 files changed, 1925 insertions(+), 49 deletions(-) create mode 100644 docs/DECISIONS/2026-05-13-contract-event-spine-v0.md create mode 100644 docs/reviews/V0_BOUNDARY_CLAIMS_AUDIT.md diff --git a/apps/dashboard/public/data/flowmemory-dashboard-v0.json b/apps/dashboard/public/data/flowmemory-dashboard-v0.json index f84df74f..299c9566 100644 --- a/apps/dashboard/public/data/flowmemory-dashboard-v0.json +++ b/apps/dashboard/public/data/flowmemory-dashboard-v0.json @@ -666,6 +666,16 @@ "txHash": "0x3333333333333333333333333333333333333333333333333333333333333333", "sequence": "1", "reasonCodes": [], + "contractEventRef": { + "signalId": "0xec2a80963190d2fa4d0eae023e735eeaf770cf33496eabdea696f3c7dda071eb", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "1", + "pulseTypeName": "ROOTFIELD_REGISTERED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333333", + "logIndex": "2" + }, "id": "0x29fcee50b38bf403556ea08db7faeda6ea50430c08fc3126cebffad4a7657522", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -696,6 +706,16 @@ "txHash": "0x3333333333333333333333333333333333333333333333333333333333333334", "sequence": "2", "reasonCodes": [], + "contractEventRef": { + "signalId": "0xc595baea5e90a5f06ff49d8afeea0996eb39e13b3794903b8142dc9daf3a2df0", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333334", + "logIndex": "3" + }, "id": "0x5cdf7f5498350650adc19c62828425723a09bcca6571774992ca2d013fdc1068", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -728,6 +748,16 @@ "reasonCodes": [ "observation.reorged" ], + "contractEventRef": { + "signalId": "0x4699ec901e15d260417fd6a9a86357c179ac55b631df05f28b29f28d5a5f3b61", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333335", + "logIndex": "4" + }, "id": "0xe1b6f858279961c968cdfba0b85d489767c486289e824cab3d017997064fed89", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -760,6 +790,16 @@ "reasonCodes": [ "commitment.mismatch" ], + "contractEventRef": { + "signalId": "0xe32d6eeeff9c6bafadca56b980d58159afe8ffb29184458fa589c890829b9627", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333336", + "logIndex": "5" + }, "id": "0x35db5f8c36e2bc988c4d60f25a2e60d971256bdfdb79a73c92c0b82a41e5a367", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -792,6 +832,16 @@ "reasonCodes": [ "artifact.unavailable" ], + "contractEventRef": { + "signalId": "0xfdc7756ac00683bc3e85bb3a9c2bd01f9719667b2d739818591fe697ee45d6c4", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333337", + "logIndex": "6" + }, "id": "0x31d44377aa98e7fcaa07110256e1600249c4337c69e6d06c14d36e6aad6a79c4", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -824,6 +874,16 @@ "reasonCodes": [ "pulse.type.unsupported" ], + "contractEventRef": { + "signalId": "0x74f686fdd91352713b0e1f74f8218d8e41359b67634f8c8be6cbafe15f7f95d5", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "99", + "pulseTypeName": "UNKNOWN_FLOWPULSE_TYPE", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333338", + "logIndex": "7" + }, "id": "0xdc9a57620b3309aceee35e858f62650b565e5f17ec6d9218ffd653ef5a633cdf", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -860,6 +920,47 @@ "occurredAt": "2026-05-13T02:40:00.000Z", "uri": "ipfs://bafy-flowmemory-example", "summary": "rootfield registration pulse 1", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "1", + "pulseTypeName": "ROOTFIELD_REGISTERED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "commitment": "0x4122209ff672fc04b2ec3af31ab1af79813971f86de000aa6534038cc79de6b5", + "parentPulseId": "0x0000000000000000000000000000000000000000000000000000000000000000", + "sequence": "1", + "occurredAt": "2026-05-13T02:40:00.000Z", + "uri": "ipfs://bafy-flowmemory-example" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123456", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222222", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333333", + "transactionIndex": "7", + "logIndex": "2", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + }, "id": "0xec2a80963190d2fa4d0eae023e735eeaf770cf33496eabdea696f3c7dda071eb", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -894,6 +995,47 @@ "occurredAt": "2026-05-13T02:40:00.000Z", "uri": "ipfs://bafy-flowmemory-example", "summary": "rootfield registration pulse 1", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "1", + "pulseTypeName": "ROOTFIELD_REGISTERED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "commitment": "0x4122209ff672fc04b2ec3af31ab1af79813971f86de000aa6534038cc79de6b5", + "parentPulseId": "0x0000000000000000000000000000000000000000000000000000000000000000", + "sequence": "1", + "occurredAt": "2026-05-13T02:40:00.000Z", + "uri": "ipfs://bafy-flowmemory-example" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123456", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222222", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333333", + "transactionIndex": "7", + "logIndex": "2", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + }, "id": "0xec2a80963190d2fa4d0eae023e735eeaf770cf33496eabdea696f3c7dda071eb", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -928,6 +1070,47 @@ "occurredAt": "2026-05-13T02:41:00.000Z", "uri": "fixture://root-commit-valid", "summary": "root commitment pulse 2", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab001", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1", + "commitment": "0x69a9f953179a6ce2e08724dd759fb71b08b0759a5900fc0399a753ecf0557df5", + "parentPulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sequence": "2", + "occurredAt": "2026-05-13T02:41:00.000Z", + "uri": "fixture://root-commit-valid" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123457", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222223", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333334", + "transactionIndex": "8", + "logIndex": "3", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + }, "id": "0xc595baea5e90a5f06ff49d8afeea0996eb39e13b3794903b8142dc9daf3a2df0", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -962,6 +1145,47 @@ "occurredAt": "2026-05-13T02:41:00.000Z", "uri": "fixture://root-commit-valid", "summary": "root commitment pulse 2", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab002", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1", + "commitment": "0x69a9f953179a6ce2e08724dd759fb71b08b0759a5900fc0399a753ecf0557df5", + "parentPulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sequence": "2", + "occurredAt": "2026-05-13T02:41:00.000Z", + "uri": "fixture://root-commit-valid" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123458", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222224", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333335", + "transactionIndex": "9", + "logIndex": "4", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + }, "id": "0x4699ec901e15d260417fd6a9a86357c179ac55b631df05f28b29f28d5a5f3b61", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -996,6 +1220,47 @@ "occurredAt": "2026-05-13T02:42:00.000Z", "uri": "fixture://root-commit-valid", "summary": "root commitment pulse 3", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab003", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1", + "commitment": "0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", + "parentPulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sequence": "3", + "occurredAt": "2026-05-13T02:42:00.000Z", + "uri": "fixture://root-commit-valid" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123459", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222225", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333336", + "transactionIndex": "10", + "logIndex": "5", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + }, "id": "0xe32d6eeeff9c6bafadca56b980d58159afe8ffb29184458fa589c890829b9627", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -1030,6 +1295,47 @@ "occurredAt": "2026-05-13T02:43:00.000Z", "uri": "fixture://missing-artifact", "summary": "root commitment pulse 4", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab004", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1", + "commitment": "0x69a9f953179a6ce2e08724dd759fb71b08b0759a5900fc0399a753ecf0557df5", + "parentPulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sequence": "4", + "occurredAt": "2026-05-13T02:43:00.000Z", + "uri": "fixture://missing-artifact" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123460", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222226", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333337", + "transactionIndex": "11", + "logIndex": "6", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + }, "id": "0xfdc7756ac00683bc3e85bb3a9c2bd01f9719667b2d739818591fe697ee45d6c4", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -1064,6 +1370,47 @@ "occurredAt": "2026-05-13T02:44:00.000Z", "uri": "fixture://unsupported", "summary": "unsupported pulse pulse 5", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "99", + "pulseTypeName": "UNKNOWN_FLOWPULSE_TYPE", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab005", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1", + "commitment": "0x69a9f953179a6ce2e08724dd759fb71b08b0759a5900fc0399a753ecf0557df5", + "parentPulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sequence": "5", + "occurredAt": "2026-05-13T02:44:00.000Z", + "uri": "fixture://unsupported" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123461", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222227", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333338", + "transactionIndex": "12", + "logIndex": "7", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + }, "id": "0x74f686fdd91352713b0e1f74f8218d8e41359b67634f8c8be6cbafe15f7f95d5", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { diff --git a/apps/dashboard/src/data/types.ts b/apps/dashboard/src/data/types.ts index 4e6c0cf7..8adc4809 100644 --- a/apps/dashboard/src/data/types.ts +++ b/apps/dashboard/src/data/types.ts @@ -30,6 +30,59 @@ export interface Provenance { localPathHint?: string; } +export type FlowPulseContractTypeName = + | "ROOTFIELD_REGISTERED" + | "ROOT_COMMITTED" + | "ROOTFIELD_STATUS_CHANGED" + | "UNKNOWN_FLOWPULSE_TYPE"; + +export interface FlowPulseContractEvent { + schema: "flowmemory.flowpulse_contract_event.v0"; + interfaceName: "IFlowPulse"; + eventName: "FlowPulse"; + eventSignatureText: string; + eventTopic0: string; + expectedTopic0: string; + topicMatchesContract: boolean; + sourceContract: string; + pulseTypeId: string; + pulseTypeName: FlowPulseContractTypeName; + indexed: { + pulseId: string; + rootfieldId: string; + actor: string; + }; + payload: { + subject: string; + commitment: string; + parentPulseId: string; + sequence: string; + occurredAt: string; + uri: string; + }; + receiptLocator: { + chainId: string; + blockNumber: string; + blockHash: string; + txHash: string; + transactionIndex: string; + logIndex: string; + receiptStatus: string; + }; + receiptDerivedFields: string[]; +} + +export interface FlowPulseContractEventRef { + signalId: string; + eventName: "FlowPulse"; + eventTopic0: string; + sourceContract: string; + pulseTypeId: string; + pulseTypeName: FlowPulseContractTypeName; + txHash: string; + logIndex: string; +} + export interface ProvenancedRecord { id: string; status: DashboardStatus; @@ -149,6 +202,7 @@ export interface RootflowTransition extends ProvenancedRecord { txHash: string; sequence: string; reasonCodes: string[]; + contractEventRef: FlowPulseContractEventRef; } export interface MemorySignal extends ProvenancedRecord { @@ -172,6 +226,7 @@ export interface MemorySignal extends ProvenancedRecord { occurredAt: string; uri: string; summary: string; + contractEvent: FlowPulseContractEvent; } export interface MemoryReceipt extends ProvenancedRecord { diff --git a/apps/dashboard/src/styles.css b/apps/dashboard/src/styles.css index 2011ab24..93d9e3fc 100644 --- a/apps/dashboard/src/styles.css +++ b/apps/dashboard/src/styles.css @@ -313,6 +313,72 @@ small { gap: 10px; } +.flowmemory-hero { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(280px, 0.34fr); + gap: 14px; + align-items: stretch; + border: 1px solid var(--line); + border-radius: 8px; + background: linear-gradient(135deg, #fbfcf8 0%, #edf4ef 100%); + box-shadow: var(--shadow); +} + +.flowmemory-hero-main { + display: grid; + gap: 12px; + padding: 18px; +} + +.flowmemory-hero-main h2 { + max-width: 780px; + margin: 0; + font-size: 1.48rem; + line-height: 1.14; +} + +.flowmemory-hero-main p { + max-width: 82ch; + margin: 0; + color: #465047; + line-height: 1.5; +} + +.flowmemory-spine { + display: grid; + grid-template-columns: repeat(5, minmax(0, 1fr)); + gap: 8px; +} + +.flowmemory-spine span { + min-height: 34px; + padding: 8px 9px; + color: #284238; + border: 1px solid #bfd1c7; + border-radius: 7px; + background: rgba(251, 252, 248, 0.78); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 0.74rem; + text-align: center; +} + +.flowmemory-hero-side { + display: grid; + gap: 1px; + min-width: 0; + padding: 1px; + border-left: 1px solid var(--line); +} + +.flowmemory-hero-side div { + display: grid; + gap: 5px; + align-content: center; + min-width: 0; + padding: 12px; + background: rgba(251, 252, 248, 0.72); +} + .metric-tile, .panel, .table-panel, @@ -367,6 +433,10 @@ small { grid-column: span 1; } +.panel-side-bottom { + grid-column: 2; +} + .panel-heading { display: flex; align-items: center; @@ -403,6 +473,28 @@ small { display: grid; } +.status-strip { + display: flex; + flex-wrap: wrap; + gap: 8px; + padding: 10px 0 2px; +} + +.status-strip span { + display: inline-flex; + gap: 6px; + align-items: center; + padding: 3px 6px 3px 3px; + border: 1px solid var(--line); + border-radius: 999px; + background: #f8f9f4; +} + +.status-strip strong { + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 0.74rem; +} + .record-row { display: grid; grid-template-columns: minmax(0, 1fr) 270px; @@ -432,7 +524,7 @@ small { } .record-facts { - grid-template-columns: repeat(3, minmax(0, 1fr)); + grid-template-columns: repeat(2, minmax(0, 1fr)); } .record-facts div, @@ -473,6 +565,63 @@ dd { overflow-wrap: anywhere; } +.contract-event-list { + display: grid; +} + +.contract-event-list article { + display: grid; + gap: 9px; + padding: 12px 0; + border-bottom: 1px solid var(--line); +} + +.contract-event-list article:last-child { + border-bottom: 0; +} + +.contract-event-list article > div { + display: flex; + gap: 8px; + align-items: center; + min-width: 0; +} + +.contract-event-list strong { + overflow-wrap: anywhere; + font-size: 0.84rem; +} + +.contract-event-list dl { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 8px; + margin: 0; +} + +.bundle-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 10px; + padding-top: 14px; +} + +.bundle-grid article { + display: grid; + gap: 8px; + min-width: 0; + padding: 12px; + border: 1px solid var(--line); + border-radius: 7px; + background: #f7f8f4; +} + +.bundle-grid strong, +.bundle-grid small { + display: block; + overflow-wrap: anywhere; +} + .block-strip { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); @@ -825,6 +974,23 @@ dd { .lane-grid { grid-template-columns: 1fr; } + + .flowmemory-hero, + .flowmemory-spine, + .contract-event-list dl, + .bundle-grid { + grid-template-columns: 1fr; + } + + .flowmemory-hero-side, + .panel-side-bottom { + grid-column: auto; + } + + .flowmemory-hero-side { + border-left: 0; + border-top: 1px solid var(--line); + } } @media (max-width: 860px) { diff --git a/apps/dashboard/src/test/dashboardData.test.ts b/apps/dashboard/src/test/dashboardData.test.ts index bc050fe9..a635ffc9 100644 --- a/apps/dashboard/src/test/dashboardData.test.ts +++ b/apps/dashboard/src/test/dashboardData.test.ts @@ -13,6 +13,9 @@ describe("dashboard fixture", () => { expect(data.metadata.mode).toBe("fixture"); expect(data.flowPulseObservations.length).toBeGreaterThan(0); expect(data.verifierReports.length).toBeGreaterThan(0); + expect(data.memorySignals.every((signal) => signal.contractEvent.eventName === "FlowPulse")).toBe(true); + expect(data.memorySignals.every((signal) => signal.contractEvent.topicMatchesContract)).toBe(true); + expect(data.rootflowTransitions.every((transition) => transition.contractEventRef.signalId === transition.memorySignalId)).toBe(true); }); it("covers every required dashboard status", () => { diff --git a/apps/dashboard/src/views/FlowMemoryView.tsx b/apps/dashboard/src/views/FlowMemoryView.tsx index 1dd8fbe7..2464b686 100644 --- a/apps/dashboard/src/views/FlowMemoryView.tsx +++ b/apps/dashboard/src/views/FlowMemoryView.tsx @@ -1,12 +1,12 @@ import { useMemo, useState } from "react"; -import { BrainCircuit, Search } from "lucide-react"; +import { Activity, BrainCircuit, GitBranch, Search, ShieldCheck } from "lucide-react"; import { EmptyState } from "../components/EmptyState"; import { HashValue } from "../components/HashValue"; import { ProvenanceLine } from "../components/ProvenanceLine"; import { SectionHeader } from "../components/SectionHeader"; import { StatusBadge } from "../components/StatusBadge"; import { searchRecords } from "../data/selectors"; -import type { DashboardData } from "../data/types"; +import type { DashboardData, DashboardStatus } from "../data/types"; export function FlowMemoryView({ data }: { data: DashboardData }) { const [query, setQuery] = useState(""); @@ -14,6 +14,16 @@ export function FlowMemoryView({ data }: { data: DashboardData }) { () => searchRecords(data.rootflowTransitions, query), [data.rootflowTransitions, query], ); + const latestView = data.agentMemoryViews[0]; + const latestBundle = data.rootfieldBundles[0]; + const contractEventCount = data.memorySignals.filter((signal) => signal.contractEvent.topicMatchesContract).length; + const statusCounts = useMemo( + () => data.rootflowTransitions.reduce>((counts, transition) => { + counts[transition.status] = (counts[transition.status] ?? 0) + 1; + return counts; + }, {}), + [data.rootflowTransitions], + ); return (
@@ -29,6 +39,38 @@ export function FlowMemoryView({ data }: { data: DashboardData }) { } /> +
+
+ local acceptance path +

IFlowPulse events become verified memory state

+

+ The fixture path now preserves the contract event spine: indexed FlowPulse fields, + receipt-derived coordinates, verifier result, and Rootflow state movement. +

+
+ FlowPulse + MemorySignal + MemoryReceipt + RootflowTransition + AgentMemoryView +
+
+
+
+ Latest root + +
+
+ Rootfield + +
+
+ Agent view + +
+
+
+
Memory signals @@ -62,6 +104,14 @@ export function FlowMemoryView({ data }: { data: DashboardData }) { warnings preserved
+
+ Contract events + {contractEventCount} +
+ + topic0 matched +
+
@@ -73,6 +123,14 @@ export function FlowMemoryView({ data }: { data: DashboardData }) { {transitions.length} shown +
+ {Object.entries(statusCounts).map(([status, count]) => ( + + + {count} + + ))} +
{transitions.length > 0 ? (
{transitions.map((transition) => ( @@ -90,6 +148,22 @@ export function FlowMemoryView({ data }: { data: DashboardData }) {
+
+
event
+
{transition.contractEventRef.pulseTypeName}
+
+
+
source
+
+ +
+
+
+
tx/log
+
+ / {transition.contractEventRef.logIndex} +
+
pulse
@@ -116,7 +190,47 @@ export function FlowMemoryView({ data }: { data: DashboardData }) {
-
+ {data.memorySignals.length} signals +
+
+ {data.memorySignals.map((signal, index) => ( +
+
+ + {signal.contractEvent.pulseTypeName} +
+
+
+
indexed
+
+ +
+
+
+
payload
+
+ +
+
+
+
locator
+
+ / {signal.contractEvent.receiptLocator.logIndex} +
+
+
+
+ ))} +
+
+ +
+
+
+
{data.agentMemoryViews.length} views @@ -136,6 +250,32 @@ export function FlowMemoryView({ data }: { data: DashboardData }) {
+ +
+
+
+
+ {data.rootfieldBundles.length} bundle +
+
+ {data.rootfieldBundles.map((bundle) => ( +
+ +
+ + + + + {bundle.counts.verified} verified, {bundle.counts.failed} failed, {bundle.counts.unresolved} unresolved + +
+ +
+ ))} +
+
); } diff --git a/docs/CURRENT_STATE.md b/docs/CURRENT_STATE.md index fb63e90e..1ce4eba1 100644 --- a/docs/CURRENT_STATE.md +++ b/docs/CURRENT_STATE.md @@ -62,6 +62,8 @@ Launch-core integration: - `fixtures/launch-core/flowmemory-launch-v0.json` contains generated MemorySignal, MemoryReceipt, RootfieldBundle, AgentMemoryView, and RootflowTransition objects. - `fixtures/launch-core/rootflow-transitions.json` contains concrete generated RootflowTransition output. - `schemas/flowmemory/` contains canonical JSON schemas for MemorySignal, MemoryReceipt, RootflowTransition, RootfieldBundle, and AgentMemoryView. +- Generated MemorySignals include a `contractEvent` object tying each signal to `IFlowPulse.FlowPulse` event semantics, pulse type names, indexed fields, payload fields, and receipt-derived locator fields. +- Generated RootflowTransitions include `contractEventRef` so reviewers and dashboards can trace each transition back to the contract event that produced the MemorySignal. - `services/flowmemory/src/status.ts` implements the explicit verifier-to-Flow-Memory status adapter: `valid` -> `verified`, `invalid` -> `failed`, `unresolved` -> `unresolved`, `unsupported` -> `unsupported`, `reorged` -> `reorged`. - `.github/workflows/ci.yml` now includes area jobs for contracts, services/launch core, crypto, dashboard, devnet, and hardware. @@ -126,6 +128,7 @@ Recently merged PRs: - #60 Crypto V0 foundation. - #61 Indexer/verifier V0 fixture package. - #62 Dashboard V0. +- #68 Launch-core FlowMemory V0 integration. ## Active Local Work @@ -156,12 +159,11 @@ Before assigning agents, check for dirty worktrees and avoid overlapping folders ## Current Operator Priorities -1. Make Rootflow V0 and Flow Memory V0 pass the launch acceptance matrix in `docs/V0_LAUNCH_ACCEPTANCE.md`. -2. Keep the generated launch-core command stable in CI. -3. Add richer schema validation before live services. -4. Finish contracts hardening without production deployment or token mechanics. -5. Keep dashboard work fixture-backed until a production API is explicitly scoped. -6. Keep chain/appchain work no-value and local until explicit gates are passed. +1. Keep the generated launch-core command stable in CI. +2. Add runtime schema validation and fixture diff guardrails before live services. +3. Finish contracts hardening without production deployment or token mechanics. +4. Keep dashboard work fixture-backed until a production API is explicitly scoped. +5. Keep chain/appchain work no-value and local until explicit gates are passed. ## Update Rule diff --git a/docs/DECISIONS/2026-05-13-contract-event-spine-v0.md b/docs/DECISIONS/2026-05-13-contract-event-spine-v0.md new file mode 100644 index 00000000..02423955 --- /dev/null +++ b/docs/DECISIONS/2026-05-13-contract-event-spine-v0.md @@ -0,0 +1,54 @@ +# Contract Event Spine For Launch-Core V0 + +Date: 2026-05-13 + +Status: accepted for local/test V0 fixtures. + +## Context + +The launch-core generator already connected indexer observations, verifier +reports, Rootflow transitions, and dashboard fixture output. The missing piece +was an explicit contract-event spine that showed how generated Flow Memory +objects map back to `IFlowPulse.FlowPulse` semantics. + +Without this spine, dashboards and reviewers could see `pulseId`, `txHash`, and +`logIndex`, but they had to infer which fields were emitted by the contract and +which fields were derived by the indexer after receipts/logs existed. + +## Decision + +Generated `MemorySignal` objects now include `contractEvent`: + +- `interfaceName`: `IFlowPulse` +- `eventName`: `FlowPulse` +- event signature text and topic0 +- source contract address +- pulse type id and pulse type name +- indexed event fields: `pulseId`, `rootfieldId`, `actor` +- payload fields: `subject`, `commitment`, `parentPulseId`, `sequence`, + `occurredAt`, `uri` +- receipt-derived locator fields: `chainId`, `blockNumber`, `blockHash`, + `txHash`, `transactionIndex`, `logIndex`, `receiptStatus` + +Generated `RootflowTransition` objects now include `contractEventRef`, a compact +reference back to the event that produced the transition's MemorySignal. + +The dashboard may display this event spine for launch demos, but it must remain +fixture-backed until a separate live indexing/API decision is accepted. + +## Boundaries + +- Contracts do not know `txHash`, `transactionIndex`, `logIndex`, `blockHash`, + or receipt status during execution. +- Indexers derive receipt locator fields after reading receipts and logs. +- This is not a production Uniswap v4 deployment. +- This is not a production L1, production mainnet readiness, full trustless + verification, free storage, or AI running on-chain. + +## Consequences + +- Reviewers can trace MemorySignals and RootflowTransitions back to concrete + contract event semantics. +- Dashboard demos can show the full local path from `FlowPulse` to agent memory + without implying that heavy memory data lives on-chain. +- Future live indexing work must preserve the same emitted-vs-derived boundary. diff --git a/docs/FLOW_MEMORY_V0.md b/docs/FLOW_MEMORY_V0.md index 39875d28..00782a40 100644 --- a/docs/FLOW_MEMORY_V0.md +++ b/docs/FLOW_MEMORY_V0.md @@ -46,18 +46,40 @@ Minimum V0 fields: "signalType": "root_commitment|swap_activity|failure|repair|evaluation|hardware_heartbeat|unsupported", "subject": "bytes32-or-hex-string", "commitment": "bytes32-or-hex-string", - "source": { - "chainId": 84532, - "contractAddress": "0x...", - "blockNumber": 1, - "blockHash": "0x...", - "txHash": "0x...", - "logIndex": 0 + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "pulseTypeName": "ROOT_COMMITTED", + "indexed": { + "pulseId": "bytes32-or-hex-string", + "rootfieldId": "bytes32-or-hex-string", + "actor": "0x..." + }, + "payload": { + "subject": "bytes32-or-hex-string", + "commitment": "bytes32-or-hex-string", + "parentPulseId": "bytes32-or-hex-string", + "sequence": "2" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123457", + "txHash": "0x...", + "logIndex": "3" + } }, "status": "observed|pending|verified|failed|reorged|unsupported" } ``` +`contractEvent` is intentionally split between contract-emitted event fields and +receipt-derived locator fields. `IFlowPulse` emits `pulseId`, `rootfieldId`, +`actor`, `pulseType`, `subject`, `commitment`, `parentPulseId`, `sequence`, +`occurredAt`, and `uri`; the indexer adds `txHash`, `logIndex`, block metadata, +and receipt status after receipts/logs exist. + ### MemoryReceipt A `MemoryReceipt` links a signal to evidence, commitments, and verifier output. @@ -142,6 +164,7 @@ Allowed: - "This swap or fixture produced a FlowPulse." - "The indexer observed the pulse and derived receipt metadata." +- "This MemorySignal is linked to `IFlowPulse.FlowPulse` event semantics." - "The verifier produced a V0 report." - "Rootflow moved this Rootfield from one committed root to another." - "This AgentMemoryView exposes verified and pending memory signals." diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index fecc8833..3bd7a1be 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -14,6 +14,7 @@ The launch-core V0 stack means: - FlowPulse fixtures can be produced or consumed deterministically. - Rootflow transitions link FlowPulse observations, parent state, receipts, verifier reports, and new roots. - Flow Memory objects expose MemorySignal, MemoryReceipt, RootfieldBundle, and AgentMemoryView shapes. +- MemorySignals and RootflowTransitions preserve explicit `IFlowPulse.FlowPulse` contract-event semantics while keeping receipt-only fields indexer-derived. - Indexer/verifier specs define observation identity, reorg states, and report shape. - Crypto vocabulary defines receipts, attestations, roots, commitments, and proof boundaries. - Dashboard can consume fixture-backed observed, pending, verified, failed, unsupported, and reorged states. @@ -60,6 +61,7 @@ Status: implemented as fixture-first services plus generated launch-core state; - Verifier statuses and report JSON schema exist for local fixture reports. - Rootflow transition schema and parent/child state-linking behavior exist as generated local fixtures. - Flow Memory schemas for MemorySignal, MemoryReceipt, RootfieldBundle, and AgentMemoryView exist under `schemas/flowmemory/`. +- Generated MemorySignal and RootflowTransition fixtures expose contract-event linkage through `contractEvent` and `contractEventRef`. - Fixture-based parser and reorg-state tests exist in the indexer/verifier packages. - Define persistence and local RPC reader boundaries only after fixture behavior stabilizes. - Local devnet smoke-test gates exist as a no-value Rust prototype, without mainnet or production deployment. @@ -92,6 +94,7 @@ Status: implemented as a generated fixture-backed local app. - App-facing entities exist in `apps/dashboard`. - Observed, pending, finalized, verified, failed, unresolved, unsupported, reorged, offline, and stale states are modeled for display. - Dashboard renders local fixture views for overview, Flow Memory / Rootflow, FlowPulse stream, Rootfields, work receipts, verifier reports, devnet blocks, hardware nodes, alerts, and raw JSON. +- The Flow Memory / Rootflow view includes launch-demo summaries for contract event linkage, transition status counts, root bundle state, and agent memory warnings. - The dashboard fixture is generated from services, local devnet, and hardware POC outputs by `npm run launch:v0`. - Keep hosted production APIs and deployment out of scope until the local stack stabilizes. diff --git a/docs/ROOTFLOW_V0.md b/docs/ROOTFLOW_V0.md index cbf17d56..bab6bcf5 100644 --- a/docs/ROOTFLOW_V0.md +++ b/docs/ROOTFLOW_V0.md @@ -73,24 +73,31 @@ Every Rootflow transition must be expressible with this canonical shape: "sequence": 1, "observedAt": "iso-8601-or-block-time", "updatedAt": "iso-8601", - "source": { - "chainId": 84532, - "contractAddress": "0x...", - "blockNumber": 1, - "blockHash": "0x...", + "contractEventRef": { + "signalId": "bytes32-or-hex-string", + "eventName": "FlowPulse", + "eventTopic0": "bytes32-or-hex-string", + "sourceContract": "0x...", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", "txHash": "0x...", - "logIndex": 0 + "logIndex": "3" } } ``` -The exact JSON schema may live in the crypto or indexer package, but the fields above are the V0 minimum. +The canonical local/test JSON schema lives at +`schemas/flowmemory/rootflow-transition.schema.json`. `contractEventRef` +keeps each transition tied to the `IFlowPulse.FlowPulse` event that produced its +MemorySignal while preserving the boundary that `txHash` and `logIndex` are +indexer-derived after receipts/logs exist. ## Invariants - A transition must belong to exactly one `rootfieldId`. - A transition must link to one `pulseId`. - A transition must identify its source observation after the indexer reads receipts and logs. +- A transition must include enough contract-event reference data for a dashboard or reviewer to map it back to `IFlowPulse.FlowPulse` semantics. - A contract must not claim final `txHash` or `logIndex` during execution. - Heavy memory, model, evaluation, media, and artifact data stays off-chain. - On-chain state stores compact roots, commitments, receipts, counters, and intentional protocol state only. diff --git a/docs/V0_LAUNCH_ACCEPTANCE.md b/docs/V0_LAUNCH_ACCEPTANCE.md index 25a0a8a1..7fa2f54a 100644 --- a/docs/V0_LAUNCH_ACCEPTANCE.md +++ b/docs/V0_LAUNCH_ACCEPTANCE.md @@ -35,6 +35,7 @@ It must not claim production L1, production mainnet readiness, full trustless ve | Root commitments | Contract or fixture commits a nonzero root and emits/records the update. | Contracts | Implemented for local/test V0 in contracts and generated fixtures. | | Parent/child transitions | `RootflowTransition` includes parent pulse/root and new root. | Indexer + Crypto + Contracts | Implemented in `fixtures/launch-core/rootflow-transitions.json`. | | FlowPulse linkage | Transition and memory signal reference `pulseId`. | Indexer + Dashboard | Implemented in generated MemorySignals and RootflowTransitions. | +| Contract event semantics | Generated MemorySignals preserve `IFlowPulse.FlowPulse` event signature, indexed fields, payload fields, pulse type, and receipt-derived locator fields. | Contracts + Indexer + Dashboard | Implemented with `contractEvent` and `contractEventRef` fields in launch-core fixtures and dashboard data. | | Receipt linkage | `MemoryReceipt` links signal, artifact commitment, evidence URI, and verifier report. | Crypto + Indexer | Implemented in `fixtures/launch-core/flowmemory-launch-v0.json`. | | Verifier statuses | Cross-agent status vocabulary exists and verifier reports use it. | Indexer + Crypto | Implemented with explicit adapter in `services/flowmemory/src/status.ts`. | | Pending state | Fixture/report can show pending transition. | Indexer + Dashboard | Implemented in generated dashboard fixture. | @@ -75,6 +76,7 @@ Contracts to indexer: - RootfieldRegistry ABI. - local deployment or fixture event output. - contract tests showing root registration and root commitment. +- pulse type semantics for `ROOTFIELD_REGISTERED`, `ROOT_COMMITTED`, and `ROOTFIELD_STATUS_CHANGED`. Crypto to indexer: diff --git a/docs/reviews/ROOTFLOW_FLOW_MEMORY_V0_ACCEPTANCE_AUDIT.md b/docs/reviews/ROOTFLOW_FLOW_MEMORY_V0_ACCEPTANCE_AUDIT.md index 1adcfe26..ce77f912 100644 --- a/docs/reviews/ROOTFLOW_FLOW_MEMORY_V0_ACCEPTANCE_AUDIT.md +++ b/docs/reviews/ROOTFLOW_FLOW_MEMORY_V0_ACCEPTANCE_AUDIT.md @@ -45,6 +45,20 @@ Generated outputs: - `apps/dashboard/public/data/flowmemory-dashboard-v0.json` - `fixtures/launch-core/generated/devnet/` +Launch-hardening evidence: + +- Generated `MemorySignal` objects now embed `contractEvent` data for + `IFlowPulse.FlowPulse`, including event signature text, topic0, pulse type, + indexed fields, payload fields, and receipt-derived locator fields. +- Generated `RootflowTransition` objects now include `contractEventRef` so a + dashboard or reviewer can map each transition back to the contract event + semantics that produced the signal. +- The Flow Memory / Rootflow dashboard view now includes a contract-event spine, + transition status counts, root bundle summary, and agent memory warnings for + launch demo review. +- `docs/reviews/V0_BOUNDARY_CLAIMS_AUDIT.md` records the latest review pass for + blocked production, storage, trustlessness, hardware, and AI-on-chain claims. + Canonical schemas: - `schemas/flowmemory/memory-signal.schema.json` @@ -76,6 +90,7 @@ These commands were run from merged `main` on 2026-05-13. | Root commitments | `submitRoot`, counters, latest root storage, FlowPulse emission, tests. | Implemented for V0 local contracts. | | Parent/child memory-state transitions | `fixtures/launch-core/rootflow-transitions.json` contains generated RootflowTransition objects with parent pulse and parent transition links. | Implemented for local/test V0. | | FlowPulse linkage | Contracts emit FlowPulse; services parse fixture logs and generated MemorySignals reference pulse/observation ids. | Implemented for local/test V0. | +| Contract event semantics | Generated MemorySignals and RootflowTransitions expose `IFlowPulse.FlowPulse` event metadata, indexed fields, payload fields, and receipt locator fields. | Implemented for local/test V0. | | Receipt linkage | Generated MemoryReceipts link verifier reports to observations/rootfields. | Implemented for local/test V0. | | Verifier status | `services/flowmemory/src/status.ts` maps `valid`/`invalid` to `verified`/`failed`. | Implemented. | | Pending/verified/failed/reorged states | Generated dashboard fixture includes observed, pending, finalized, verified, failed, unresolved, unsupported, reorged, offline, and stale. | Implemented for local/test V0. | @@ -108,9 +123,9 @@ Not part of local/test V0 completion: - Agent/worktree: Contracts Agent in `E:\FlowMemory\flowmemory-contracts`. - Owns: Slither setup issue, owner/status boundary review, test gaps. -3. `[dashboard/polish] Polish generated Flow Memory / Rootflow dashboard view` +3. `[dashboard/polish] Add deeper generated object inspection` - Agent/worktree: Dashboard Agent in `E:\FlowMemory\flowmemory-dashboard`. - - Owns: visual polish, better filtering, generated object inspection, no live API claims. + - Owns: drilldown views, generated object inspection, no live API claims. ## Current Recommendation diff --git a/docs/reviews/V0_BOUNDARY_CLAIMS_AUDIT.md b/docs/reviews/V0_BOUNDARY_CLAIMS_AUDIT.md new file mode 100644 index 00000000..df5c96f2 --- /dev/null +++ b/docs/reviews/V0_BOUNDARY_CLAIMS_AUDIT.md @@ -0,0 +1,52 @@ +# V0 Boundary Claims Audit + +Date: 2026-05-13 + +Status: pass for the current launch-core documentation set. + +## Scope Reviewed + +Reviewed the launch-facing source-of-truth docs and generated local/test V0 +surfaces for unsafe production claims: + +- `README.md` +- `docs/CURRENT_STATE.md` +- `docs/ROADMAP.md` +- `docs/ARCHITECTURE.md` +- `docs/ROOTFLOW_V0.md` +- `docs/FLOW_MEMORY_V0.md` +- `docs/V0_LAUNCH_ACCEPTANCE.md` +- `docs/SECURITY_MODEL.md` +- `docs/reviews/ROOTFLOW_FLOW_MEMORY_V0_ACCEPTANCE_AUDIT.md` +- `apps/dashboard/README.md` +- generated launch-core and dashboard fixture descriptions + +## Claims That Remain Allowed + +- FlowMemory has a local/test V0 launch-core path. +- `npm run launch:v0` regenerates fixture-backed Rootflow and Flow Memory state. +- Contracts emit compact `FlowPulse` events. +- Indexers derive receipt coordinates such as `txHash` and `logIndex` after + receipts/logs exist. +- Verifiers produce local/test V0 reports. +- The dashboard renders generated fixture data. + +## Claims That Remain Blocked + +- FlowMemory is a production L1 or mainnet-ready chain. +- FlowMemory has production Uniswap v4 hook deployment. +- FlowMemory provides full trustless verification. +- FlowMemory provides free on-chain storage. +- AI runs on-chain. +- Transaction hashes store arbitrary memory data. +- Hardware is manufactured, field-deployed, or fully trustless. +- Meshtastic/LoRa provides normal internet bandwidth. + +## Result + +No launch-facing source-of-truth doc reviewed here claims production L1, +production mainnet readiness, full trustless verification, free storage, or AI +running on-chain. + +Keep this audit updated whenever docs, dashboard copy, README language, or +generated fixture descriptions change in a way that affects launch claims. diff --git a/fixtures/dashboard/flowmemory-dashboard-v0.json b/fixtures/dashboard/flowmemory-dashboard-v0.json index f84df74f..299c9566 100644 --- a/fixtures/dashboard/flowmemory-dashboard-v0.json +++ b/fixtures/dashboard/flowmemory-dashboard-v0.json @@ -666,6 +666,16 @@ "txHash": "0x3333333333333333333333333333333333333333333333333333333333333333", "sequence": "1", "reasonCodes": [], + "contractEventRef": { + "signalId": "0xec2a80963190d2fa4d0eae023e735eeaf770cf33496eabdea696f3c7dda071eb", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "1", + "pulseTypeName": "ROOTFIELD_REGISTERED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333333", + "logIndex": "2" + }, "id": "0x29fcee50b38bf403556ea08db7faeda6ea50430c08fc3126cebffad4a7657522", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -696,6 +706,16 @@ "txHash": "0x3333333333333333333333333333333333333333333333333333333333333334", "sequence": "2", "reasonCodes": [], + "contractEventRef": { + "signalId": "0xc595baea5e90a5f06ff49d8afeea0996eb39e13b3794903b8142dc9daf3a2df0", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333334", + "logIndex": "3" + }, "id": "0x5cdf7f5498350650adc19c62828425723a09bcca6571774992ca2d013fdc1068", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -728,6 +748,16 @@ "reasonCodes": [ "observation.reorged" ], + "contractEventRef": { + "signalId": "0x4699ec901e15d260417fd6a9a86357c179ac55b631df05f28b29f28d5a5f3b61", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333335", + "logIndex": "4" + }, "id": "0xe1b6f858279961c968cdfba0b85d489767c486289e824cab3d017997064fed89", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -760,6 +790,16 @@ "reasonCodes": [ "commitment.mismatch" ], + "contractEventRef": { + "signalId": "0xe32d6eeeff9c6bafadca56b980d58159afe8ffb29184458fa589c890829b9627", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333336", + "logIndex": "5" + }, "id": "0x35db5f8c36e2bc988c4d60f25a2e60d971256bdfdb79a73c92c0b82a41e5a367", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -792,6 +832,16 @@ "reasonCodes": [ "artifact.unavailable" ], + "contractEventRef": { + "signalId": "0xfdc7756ac00683bc3e85bb3a9c2bd01f9719667b2d739818591fe697ee45d6c4", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333337", + "logIndex": "6" + }, "id": "0x31d44377aa98e7fcaa07110256e1600249c4337c69e6d06c14d36e6aad6a79c4", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -824,6 +874,16 @@ "reasonCodes": [ "pulse.type.unsupported" ], + "contractEventRef": { + "signalId": "0x74f686fdd91352713b0e1f74f8218d8e41359b67634f8c8be6cbafe15f7f95d5", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "99", + "pulseTypeName": "UNKNOWN_FLOWPULSE_TYPE", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333338", + "logIndex": "7" + }, "id": "0xdc9a57620b3309aceee35e858f62650b565e5f17ec6d9218ffd653ef5a633cdf", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -860,6 +920,47 @@ "occurredAt": "2026-05-13T02:40:00.000Z", "uri": "ipfs://bafy-flowmemory-example", "summary": "rootfield registration pulse 1", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "1", + "pulseTypeName": "ROOTFIELD_REGISTERED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "commitment": "0x4122209ff672fc04b2ec3af31ab1af79813971f86de000aa6534038cc79de6b5", + "parentPulseId": "0x0000000000000000000000000000000000000000000000000000000000000000", + "sequence": "1", + "occurredAt": "2026-05-13T02:40:00.000Z", + "uri": "ipfs://bafy-flowmemory-example" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123456", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222222", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333333", + "transactionIndex": "7", + "logIndex": "2", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + }, "id": "0xec2a80963190d2fa4d0eae023e735eeaf770cf33496eabdea696f3c7dda071eb", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -894,6 +995,47 @@ "occurredAt": "2026-05-13T02:40:00.000Z", "uri": "ipfs://bafy-flowmemory-example", "summary": "rootfield registration pulse 1", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "1", + "pulseTypeName": "ROOTFIELD_REGISTERED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "commitment": "0x4122209ff672fc04b2ec3af31ab1af79813971f86de000aa6534038cc79de6b5", + "parentPulseId": "0x0000000000000000000000000000000000000000000000000000000000000000", + "sequence": "1", + "occurredAt": "2026-05-13T02:40:00.000Z", + "uri": "ipfs://bafy-flowmemory-example" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123456", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222222", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333333", + "transactionIndex": "7", + "logIndex": "2", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + }, "id": "0xec2a80963190d2fa4d0eae023e735eeaf770cf33496eabdea696f3c7dda071eb", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -928,6 +1070,47 @@ "occurredAt": "2026-05-13T02:41:00.000Z", "uri": "fixture://root-commit-valid", "summary": "root commitment pulse 2", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab001", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1", + "commitment": "0x69a9f953179a6ce2e08724dd759fb71b08b0759a5900fc0399a753ecf0557df5", + "parentPulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sequence": "2", + "occurredAt": "2026-05-13T02:41:00.000Z", + "uri": "fixture://root-commit-valid" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123457", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222223", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333334", + "transactionIndex": "8", + "logIndex": "3", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + }, "id": "0xc595baea5e90a5f06ff49d8afeea0996eb39e13b3794903b8142dc9daf3a2df0", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -962,6 +1145,47 @@ "occurredAt": "2026-05-13T02:41:00.000Z", "uri": "fixture://root-commit-valid", "summary": "root commitment pulse 2", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab002", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1", + "commitment": "0x69a9f953179a6ce2e08724dd759fb71b08b0759a5900fc0399a753ecf0557df5", + "parentPulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sequence": "2", + "occurredAt": "2026-05-13T02:41:00.000Z", + "uri": "fixture://root-commit-valid" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123458", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222224", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333335", + "transactionIndex": "9", + "logIndex": "4", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + }, "id": "0x4699ec901e15d260417fd6a9a86357c179ac55b631df05f28b29f28d5a5f3b61", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -996,6 +1220,47 @@ "occurredAt": "2026-05-13T02:42:00.000Z", "uri": "fixture://root-commit-valid", "summary": "root commitment pulse 3", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab003", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1", + "commitment": "0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", + "parentPulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sequence": "3", + "occurredAt": "2026-05-13T02:42:00.000Z", + "uri": "fixture://root-commit-valid" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123459", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222225", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333336", + "transactionIndex": "10", + "logIndex": "5", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + }, "id": "0xe32d6eeeff9c6bafadca56b980d58159afe8ffb29184458fa589c890829b9627", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -1030,6 +1295,47 @@ "occurredAt": "2026-05-13T02:43:00.000Z", "uri": "fixture://missing-artifact", "summary": "root commitment pulse 4", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab004", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1", + "commitment": "0x69a9f953179a6ce2e08724dd759fb71b08b0759a5900fc0399a753ecf0557df5", + "parentPulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sequence": "4", + "occurredAt": "2026-05-13T02:43:00.000Z", + "uri": "fixture://missing-artifact" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123460", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222226", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333337", + "transactionIndex": "11", + "logIndex": "6", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + }, "id": "0xfdc7756ac00683bc3e85bb3a9c2bd01f9719667b2d739818591fe697ee45d6c4", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { @@ -1064,6 +1370,47 @@ "occurredAt": "2026-05-13T02:44:00.000Z", "uri": "fixture://unsupported", "summary": "unsupported pulse pulse 5", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "99", + "pulseTypeName": "UNKNOWN_FLOWPULSE_TYPE", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab005", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1", + "commitment": "0x69a9f953179a6ce2e08724dd759fb71b08b0759a5900fc0399a753ecf0557df5", + "parentPulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sequence": "5", + "occurredAt": "2026-05-13T02:44:00.000Z", + "uri": "fixture://unsupported" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123461", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222227", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333338", + "transactionIndex": "12", + "logIndex": "7", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + }, "id": "0x74f686fdd91352713b0e1f74f8218d8e41359b67634f8c8be6cbafe15f7f95d5", "lastUpdated": "2026-05-13T17:02:00.000Z", "provenance": { diff --git a/fixtures/launch-core/flowmemory-launch-v0.json b/fixtures/launch-core/flowmemory-launch-v0.json index 08172325..f5298b92 100644 --- a/fixtures/launch-core/flowmemory-launch-v0.json +++ b/fixtures/launch-core/flowmemory-launch-v0.json @@ -38,7 +38,48 @@ "sequence": "1", "occurredAt": "2026-05-13T02:40:00.000Z", "uri": "ipfs://bafy-flowmemory-example", - "summary": "rootfield registration pulse 1" + "summary": "rootfield registration pulse 1", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "1", + "pulseTypeName": "ROOTFIELD_REGISTERED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "commitment": "0x4122209ff672fc04b2ec3af31ab1af79813971f86de000aa6534038cc79de6b5", + "parentPulseId": "0x0000000000000000000000000000000000000000000000000000000000000000", + "sequence": "1", + "occurredAt": "2026-05-13T02:40:00.000Z", + "uri": "ipfs://bafy-flowmemory-example" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123456", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222222", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333333", + "transactionIndex": "7", + "logIndex": "2", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + } }, { "schema": "flowmemory.memory_signal.v0", @@ -62,7 +103,48 @@ "sequence": "1", "occurredAt": "2026-05-13T02:40:00.000Z", "uri": "ipfs://bafy-flowmemory-example", - "summary": "rootfield registration pulse 1" + "summary": "rootfield registration pulse 1", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "1", + "pulseTypeName": "ROOTFIELD_REGISTERED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "commitment": "0x4122209ff672fc04b2ec3af31ab1af79813971f86de000aa6534038cc79de6b5", + "parentPulseId": "0x0000000000000000000000000000000000000000000000000000000000000000", + "sequence": "1", + "occurredAt": "2026-05-13T02:40:00.000Z", + "uri": "ipfs://bafy-flowmemory-example" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123456", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222222", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333333", + "transactionIndex": "7", + "logIndex": "2", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + } }, { "schema": "flowmemory.memory_signal.v0", @@ -86,7 +168,48 @@ "sequence": "2", "occurredAt": "2026-05-13T02:41:00.000Z", "uri": "fixture://root-commit-valid", - "summary": "root commitment pulse 2" + "summary": "root commitment pulse 2", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab001", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1", + "commitment": "0x69a9f953179a6ce2e08724dd759fb71b08b0759a5900fc0399a753ecf0557df5", + "parentPulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sequence": "2", + "occurredAt": "2026-05-13T02:41:00.000Z", + "uri": "fixture://root-commit-valid" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123457", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222223", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333334", + "transactionIndex": "8", + "logIndex": "3", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + } }, { "schema": "flowmemory.memory_signal.v0", @@ -110,7 +233,48 @@ "sequence": "2", "occurredAt": "2026-05-13T02:41:00.000Z", "uri": "fixture://root-commit-valid", - "summary": "root commitment pulse 2" + "summary": "root commitment pulse 2", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab002", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1", + "commitment": "0x69a9f953179a6ce2e08724dd759fb71b08b0759a5900fc0399a753ecf0557df5", + "parentPulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sequence": "2", + "occurredAt": "2026-05-13T02:41:00.000Z", + "uri": "fixture://root-commit-valid" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123458", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222224", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333335", + "transactionIndex": "9", + "logIndex": "4", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + } }, { "schema": "flowmemory.memory_signal.v0", @@ -134,7 +298,48 @@ "sequence": "3", "occurredAt": "2026-05-13T02:42:00.000Z", "uri": "fixture://root-commit-valid", - "summary": "root commitment pulse 3" + "summary": "root commitment pulse 3", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab003", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1", + "commitment": "0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", + "parentPulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sequence": "3", + "occurredAt": "2026-05-13T02:42:00.000Z", + "uri": "fixture://root-commit-valid" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123459", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222225", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333336", + "transactionIndex": "10", + "logIndex": "5", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + } }, { "schema": "flowmemory.memory_signal.v0", @@ -158,7 +363,48 @@ "sequence": "4", "occurredAt": "2026-05-13T02:43:00.000Z", "uri": "fixture://missing-artifact", - "summary": "root commitment pulse 4" + "summary": "root commitment pulse 4", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab004", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1", + "commitment": "0x69a9f953179a6ce2e08724dd759fb71b08b0759a5900fc0399a753ecf0557df5", + "parentPulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sequence": "4", + "occurredAt": "2026-05-13T02:43:00.000Z", + "uri": "fixture://missing-artifact" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123460", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222226", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333337", + "transactionIndex": "11", + "logIndex": "6", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + } }, { "schema": "flowmemory.memory_signal.v0", @@ -182,7 +428,48 @@ "sequence": "5", "occurredAt": "2026-05-13T02:44:00.000Z", "uri": "fixture://unsupported", - "summary": "unsupported pulse pulse 5" + "summary": "unsupported pulse pulse 5", + "contractEvent": { + "schema": "flowmemory.flowpulse_contract_event.v0", + "interfaceName": "IFlowPulse", + "eventName": "FlowPulse", + "eventSignatureText": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "expectedTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "topicMatchesContract": true, + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "99", + "pulseTypeName": "UNKNOWN_FLOWPULSE_TYPE", + "indexed": { + "pulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab005", + "rootfieldId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "actor": "0x4444444444444444444444444444444444444444" + }, + "payload": { + "subject": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1", + "commitment": "0x69a9f953179a6ce2e08724dd759fb71b08b0759a5900fc0399a753ecf0557df5", + "parentPulseId": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sequence": "5", + "occurredAt": "2026-05-13T02:44:00.000Z", + "uri": "fixture://unsupported" + }, + "receiptLocator": { + "chainId": "8453", + "blockNumber": "123461", + "blockHash": "0x2222222222222222222222222222222222222222222222222222222222222227", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333338", + "transactionIndex": "12", + "logIndex": "7", + "receiptStatus": "success" + }, + "receiptDerivedFields": [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus" + ] + } } ], "memoryReceipts": [ @@ -346,7 +633,17 @@ "blockNumber": "123456", "txHash": "0x3333333333333333333333333333333333333333333333333333333333333333", "sequence": "1", - "reasonCodes": [] + "reasonCodes": [], + "contractEventRef": { + "signalId": "0xec2a80963190d2fa4d0eae023e735eeaf770cf33496eabdea696f3c7dda071eb", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "1", + "pulseTypeName": "ROOTFIELD_REGISTERED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333333", + "logIndex": "2" + } }, { "schema": "flowmemory.rootflow_transition.v0", @@ -366,7 +663,17 @@ "blockNumber": "123457", "txHash": "0x3333333333333333333333333333333333333333333333333333333333333334", "sequence": "2", - "reasonCodes": [] + "reasonCodes": [], + "contractEventRef": { + "signalId": "0xc595baea5e90a5f06ff49d8afeea0996eb39e13b3794903b8142dc9daf3a2df0", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333334", + "logIndex": "3" + } }, { "schema": "flowmemory.rootflow_transition.v0", @@ -388,7 +695,17 @@ "sequence": "2", "reasonCodes": [ "observation.reorged" - ] + ], + "contractEventRef": { + "signalId": "0x4699ec901e15d260417fd6a9a86357c179ac55b631df05f28b29f28d5a5f3b61", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333335", + "logIndex": "4" + } }, { "schema": "flowmemory.rootflow_transition.v0", @@ -410,7 +727,17 @@ "sequence": "3", "reasonCodes": [ "commitment.mismatch" - ] + ], + "contractEventRef": { + "signalId": "0xe32d6eeeff9c6bafadca56b980d58159afe8ffb29184458fa589c890829b9627", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333336", + "logIndex": "5" + } }, { "schema": "flowmemory.rootflow_transition.v0", @@ -432,7 +759,17 @@ "sequence": "4", "reasonCodes": [ "artifact.unavailable" - ] + ], + "contractEventRef": { + "signalId": "0xfdc7756ac00683bc3e85bb3a9c2bd01f9719667b2d739818591fe697ee45d6c4", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333337", + "logIndex": "6" + } }, { "schema": "flowmemory.rootflow_transition.v0", @@ -454,7 +791,17 @@ "sequence": "5", "reasonCodes": [ "pulse.type.unsupported" - ] + ], + "contractEventRef": { + "signalId": "0x74f686fdd91352713b0e1f74f8218d8e41359b67634f8c8be6cbafe15f7f95d5", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "99", + "pulseTypeName": "UNKNOWN_FLOWPULSE_TYPE", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333338", + "logIndex": "7" + } } ], "rootfieldBundles": [ diff --git a/fixtures/launch-core/rootflow-transitions.json b/fixtures/launch-core/rootflow-transitions.json index 51e46310..a73b43db 100644 --- a/fixtures/launch-core/rootflow-transitions.json +++ b/fixtures/launch-core/rootflow-transitions.json @@ -20,7 +20,17 @@ "blockNumber": "123456", "txHash": "0x3333333333333333333333333333333333333333333333333333333333333333", "sequence": "1", - "reasonCodes": [] + "reasonCodes": [], + "contractEventRef": { + "signalId": "0xec2a80963190d2fa4d0eae023e735eeaf770cf33496eabdea696f3c7dda071eb", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "1", + "pulseTypeName": "ROOTFIELD_REGISTERED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333333", + "logIndex": "2" + } }, { "schema": "flowmemory.rootflow_transition.v0", @@ -40,7 +50,17 @@ "blockNumber": "123457", "txHash": "0x3333333333333333333333333333333333333333333333333333333333333334", "sequence": "2", - "reasonCodes": [] + "reasonCodes": [], + "contractEventRef": { + "signalId": "0xc595baea5e90a5f06ff49d8afeea0996eb39e13b3794903b8142dc9daf3a2df0", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333334", + "logIndex": "3" + } }, { "schema": "flowmemory.rootflow_transition.v0", @@ -62,7 +82,17 @@ "sequence": "2", "reasonCodes": [ "observation.reorged" - ] + ], + "contractEventRef": { + "signalId": "0x4699ec901e15d260417fd6a9a86357c179ac55b631df05f28b29f28d5a5f3b61", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333335", + "logIndex": "4" + } }, { "schema": "flowmemory.rootflow_transition.v0", @@ -84,7 +114,17 @@ "sequence": "3", "reasonCodes": [ "commitment.mismatch" - ] + ], + "contractEventRef": { + "signalId": "0xe32d6eeeff9c6bafadca56b980d58159afe8ffb29184458fa589c890829b9627", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333336", + "logIndex": "5" + } }, { "schema": "flowmemory.rootflow_transition.v0", @@ -106,7 +146,17 @@ "sequence": "4", "reasonCodes": [ "artifact.unavailable" - ] + ], + "contractEventRef": { + "signalId": "0xfdc7756ac00683bc3e85bb3a9c2bd01f9719667b2d739818591fe697ee45d6c4", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "2", + "pulseTypeName": "ROOT_COMMITTED", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333337", + "logIndex": "6" + } }, { "schema": "flowmemory.rootflow_transition.v0", @@ -128,7 +178,17 @@ "sequence": "5", "reasonCodes": [ "pulse.type.unsupported" - ] + ], + "contractEventRef": { + "signalId": "0x74f686fdd91352713b0e1f74f8218d8e41359b67634f8c8be6cbafe15f7f95d5", + "eventName": "FlowPulse", + "eventTopic0": "0x5d07190b9ae441b4d7b16259a48424acd451492b12f5f99a29f5bfd992c13e43", + "sourceContract": "0x1111111111111111111111111111111111111111", + "pulseTypeId": "99", + "pulseTypeName": "UNKNOWN_FLOWPULSE_TYPE", + "txHash": "0x3333333333333333333333333333333333333333333333333333333333333338", + "logIndex": "7" + } } ] } diff --git a/schemas/flowmemory/README.md b/schemas/flowmemory/README.md index 014792b6..d3650385 100644 --- a/schemas/flowmemory/README.md +++ b/schemas/flowmemory/README.md @@ -8,4 +8,9 @@ These schemas are the canonical local/test V0 shapes for generated Flow Memory a - `rootfield-bundle.schema.json` - `agent-memory-view.schema.json` +`memory-signal.schema.json` also embeds the `flowmemory.flowpulse_contract_event.v0` +shape, which records the `IFlowPulse.FlowPulse` event signature, indexed fields, +payload fields, and receipt-derived locator fields that the indexer added after +reading logs and receipts. + They describe local fixture objects only. They do not claim production L1 readiness, trustless verification, free storage, AI running on-chain, or production Uniswap v4 deployment. diff --git a/schemas/flowmemory/memory-signal.schema.json b/schemas/flowmemory/memory-signal.schema.json index 62a83078..1883568e 100644 --- a/schemas/flowmemory/memory-signal.schema.json +++ b/schemas/flowmemory/memory-signal.schema.json @@ -26,7 +26,8 @@ "sequence", "occurredAt", "uri", - "summary" + "summary", + "contractEvent" ], "properties": { "schema": { "const": "flowmemory.memory_signal.v0" }, @@ -50,11 +51,89 @@ "sequence": { "type": "string", "pattern": "^[0-9]+$" }, "occurredAt": { "type": "string", "format": "date-time" }, "uri": { "type": "string" }, - "summary": { "type": "string" } + "summary": { "type": "string" }, + "contractEvent": { "$ref": "#/$defs/flowPulseContractEvent" } }, "$defs": { "hex32": { "type": "string", "pattern": "^0x[0-9a-fA-F]{64}$" }, "address": { "type": "string", "pattern": "^0x[0-9a-fA-F]{40}$" }, + "flowPulseContractTypeName": { + "enum": ["ROOTFIELD_REGISTERED", "ROOT_COMMITTED", "ROOTFIELD_STATUS_CHANGED", "UNKNOWN_FLOWPULSE_TYPE"] + }, + "flowPulseContractEvent": { + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "interfaceName", + "eventName", + "eventSignatureText", + "eventTopic0", + "expectedTopic0", + "topicMatchesContract", + "sourceContract", + "pulseTypeId", + "pulseTypeName", + "indexed", + "payload", + "receiptLocator", + "receiptDerivedFields" + ], + "properties": { + "schema": { "const": "flowmemory.flowpulse_contract_event.v0" }, + "interfaceName": { "const": "IFlowPulse" }, + "eventName": { "const": "FlowPulse" }, + "eventSignatureText": { "const": "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)" }, + "eventTopic0": { "$ref": "#/$defs/hex32" }, + "expectedTopic0": { "$ref": "#/$defs/hex32" }, + "topicMatchesContract": { "type": "boolean" }, + "sourceContract": { "$ref": "#/$defs/address" }, + "pulseTypeId": { "type": "string", "pattern": "^[0-9]+$" }, + "pulseTypeName": { "$ref": "#/$defs/flowPulseContractTypeName" }, + "indexed": { + "type": "object", + "additionalProperties": false, + "required": ["pulseId", "rootfieldId", "actor"], + "properties": { + "pulseId": { "$ref": "#/$defs/hex32" }, + "rootfieldId": { "$ref": "#/$defs/hex32" }, + "actor": { "$ref": "#/$defs/address" } + } + }, + "payload": { + "type": "object", + "additionalProperties": false, + "required": ["subject", "commitment", "parentPulseId", "sequence", "occurredAt", "uri"], + "properties": { + "subject": { "$ref": "#/$defs/hex32" }, + "commitment": { "$ref": "#/$defs/hex32" }, + "parentPulseId": { "$ref": "#/$defs/hex32" }, + "sequence": { "type": "string", "pattern": "^[0-9]+$" }, + "occurredAt": { "type": "string", "format": "date-time" }, + "uri": { "type": "string" } + } + }, + "receiptLocator": { + "type": "object", + "additionalProperties": false, + "required": ["chainId", "blockNumber", "blockHash", "txHash", "transactionIndex", "logIndex", "receiptStatus"], + "properties": { + "chainId": { "type": "string", "minLength": 1 }, + "blockNumber": { "type": "string", "pattern": "^[0-9]+$" }, + "blockHash": { "$ref": "#/$defs/hex32" }, + "txHash": { "$ref": "#/$defs/hex32" }, + "transactionIndex": { "type": "string", "pattern": "^[0-9]+$" }, + "logIndex": { "type": "string", "pattern": "^[0-9]+$" }, + "receiptStatus": { "enum": ["success", "reverted", "unknown"] } + } + }, + "receiptDerivedFields": { + "type": "array", + "items": { "type": "string" }, + "minItems": 1 + } + } + }, "flowMemoryStatus": { "enum": ["observed", "pending", "finalized", "verified", "unresolved", "failed", "unsupported", "reorged", "offline", "stale"] } diff --git a/schemas/flowmemory/rootflow-transition.schema.json b/schemas/flowmemory/rootflow-transition.schema.json index c6742b3e..5f5a1a38 100644 --- a/schemas/flowmemory/rootflow-transition.schema.json +++ b/schemas/flowmemory/rootflow-transition.schema.json @@ -22,7 +22,8 @@ "blockNumber", "txHash", "sequence", - "reasonCodes" + "reasonCodes", + "contractEventRef" ], "properties": { "schema": { "const": "flowmemory.rootflow_transition.v0" }, @@ -42,10 +43,30 @@ "blockNumber": { "type": "string", "pattern": "^[0-9]+$" }, "txHash": { "$ref": "#/$defs/hex32" }, "sequence": { "type": "string", "pattern": "^[0-9]+$" }, - "reasonCodes": { "type": "array", "items": { "type": "string" } } + "reasonCodes": { "type": "array", "items": { "type": "string" } }, + "contractEventRef": { "$ref": "#/$defs/flowPulseContractEventRef" } }, "$defs": { "hex32": { "type": "string", "pattern": "^0x[0-9a-fA-F]{64}$" }, + "address": { "type": "string", "pattern": "^0x[0-9a-fA-F]{40}$" }, + "flowPulseContractTypeName": { + "enum": ["ROOTFIELD_REGISTERED", "ROOT_COMMITTED", "ROOTFIELD_STATUS_CHANGED", "UNKNOWN_FLOWPULSE_TYPE"] + }, + "flowPulseContractEventRef": { + "type": "object", + "additionalProperties": false, + "required": ["signalId", "eventName", "eventTopic0", "sourceContract", "pulseTypeId", "pulseTypeName", "txHash", "logIndex"], + "properties": { + "signalId": { "$ref": "#/$defs/hex32" }, + "eventName": { "const": "FlowPulse" }, + "eventTopic0": { "$ref": "#/$defs/hex32" }, + "sourceContract": { "$ref": "#/$defs/address" }, + "pulseTypeId": { "type": "string", "pattern": "^[0-9]+$" }, + "pulseTypeName": { "$ref": "#/$defs/flowPulseContractTypeName" }, + "txHash": { "$ref": "#/$defs/hex32" }, + "logIndex": { "type": "string", "pattern": "^[0-9]+$" } + } + }, "flowMemoryStatus": { "enum": ["observed", "pending", "finalized", "verified", "unresolved", "failed", "unsupported", "reorged", "offline", "stale"] } diff --git a/services/flowmemory/src/generate-launch-core.ts b/services/flowmemory/src/generate-launch-core.ts index 7876b226..72d48984 100644 --- a/services/flowmemory/src/generate-launch-core.ts +++ b/services/flowmemory/src/generate-launch-core.ts @@ -12,6 +12,9 @@ import { } from "./status.ts"; import type { AgentMemoryView, + FlowPulseContractEvent, + FlowPulseContractEventRef, + FlowPulseContractTypeName, LaunchCoreOutput, MemoryReceipt, MemorySignal, @@ -23,6 +26,13 @@ const ZERO_ROOT = "0x00000000000000000000000000000000000000000000000000000000000 const GENERATED_AT = "2026-05-13T17:02:00.000Z"; const CHAIN_CONTEXT = "flowmemory-local-v0"; const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../../.."); +const FLOWPULSE_EVENT_SIGNATURE_TEXT = "FlowPulse(bytes32,bytes32,address,uint8,bytes32,bytes32,bytes32,uint64,uint64,string)"; +const FLOWPULSE_EVENT_TOPIC0 = keccak256Hex(new TextEncoder().encode(FLOWPULSE_EVENT_SIGNATURE_TEXT)); +const FLOWPULSE_CONTRACT_TYPE_NAMES: Record = { + "1": "ROOTFIELD_REGISTERED", + "2": "ROOT_COMMITTED", + "3": "ROOTFIELD_STATUS_CHANGED", +}; type JsonObject = Record; @@ -146,6 +156,10 @@ function pulseTypeName(pulseType: string): MemorySignal["signalType"] { return "unsupported_pulse"; } +function contractPulseTypeName(pulseType: string): FlowPulseContractTypeName { + return FLOWPULSE_CONTRACT_TYPE_NAMES[pulseType] ?? "UNKNOWN_FLOWPULSE_TYPE"; +} + function isoFromUnixSeconds(value: string): string { const seconds = Number(value); if (!Number.isFinite(seconds)) { @@ -172,6 +186,65 @@ function sortObservations(observations: IndexedObservation[]): IndexedObservatio }); } +function buildFlowPulseContractEvent(observation: IndexedObservation): FlowPulseContractEvent { + const occurredAt = isoFromUnixSeconds(observation.occurredAt); + + return { + schema: "flowmemory.flowpulse_contract_event.v0", + interfaceName: "IFlowPulse", + eventName: "FlowPulse", + eventSignatureText: FLOWPULSE_EVENT_SIGNATURE_TEXT, + eventTopic0: observation.eventSignature, + expectedTopic0: FLOWPULSE_EVENT_TOPIC0, + topicMatchesContract: observation.eventSignature.toLowerCase() === FLOWPULSE_EVENT_TOPIC0.toLowerCase(), + sourceContract: observation.emittingContract, + pulseTypeId: observation.pulseType, + pulseTypeName: contractPulseTypeName(observation.pulseType), + indexed: { + pulseId: observation.pulseId, + rootfieldId: observation.rootfieldId, + actor: observation.actor, + }, + payload: { + subject: observation.subject, + commitment: observation.commitment, + parentPulseId: observation.parentPulseId, + sequence: observation.sequence, + occurredAt, + uri: observation.uri, + }, + receiptLocator: { + chainId: observation.chainId, + blockNumber: observation.blockNumber, + blockHash: observation.blockHash, + txHash: observation.txHash, + transactionIndex: observation.transactionIndex, + logIndex: observation.logIndex, + receiptStatus: observation.receiptStatus, + }, + receiptDerivedFields: [ + "blockHash", + "txHash", + "transactionIndex", + "logIndex", + "receiptStatus", + ], + }; +} + +function buildContractEventRef(signal: MemorySignal): FlowPulseContractEventRef { + return { + signalId: signal.signalId, + eventName: signal.contractEvent.eventName, + eventTopic0: signal.contractEvent.eventTopic0, + sourceContract: signal.contractEvent.sourceContract, + pulseTypeId: signal.contractEvent.pulseTypeId, + pulseTypeName: signal.contractEvent.pulseTypeName, + txHash: signal.contractEvent.receiptLocator.txHash, + logIndex: signal.contractEvent.receiptLocator.logIndex, + }; +} + function buildMemorySignal(observation: IndexedObservation, status: FlowMemoryStatus): MemorySignal { const signalCore = { observationId: observation.observationId, @@ -180,6 +253,7 @@ function buildMemorySignal(observation: IndexedObservation, status: FlowMemorySt pulseType: observation.pulseType, sequence: observation.sequence, }; + const contractEvent = buildFlowPulseContractEvent(observation); return { schema: "flowmemory.memory_signal.v0", @@ -204,6 +278,7 @@ function buildMemorySignal(observation: IndexedObservation, status: FlowMemorySt occurredAt: isoFromUnixSeconds(observation.occurredAt), uri: observation.uri, summary: `${pulseTypeName(observation.pulseType).replaceAll("_", " ")} pulse ${observation.sequence}`, + contractEvent, }; } @@ -301,6 +376,7 @@ function buildLaunchCore(indexer: IndexerPersistence, verifier: VerifierPersiste txHash: observation.txHash, sequence: observation.sequence, reasonCodes: receipt?.reasonCodes ?? [], + contractEventRef: buildContractEventRef(signal), }; rootflowTransitions.push(transition); diff --git a/services/flowmemory/src/types.ts b/services/flowmemory/src/types.ts index 38274f59..7c10fd7c 100644 --- a/services/flowmemory/src/types.ts +++ b/services/flowmemory/src/types.ts @@ -1,5 +1,58 @@ import type { FlowMemoryStatus } from "./status.ts"; +export type FlowPulseContractTypeName = + | "ROOTFIELD_REGISTERED" + | "ROOT_COMMITTED" + | "ROOTFIELD_STATUS_CHANGED" + | "UNKNOWN_FLOWPULSE_TYPE"; + +export interface FlowPulseContractEvent { + schema: "flowmemory.flowpulse_contract_event.v0"; + interfaceName: "IFlowPulse"; + eventName: "FlowPulse"; + eventSignatureText: string; + eventTopic0: string; + expectedTopic0: string; + topicMatchesContract: boolean; + sourceContract: string; + pulseTypeId: string; + pulseTypeName: FlowPulseContractTypeName; + indexed: { + pulseId: string; + rootfieldId: string; + actor: string; + }; + payload: { + subject: string; + commitment: string; + parentPulseId: string; + sequence: string; + occurredAt: string; + uri: string; + }; + receiptLocator: { + chainId: string; + blockNumber: string; + blockHash: string; + txHash: string; + transactionIndex: string; + logIndex: string; + receiptStatus: string; + }; + receiptDerivedFields: string[]; +} + +export interface FlowPulseContractEventRef { + signalId: string; + eventName: "FlowPulse"; + eventTopic0: string; + sourceContract: string; + pulseTypeId: string; + pulseTypeName: FlowPulseContractTypeName; + txHash: string; + logIndex: string; +} + export interface MemorySignal { schema: "flowmemory.memory_signal.v0"; signalId: string; @@ -23,6 +76,7 @@ export interface MemorySignal { occurredAt: string; uri: string; summary: string; + contractEvent: FlowPulseContractEvent; } export interface MemoryReceipt { @@ -61,6 +115,7 @@ export interface RootflowTransition { txHash: string; sequence: string; reasonCodes: string[]; + contractEventRef: FlowPulseContractEventRef; } export interface RootfieldBundle { diff --git a/services/flowmemory/test/flowmemory.test.ts b/services/flowmemory/test/flowmemory.test.ts index 4b2290bc..6f29f17f 100644 --- a/services/flowmemory/test/flowmemory.test.ts +++ b/services/flowmemory/test/flowmemory.test.ts @@ -64,6 +64,23 @@ test("generates concrete Rootflow and Flow Memory V0 outputs", () => { assert.equal(launchCore.rootfieldBundles.length, 1); assert.equal(launchCore.agentMemoryViews.length, 1); + const firstSignal = launchCore.memorySignals[0]; + assert.equal(firstSignal.contractEvent.interfaceName, "IFlowPulse"); + assert.equal(firstSignal.contractEvent.eventName, "FlowPulse"); + assert.equal(firstSignal.contractEvent.indexed.pulseId, firstSignal.pulseId); + assert.equal(firstSignal.contractEvent.indexed.rootfieldId, firstSignal.rootfieldId); + assert.equal(firstSignal.contractEvent.payload.commitment, firstSignal.commitment); + assert.equal(firstSignal.contractEvent.receiptLocator.txHash, firstSignal.txHash); + assert.equal(firstSignal.contractEvent.topicMatchesContract, true); + + const unsupportedSignal = launchCore.memorySignals.find((signal) => signal.contractEvent.pulseTypeId === "99"); + assert.equal(unsupportedSignal?.contractEvent.pulseTypeName, "UNKNOWN_FLOWPULSE_TYPE"); + + const firstTransition = launchCore.rootflowTransitions[0]; + assert.equal(firstTransition.contractEventRef.signalId, firstTransition.memorySignalId); + assert.equal(firstTransition.contractEventRef.eventName, "FlowPulse"); + assert.equal(firstTransition.contractEventRef.txHash, firstTransition.txHash); + const transitionStatuses = new Set(launchCore.rootflowTransitions.map((transition) => transition.status)); assert.ok(transitionStatuses.has("verified")); assert.ok(transitionStatuses.has("failed"));