Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 51 additions & 3 deletions apps/dashboard/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# FlowMemory Dashboard V0
# FlowMemory Dashboard / FlowChain Workbench V0

Local operator/explorer app for inspecting FlowMemory V0 fixture output. It is intentionally fixture-backed and does not claim production live data, wallet support, token pricing, or hosted deployment.
Local operator/explorer app for inspecting FlowMemory V0 fixture output and the FlowChain private/local testnet workbench surface. It is intentionally local-first and does not claim value-bearing wallet support, token pricing, or hosted deployment.

## Run Locally

Expand All @@ -25,6 +25,28 @@ npm test
npm run build
```

From the repo root, the same checks are:

```powershell
npm test --prefix apps/dashboard
npm run build --prefix apps/dashboard
```

The first route is the FlowChain workbench. It tries the local control-plane API at:

```text
http://127.0.0.1:8787
```

Override that endpoint when needed:

```powershell
$env:VITE_FLOWCHAIN_CONTROL_PLANE_URL="http://127.0.0.1:8787"
npm run dev
```

If the API is not running, the workbench marks the control-plane as offline, shows stale fixture fallback where appropriate, and keeps rendering deterministic local data. This app is for private/local validation and canary review only; it does not initiate value-bearing wallet flows.

## Data Boundary

The canonical dashboard fixture is generated by the launch-core command and lives at:
Expand All @@ -33,13 +55,27 @@ The canonical dashboard fixture is generated by the launch-core command and live
fixtures/dashboard/flowmemory-dashboard-v0.json
```

The guarded Base canary review fixture is separate:

```text
fixtures/dashboard/flowmemory-dashboard-base-canary-v0.json
```

The app loads its runtime copy from:

```text
apps/dashboard/public/data/flowmemory-dashboard-v0.json
apps/dashboard/public/data/flowmemory-dashboard-base-canary-v0.json
```

The `dev` and `build` scripts run `npm run sync:fixtures`, which copies the canonical fixture into the Vite public data folder before the app starts or builds.
The `dev` and `build` scripts run `npm run sync:fixtures`, which copies the canonical dashboard fixture and the existing launch-core devnet state into the Vite public data folder before the app starts or builds.

Workbench fixture fallback paths:

```text
apps/dashboard/public/data/flowchain-local-devnet-state.json
apps/dashboard/public/data/flowchain-local-devnet-dashboard-state.json
```

Generated local source outputs land under the fixture boundary first:

Expand All @@ -54,7 +90,9 @@ fixtures/dashboard/generated/hardware-heartbeats.json

## Current Views

- FlowChain workbench
- Overview
- Base canary review
- Flow Memory / Rootflow
- FlowPulse stream
- Rootfields
Expand All @@ -67,6 +105,16 @@ fixtures/dashboard/generated/hardware-heartbeats.json

Every displayed record carries source subsystem, fixture/local origin, chain context, ID/hash, status, and last-updated metadata when available.

The workbench adds local setup/API status plus object views for blocks, transactions, agents, models, receipts, memory cells, artifacts, verifier reports, challenges, finality, provenance, and raw JSON. When a current fixture does not yet contain a private-testnet object type, the view stays empty and names the expected control-plane endpoint.

Workbench object coverage:

```text
node/chain status, blocks, transactions, rootfields, agents, models, work receipts,
memory cells, artifacts, verifier modules, verifier reports, challenges, finality,
provenance/source, hardware signals, raw JSON
```

## Status Vocabulary

Dashboard V0 visually distinguishes:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"artifactCommitments": {
"artifact:demo:001": {
"artifactId": "artifact:demo:001",
"commitment": "0x4de1ac0e70ce73c0a03df255d1ea2a7bbcb40f05c60f1b0c1b73e0b4577c537a",
"rootfieldId": "rootfield:demo:alpha",
"uriHint": "fixture://artifact/demo/001"
}
},
"baseAnchors": {
"0x08530e63dacb23a630bbbbd56ffc4dead54aca6d7e7ee7d920d7376eb9340ae7": {
"anchorId": "0x08530e63dacb23a630bbbbd56ffc4dead54aca6d7e7ee7d920d7376eb9340ae7",
"appchainChainId": "flowmemory-local-devnet-v0",
"artifactCommitmentRoot": "0xb772a9f7273032fd3ba2da8b6476d4715bbbafbd2a7eed21ecd0d558bde3beab",
"blockRangeEnd": 1,
"blockRangeStart": 1,
"finalityStatus": "local-placeholder",
"previousAnchorId": "0x0000000000000000000000000000000000000000000000000000000000000000",
"rootfieldStateRoot": "0xb72a851dca1103410484e3272945bae5e87fc39b8f32f77d2991959b60d3bfbf",
"stateRoot": "0x76ec5260c34184b6bb54ca406a43fc1f9591a47f37f71583a7620ef4a4065aff",
"verifierReportRoot": "0x4facd21e55423e182eba87355482a35daa93f53190fbd3a8d2969f9d55bc5373",
"workReceiptRoot": "0x8b3ef5650c9eea2f608ad9c7cb73df3c289fc0ac72ed04f46e6ae4bce0a1f023"
}
},
"blockHeight": 2,
"rootfields": {
"rootfield:demo:alpha": {
"active": true,
"latestRoot": "0xbdb66f777635a2426a834652f8efee40db4f3e0b9ddd2af15f15fd065a7fe4f4",
"metadataHash": "0x514006e494877d3d6a69848ed6264b152ebe6b73b1112d8ff1b9b48860509a2f",
"owner": "operator:local-demo",
"pulseCount": 2,
"rootCount": 1,
"rootfieldId": "rootfield:demo:alpha",
"schemaHash": "0x5909a6dc30ffe1fcd89eebc118f6d2096c4d4c3ccdcc851dc0e4386fe997c6d7"
}
},
"schema": "flowmemory.dashboard_state.local_devnet.v0",
"stateRoot": "0x3e1f5fddd84f9d460ee30a380ff700b17611891b8c03eb320edf1baefe003ef9",
"verifierReports": {
"report:demo:001": {
"reasonCodes": [],
"receiptId": "receipt:demo:001",
"reportDigest": "0xe75619ea62e7a6d9593debe0123d366ae0f0104cff86d9a69391fb5c1e074f4c",
"reportId": "report:demo:001",
"rootfieldId": "rootfield:demo:alpha",
"status": "verified",
"verifierId": "verifier:local-demo"
}
},
"workReceipts": {
"receipt:demo:001": {
"artifactCommitment": "0x4de1ac0e70ce73c0a03df255d1ea2a7bbcb40f05c60f1b0c1b73e0b4577c537a",
"inputRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
"outputRoot": "0xbdb66f777635a2426a834652f8efee40db4f3e0b9ddd2af15f15fd065a7fe4f4",
"receiptId": "receipt:demo:001",
"rootfieldId": "rootfield:demo:alpha",
"ruleSet": "flowmemory.work.rule_set.local_demo.v0",
"workerId": "worker:local-demo"
}
}
}
130 changes: 130 additions & 0 deletions apps/dashboard/public/data/flowchain-local-devnet-state.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
{
"schema": "flowmemory.local_devnet.state.v0",
"chainId": "flowmemory-local-devnet-v0",
"genesisHash": "0x0f23c892cbd2d00c10839d97ddab833698a83f8df8d6df27ceac03cfdd4b7bc9",
"nextBlockNumber": 3,
"logicalTime": 1778688002,
"parentHash": "0x7515374a9b020a6d271820031738a5190cb0fc374adcd74a88a32c0fd0d5c7a6",
"rootfields": {
"rootfield:demo:alpha": {
"rootfieldId": "rootfield:demo:alpha",
"owner": "operator:local-demo",
"schemaHash": "0x5909a6dc30ffe1fcd89eebc118f6d2096c4d4c3ccdcc851dc0e4386fe997c6d7",
"metadataHash": "0x514006e494877d3d6a69848ed6264b152ebe6b73b1112d8ff1b9b48860509a2f",
"latestRoot": "0xbdb66f777635a2426a834652f8efee40db4f3e0b9ddd2af15f15fd065a7fe4f4",
"pulseCount": 2,
"rootCount": 1,
"active": true
}
},
"artifactCommitments": {
"artifact:demo:001": {
"artifactId": "artifact:demo:001",
"rootfieldId": "rootfield:demo:alpha",
"commitment": "0x4de1ac0e70ce73c0a03df255d1ea2a7bbcb40f05c60f1b0c1b73e0b4577c537a",
"uriHint": "fixture://artifact/demo/001"
}
},
"workReceipts": {
"receipt:demo:001": {
"receiptId": "receipt:demo:001",
"rootfieldId": "rootfield:demo:alpha",
"workerId": "worker:local-demo",
"inputRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
"outputRoot": "0xbdb66f777635a2426a834652f8efee40db4f3e0b9ddd2af15f15fd065a7fe4f4",
"artifactCommitment": "0x4de1ac0e70ce73c0a03df255d1ea2a7bbcb40f05c60f1b0c1b73e0b4577c537a",
"ruleSet": "flowmemory.work.rule_set.local_demo.v0"
}
},
"verifierReports": {
"report:demo:001": {
"reportId": "report:demo:001",
"rootfieldId": "rootfield:demo:alpha",
"receiptId": "receipt:demo:001",
"verifierId": "verifier:local-demo",
"reportDigest": "0xe75619ea62e7a6d9593debe0123d366ae0f0104cff86d9a69391fb5c1e074f4c",
"status": "verified",
"reasonCodes": []
}
},
"importedObservations": {},
"importedVerifierReports": {},
"baseAnchors": {
"0x08530e63dacb23a630bbbbd56ffc4dead54aca6d7e7ee7d920d7376eb9340ae7": {
"anchorId": "0x08530e63dacb23a630bbbbd56ffc4dead54aca6d7e7ee7d920d7376eb9340ae7",
"appchainChainId": "flowmemory-local-devnet-v0",
"blockRangeStart": 1,
"blockRangeEnd": 1,
"stateRoot": "0x76ec5260c34184b6bb54ca406a43fc1f9591a47f37f71583a7620ef4a4065aff",
"workReceiptRoot": "0x8b3ef5650c9eea2f608ad9c7cb73df3c289fc0ac72ed04f46e6ae4bce0a1f023",
"verifierReportRoot": "0x4facd21e55423e182eba87355482a35daa93f53190fbd3a8d2969f9d55bc5373",
"rootfieldStateRoot": "0xb72a851dca1103410484e3272945bae5e87fc39b8f32f77d2991959b60d3bfbf",
"artifactCommitmentRoot": "0xb772a9f7273032fd3ba2da8b6476d4715bbbafbd2a7eed21ecd0d558bde3beab",
"previousAnchorId": "0x0000000000000000000000000000000000000000000000000000000000000000",
"finalityStatus": "local-placeholder"
}
},
"blocks": [
{
"schema": "flowmemory.local_devnet.block.v0",
"blockNumber": 1,
"parentHash": "0x0f23c892cbd2d00c10839d97ddab833698a83f8df8d6df27ceac03cfdd4b7bc9",
"logicalTime": 1778688000,
"txIds": [
"0x2cffda58c783dc026978b06a681587b19d9536ae4e158a69be855da1200f3189",
"0xb9f435aceb1bedb86dce821743769b28c02a42002c9cd41f2df1ea0279462ab2",
"0xef6df43993478d8f14d609732c7260fa08861ecc17e74137b83beda8d50931d2",
"0x73b81134901c2ce13e575f161d82a404c6f7cd1ef2e8ee17beb6697062175c46",
"0x3ac0b196a212a0e77d0a0c4b60e2283d2994b09993971b95427996700f5b92aa"
],
"receipts": [
{
"txId": "0x2cffda58c783dc026978b06a681587b19d9536ae4e158a69be855da1200f3189",
"status": "applied",
"error": null
},
{
"txId": "0xb9f435aceb1bedb86dce821743769b28c02a42002c9cd41f2df1ea0279462ab2",
"status": "applied",
"error": null
},
{
"txId": "0xef6df43993478d8f14d609732c7260fa08861ecc17e74137b83beda8d50931d2",
"status": "applied",
"error": null
},
{
"txId": "0x73b81134901c2ce13e575f161d82a404c6f7cd1ef2e8ee17beb6697062175c46",
"status": "applied",
"error": null
},
{
"txId": "0x3ac0b196a212a0e77d0a0c4b60e2283d2994b09993971b95427996700f5b92aa",
"status": "applied",
"error": null
}
],
"stateRoot": "0x76ec5260c34184b6bb54ca406a43fc1f9591a47f37f71583a7620ef4a4065aff",
"blockHash": "0xf76ac3652230cae4a4b5afcd54b0dcec9219f20ad71e21c497264668fb30f235"
},
{
"schema": "flowmemory.local_devnet.block.v0",
"blockNumber": 2,
"parentHash": "0xf76ac3652230cae4a4b5afcd54b0dcec9219f20ad71e21c497264668fb30f235",
"logicalTime": 1778688001,
"txIds": [
"0x8f719c880f17b5d4fb6d9efd54ac276d0dd8050d11c2c7870c36a79b66bc49d7"
],
"receipts": [
{
"txId": "0x8f719c880f17b5d4fb6d9efd54ac276d0dd8050d11c2c7870c36a79b66bc49d7",
"status": "applied",
"error": null
}
],
"stateRoot": "0x3e1f5fddd84f9d460ee30a380ff700b17611891b8c03eb320edf1baefe003ef9",
"blockHash": "0x7515374a9b020a6d271820031738a5190cb0fc374adcd74a88a32c0fd0d5c7a6"
}
],
"pendingTxs": []
}
35 changes: 26 additions & 9 deletions apps/dashboard/scripts/sync-fixtures.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,35 @@ import { fileURLToPath } from "node:url";
const scriptDir = dirname(fileURLToPath(import.meta.url));
const repoRoot = resolve(scriptDir, "../../..");
const destinationDir = resolve(repoRoot, "apps/dashboard/public/data");
const fixtures = [
"flowmemory-dashboard-v0.json",
"flowmemory-dashboard-base-canary-v0.json",
const fixtureCopies = [
{
label: "dashboard fixture",
source: resolve(repoRoot, "fixtures/dashboard/flowmemory-dashboard-v0.json"),
destination: resolve(destinationDir, "flowmemory-dashboard-v0.json"),
},
{
label: "Base canary dashboard fixture",
source: resolve(repoRoot, "fixtures/dashboard/flowmemory-dashboard-base-canary-v0.json"),
destination: resolve(destinationDir, "flowmemory-dashboard-base-canary-v0.json"),
},
{
label: "FlowChain local devnet state",
source: resolve(repoRoot, "fixtures/launch-core/generated/devnet/state.json"),
destination: resolve(destinationDir, "flowchain-local-devnet-state.json"),
},
{
label: "FlowChain local devnet dashboard state",
source: resolve(repoRoot, "fixtures/launch-core/generated/devnet/dashboard-state.json"),
destination: resolve(destinationDir, "flowchain-local-devnet-dashboard-state.json"),
},
];

mkdirSync(destinationDir, { recursive: true });

for (const fixture of fixtures) {
const source = resolve(repoRoot, "fixtures/dashboard", fixture);
const destination = resolve(destinationDir, fixture);
if (existsSync(source)) {
copyFileSync(source, destination);
console.log(`Synced dashboard fixture: ${destination}`);
for (const fixture of fixtureCopies) {
if (!existsSync(fixture.source)) {
throw new Error(`Missing ${fixture.label}: ${fixture.source}`);
}
copyFileSync(fixture.source, fixture.destination);
console.log(`Synced ${fixture.label}: ${fixture.destination}`);
}
Loading
Loading