@ibgib/space-gib 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/IMPLEMENTATION.md +9 -13
- package/README.md +7 -0
- package/dist/client/bootstrap.mjs +1 -1
- package/dist/client/bootstrap.mjs.map +1 -1
- package/dist/client/chunk-ANGVYAEK.mjs +42 -0
- package/dist/client/chunk-ANGVYAEK.mjs.map +7 -0
- package/dist/client/chunk-IRGFDQRD.mjs +1920 -0
- package/dist/client/chunk-IRGFDQRD.mjs.map +7 -0
- package/dist/client/index.html +103 -5
- package/dist/client/index.mjs +1 -1
- package/dist/client/script.mjs +1 -1
- package/dist/client/style.css +466 -61
- package/dist/respec-gib.node.mjs +5 -0
- package/dist/server/server.mjs +533 -233
- package/dist/server/server.mjs.map +2 -2
- package/package.json +6 -6
- package/src/client/AUTO-GENERATED-version.mts +1 -1
- package/src/client/components/identity-header/IMPLEMENTATION.md +45 -0
- package/src/client/components/identity-header/identity-header.css +74 -0
- package/src/client/components/identity-header/identity-header.html +10 -0
- package/src/client/components/identity-header/identity-header.mts +361 -0
- package/src/client/components/identity-manager/IMPLEMENTATION.md +100 -0
- package/src/client/components/identity-manager/identity-manager.css +467 -0
- package/src/client/components/identity-manager/identity-manager.html +113 -0
- package/src/client/components/identity-manager/identity-manager.mts +767 -0
- package/src/client/components/keystone-creator/keystone-creator.css +2 -76
- package/src/client/components/keystone-creator/keystone-creator.html +41 -26
- package/src/client/components/keystone-creator/keystone-creator.mts +178 -41
- package/src/client/dev-tools/base-tools.mts +252 -0
- package/src/client/dev-tools/common.mts +217 -0
- package/src/client/dev-tools/phase-1.mts +156 -0
- package/src/client/dev-tools/phase-2.mts +143 -0
- package/src/client/dev-tools/phase-3.mts +189 -0
- package/src/client/dev-tools/phase-4-1.mts +197 -0
- package/src/client/dev-tools/phase-4-10.mts +884 -0
- package/src/client/dev-tools/phase-4-2.mts +388 -0
- package/src/client/dev-tools/phase-4-3.mts +391 -0
- package/src/client/dev-tools/phase-4-4.mts +374 -0
- package/src/client/dev-tools/phase-4-5.mts +376 -0
- package/src/client/dev-tools/phase-4-6.mts +273 -0
- package/src/client/dev-tools/phase-4-7.mts +399 -0
- package/src/client/dev-tools/phase-4-8.mts +430 -0
- package/src/client/dev-tools/phase-4-9.mts +398 -0
- package/src/client/dev-tools/phase-4.mts +1302 -0
- package/src/client/dev-tools.mts +52 -1194
- package/src/client/index.html +103 -5
- package/src/client/style.css +466 -61
- package/src/client/ui/shell/space-gib-shell-constants.mts +0 -2
- package/src/client/ui/shell/space-gib-shell-service.mts +82 -10
- package/src/common/common-constants.mts +0 -0
- package/src/common/keystone-policies.json +40 -43
- package/src/common/keystone-policies.mts +3 -5
- package/src/server/path-helper.respec.mts +99 -94
- package/src/server/serve-gib/README.md +9 -0
- package/src/server/serve-gib/handlers/api/keystone/keystone-genesis.handler.mts +1 -1
- package/src/server/serve-gib/handlers/api/keystone/keystone-get.respec.mts +1 -1
- package/src/server/serve-gib/handlers/ws/sync-upgrade-handler-base.mts +31 -3
- package/src/server/serve-gib/handlers/ws/ws-helper.mts +73 -45
- package/dist/client/chunk-2KJC5XKE.mjs +0 -31
- package/dist/client/chunk-2KJC5XKE.mjs.map +0 -7
- package/dist/client/chunk-QNIXTRFO.mjs +0 -235
- package/dist/client/chunk-QNIXTRFO.mjs.map +0 -7
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
import { extractErrorMsg, getUUID, getTimestamp } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
|
|
2
|
+
import { Factory_V1 as factory } from '@ibgib/ts-gib/dist/V1/factory.mjs';
|
|
3
|
+
import { ROOT } from '@ibgib/ts-gib/dist/V1/constants.mjs';
|
|
4
|
+
import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
|
|
5
|
+
import { KeystoneIbGib_V1 } from '@ibgib/core-gib/dist/keystone/keystone-types.mjs';
|
|
6
|
+
import { KeystoneService_V1 } from '@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs';
|
|
7
|
+
import { getGlobalMetaspace_waitIfNeeded } from "@ibgib/web-gib/dist/helpers.mjs";
|
|
8
|
+
import { mut8Timeline } from '@ibgib/core-gib/dist/timeline/timeline-api.mjs';
|
|
9
|
+
import { getTjpAddr } from '@ibgib/core-gib/dist/common/other/ibgib-helper.mjs';
|
|
10
|
+
import { SyncPeerWebSocketSender_V1 } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs';
|
|
11
|
+
import { SyncSagaCoordinator } from '@ibgib/core-gib/dist/sync/sync-saga-coordinator.mjs';
|
|
12
|
+
import { SyncConflictStrategy } from '@ibgib/core-gib/dist/sync/sync-constants.mjs';
|
|
13
|
+
import { GRAFT_BASE_REL8N_NAME, GRAFT_ORPHAN_REL8N_NAME, GRAFT_INFO_REL8N_NAME } from '@ibgib/core-gib/dist/sync/graft-info/graft-info-constants.mjs';
|
|
14
|
+
import { SESSION_KEYSTONE_POLICY, getSpaceGibPoolConfig } from "../../common/keystone-policies.mjs";
|
|
15
|
+
import { SpaceGibApiBridge } from '../api/space-gib-api-bridge.mjs';
|
|
16
|
+
|
|
17
|
+
import { debugState, devLog } from './common.mjs';
|
|
18
|
+
|
|
19
|
+
interface Phase47State {
|
|
20
|
+
domainI_latest?: KeystoneIbGib_V1;
|
|
21
|
+
testRoot?: any;
|
|
22
|
+
targetAlphaV2a?: any;
|
|
23
|
+
targetBetaV2b?: any;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const state: Phase47State = {};
|
|
27
|
+
|
|
28
|
+
export function init4_7bSetupButton(): void {
|
|
29
|
+
const btn = document.getElementById('btn-4-7b-setup') as HTMLButtonElement | null;
|
|
30
|
+
if (!btn) { return; }
|
|
31
|
+
btn.addEventListener('click', async () => {
|
|
32
|
+
try {
|
|
33
|
+
btn.disabled = true;
|
|
34
|
+
devLog('4.7B Setup: Setting up identities, seeding history, and creating divergent branches in client and remote...');
|
|
35
|
+
|
|
36
|
+
const metaspace = await getGlobalMetaspace_waitIfNeeded();
|
|
37
|
+
const space = await metaspace.getLocalUserSpace({}) as any;
|
|
38
|
+
if (!space) { throw new Error("No default space."); }
|
|
39
|
+
|
|
40
|
+
const keystoneService = new KeystoneService_V1();
|
|
41
|
+
const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
42
|
+
|
|
43
|
+
// 1. Generate Domain User Identity
|
|
44
|
+
const domainI = await keystoneService.genesis({
|
|
45
|
+
masterSecret: 'test-sender-secret-phase4-7b',
|
|
46
|
+
configs: [
|
|
47
|
+
getSpaceGibPoolConfig('sync', 'senderidentitysyncsaltphase4-7b'),
|
|
48
|
+
getSpaceGibPoolConfig('manage', 'senderidentitymanagesaltphase4-7b'),
|
|
49
|
+
],
|
|
50
|
+
metaspace,
|
|
51
|
+
space,
|
|
52
|
+
frameDetails: { client: 'space-gib-web-dev', timestamp: getTimestamp() }
|
|
53
|
+
});
|
|
54
|
+
state.domainI_latest = domainI;
|
|
55
|
+
let domainI_latest: any = domainI;
|
|
56
|
+
const domainAddr = getIbGibAddr({ ibGib: domainI });
|
|
57
|
+
devLog(`4.7B Setup: ✓ Created identity: ${domainAddr}`);
|
|
58
|
+
|
|
59
|
+
// Register on server
|
|
60
|
+
const apiBridge = new SpaceGibApiBridge();
|
|
61
|
+
const resGenesis = await apiBridge.postGenesisKeystone(domainI);
|
|
62
|
+
if (!resGenesis.success) {
|
|
63
|
+
throw new Error(`Server rejected genesis domain keystone: ${resGenesis.message}`);
|
|
64
|
+
}
|
|
65
|
+
devLog('4.7B Setup: ✓ Identity registered on server.');
|
|
66
|
+
|
|
67
|
+
// 2. Create the divergent "remote" space
|
|
68
|
+
devLog('4.7B Setup: Creating temporary remote space...');
|
|
69
|
+
const remoteSpace = await metaspace.createNewLocalSpace({
|
|
70
|
+
opts: {
|
|
71
|
+
allowCancel: false,
|
|
72
|
+
spaceName: 'remote_space_4_7b',
|
|
73
|
+
getFnPrompt: metaspace.getFnPrompt!
|
|
74
|
+
}
|
|
75
|
+
}) as any;
|
|
76
|
+
await remoteSpace.initialized;
|
|
77
|
+
|
|
78
|
+
// Copy user identity to remote space
|
|
79
|
+
await metaspace.put({ ibGib: domainI, space: remoteSpace });
|
|
80
|
+
await metaspace.registerNewIbGib({ ibGib: domainI, space: remoteSpace });
|
|
81
|
+
|
|
82
|
+
// 3. Seed common history root -> v1 locally
|
|
83
|
+
const resRoot = await factory.firstGen({
|
|
84
|
+
parentIbGib: ROOT,
|
|
85
|
+
ib: 'timeline_root_conflict_4_7b',
|
|
86
|
+
data: { type: 'root', label: 'CommonRoot', random: Math.random() },
|
|
87
|
+
dna: true,
|
|
88
|
+
nCounter: true,
|
|
89
|
+
tjp: { uuid: true, timestamp: true }
|
|
90
|
+
});
|
|
91
|
+
const testRoot = resRoot.newIbGib;
|
|
92
|
+
await metaspace.persistTransformResult({ resTransform: resRoot, space });
|
|
93
|
+
await metaspace.registerNewIbGib({ ibGib: testRoot, space });
|
|
94
|
+
state.testRoot = testRoot;
|
|
95
|
+
|
|
96
|
+
const v1_common = await mut8Timeline({
|
|
97
|
+
timeline: testRoot,
|
|
98
|
+
mut8Opts: { dataToAddOrPatch: { type: 'comment', label: 'V1Common' } },
|
|
99
|
+
metaspace,
|
|
100
|
+
space,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// 4. Copy common history to remote space
|
|
104
|
+
const graphRoot = await metaspace.getDependencyGraph({ ibGibAddr: getIbGibAddr({ ibGib: testRoot }), space });
|
|
105
|
+
const graphV1 = await metaspace.getDependencyGraph({ ibGibAddr: getIbGibAddr({ ibGib: v1_common }), space });
|
|
106
|
+
const commonDepGraph = { ...graphRoot, ...graphV1 };
|
|
107
|
+
await metaspace.put({ ibGibs: Object.values(commonDepGraph), space: remoteSpace });
|
|
108
|
+
await metaspace.registerNewIbGib({ ibGib: testRoot, space: remoteSpace });
|
|
109
|
+
await metaspace.registerNewIbGib({ ibGib: v1_common, space: remoteSpace });
|
|
110
|
+
|
|
111
|
+
// 5. Initial sync of v1_common to the server so server has it
|
|
112
|
+
devLog('4.7B Setup: Syncing v1_common to server...');
|
|
113
|
+
const senderPeerInit = new SyncPeerWebSocketSender_V1({
|
|
114
|
+
classname: 'SyncPeerWebSocketSender_V1',
|
|
115
|
+
httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
|
|
116
|
+
wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
|
|
117
|
+
});
|
|
118
|
+
const coordinatorInit = new SyncSagaCoordinator();
|
|
119
|
+
await senderPeerInit.initializeOpts({
|
|
120
|
+
localMetaspace: metaspace,
|
|
121
|
+
localSpace: space,
|
|
122
|
+
senderIdentity: domainI,
|
|
123
|
+
fnSenderSecret: async () => 'test-sender-secret-phase4-7b',
|
|
124
|
+
sagaId: await getUUID(),
|
|
125
|
+
sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
|
|
126
|
+
sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
|
|
127
|
+
targetAddrs: [domainAddr]
|
|
128
|
+
});
|
|
129
|
+
const syncSagaInit = await coordinatorInit.sync({
|
|
130
|
+
domainIbGibs: [v1_common],
|
|
131
|
+
senderIdentity: domainI,
|
|
132
|
+
fnSenderSecret: async () => 'test-sender-secret-phase4-7b',
|
|
133
|
+
peer: senderPeerInit,
|
|
134
|
+
localSpace: space,
|
|
135
|
+
metaspace,
|
|
136
|
+
conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
|
|
137
|
+
});
|
|
138
|
+
await syncSagaInit.done;
|
|
139
|
+
devLog('4.7B Setup: ✓ Seeding complete on server.');
|
|
140
|
+
|
|
141
|
+
// Fetch evolved user identity from space (now at n=2)
|
|
142
|
+
const domainLatestAddr = await metaspace.getLatestAddr({ ibGib: domainI, space });
|
|
143
|
+
if (!domainLatestAddr) { throw new Error("Could not find latest evolved identity address in local space."); }
|
|
144
|
+
const resGetLatest = await metaspace.get({ addr: domainLatestAddr, space });
|
|
145
|
+
if (!resGetLatest.success || !resGetLatest.ibGibs || resGetLatest.ibGibs.length === 0) {
|
|
146
|
+
throw new Error("Could not find latest evolved identity in local space.");
|
|
147
|
+
}
|
|
148
|
+
domainI_latest = resGetLatest.ibGibs[0] as KeystoneIbGib_V1;
|
|
149
|
+
state.domainI_latest = domainI_latest;
|
|
150
|
+
devLog(`4.7B Setup: ✓ Fetched evolved identity: ${domainLatestAddr}`);
|
|
151
|
+
|
|
152
|
+
// Copy evolved user identity to remote space
|
|
153
|
+
await metaspace.put({ ibGib: domainI_latest, space: remoteSpace });
|
|
154
|
+
await metaspace.registerNewIbGib({ ibGib: domainI_latest, space: remoteSpace });
|
|
155
|
+
|
|
156
|
+
// 6. Create Divergence:
|
|
157
|
+
// Client (default space) gets V2a (fieldA edit)
|
|
158
|
+
const v2a = await mut8Timeline({
|
|
159
|
+
timeline: v1_common,
|
|
160
|
+
mut8Opts: { dataToAddOrPatch: { fieldA: 'source_edit' } },
|
|
161
|
+
metaspace,
|
|
162
|
+
space,
|
|
163
|
+
});
|
|
164
|
+
state.targetAlphaV2a = v2a;
|
|
165
|
+
devLog(`4.7B Setup: ✓ Created client divergent edit V2a: ${getIbGibAddr({ ibGib: v2a })}`);
|
|
166
|
+
|
|
167
|
+
// Remote Space gets V2b (fieldB edit)
|
|
168
|
+
const v2b = await mut8Timeline({
|
|
169
|
+
timeline: v1_common,
|
|
170
|
+
mut8Opts: { dataToAddOrPatch: { fieldB: 'dest_edit' } },
|
|
171
|
+
metaspace,
|
|
172
|
+
space: remoteSpace,
|
|
173
|
+
});
|
|
174
|
+
state.targetBetaV2b = v2b;
|
|
175
|
+
devLog(`4.7B Setup: ✓ Created remote divergent edit V2b: ${getIbGibAddr({ ibGib: v2b })}`);
|
|
176
|
+
|
|
177
|
+
// 7. Sync V2b from remote space to server, so server tip becomes V2b
|
|
178
|
+
devLog('4.7B Setup: Pushing V2b from remote space to server...');
|
|
179
|
+
const senderPeerRemote = new SyncPeerWebSocketSender_V1({
|
|
180
|
+
classname: 'SyncPeerWebSocketSender_V1',
|
|
181
|
+
httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
|
|
182
|
+
wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
|
|
183
|
+
});
|
|
184
|
+
const coordinatorRemote = new SyncSagaCoordinator();
|
|
185
|
+
await senderPeerRemote.initializeOpts({
|
|
186
|
+
localMetaspace: metaspace,
|
|
187
|
+
localSpace: remoteSpace,
|
|
188
|
+
senderIdentity: domainI_latest,
|
|
189
|
+
fnSenderSecret: async () => 'test-sender-secret-phase4-7b',
|
|
190
|
+
sagaId: await getUUID(),
|
|
191
|
+
sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
|
|
192
|
+
sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
|
|
193
|
+
targetAddrs: [domainAddr]
|
|
194
|
+
});
|
|
195
|
+
const syncSagaRemote = await coordinatorRemote.sync({
|
|
196
|
+
domainIbGibs: [v2b],
|
|
197
|
+
senderIdentity: domainI_latest,
|
|
198
|
+
fnSenderSecret: async () => 'test-sender-secret-phase4-7b',
|
|
199
|
+
peer: senderPeerRemote,
|
|
200
|
+
localSpace: remoteSpace,
|
|
201
|
+
metaspace,
|
|
202
|
+
conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
|
|
203
|
+
});
|
|
204
|
+
await syncSagaRemote.done;
|
|
205
|
+
devLog('4.7B Setup: ✓ Server tip is now V2b.');
|
|
206
|
+
|
|
207
|
+
// Fetch evolved user identity from remote space (now at n=3)
|
|
208
|
+
const domainLatestAddrRemote = await metaspace.getLatestAddr({ ibGib: domainI, space: remoteSpace });
|
|
209
|
+
if (!domainLatestAddrRemote) { throw new Error("Could not find latest evolved identity address in remote space."); }
|
|
210
|
+
const resGetLatestRemote = await metaspace.get({ addr: domainLatestAddrRemote, space: remoteSpace });
|
|
211
|
+
if (!resGetLatestRemote.success || !resGetLatestRemote.ibGibs || resGetLatestRemote.ibGibs.length === 0) {
|
|
212
|
+
throw new Error("Could not find latest evolved identity in remote space.");
|
|
213
|
+
}
|
|
214
|
+
const domainI_latestRemote = resGetLatestRemote.ibGibs[0] as KeystoneIbGib_V1;
|
|
215
|
+
await metaspace.put({ ibGib: domainI_latestRemote, space });
|
|
216
|
+
await metaspace.registerNewIbGib({ ibGib: domainI_latestRemote, space });
|
|
217
|
+
state.domainI_latest = domainI_latestRemote;
|
|
218
|
+
devLog(`4.7B Setup: ✓ Copied evolved identity tip (n=3) back to default space: ${domainLatestAddrRemote}`);
|
|
219
|
+
|
|
220
|
+
devLog('✓ 4.7B Setup Complete! Ready for 4.7B Sync.');
|
|
221
|
+
btn.textContent = '✓ 4.7B Setup Complete';
|
|
222
|
+
|
|
223
|
+
const syncBtn = document.getElementById('btn-4-7b-sync') as HTMLButtonElement | null;
|
|
224
|
+
if (syncBtn) { syncBtn.disabled = false; }
|
|
225
|
+
|
|
226
|
+
} catch (error) {
|
|
227
|
+
devLog(`✗ 4.7B Setup FAILED: ${extractErrorMsg(error)}`);
|
|
228
|
+
console.error(error);
|
|
229
|
+
btn.disabled = false;
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export function init4_7bSyncButton(): void {
|
|
235
|
+
const btn = document.getElementById('btn-4-7b-sync') as HTMLButtonElement | null;
|
|
236
|
+
if (!btn) { return; }
|
|
237
|
+
btn.addEventListener('click', async () => {
|
|
238
|
+
try {
|
|
239
|
+
btn.disabled = true;
|
|
240
|
+
devLog('4.7B Sync: Initiating WebSocket Sync for divergent edit V2a...');
|
|
241
|
+
|
|
242
|
+
const domainI = state.domainI_latest;
|
|
243
|
+
const targetAlphaV2a = state.targetAlphaV2a;
|
|
244
|
+
if (!domainI || !targetAlphaV2a) {
|
|
245
|
+
devLog('⚠ 4.7B Sync: Missing setup state. Please run Setup first.');
|
|
246
|
+
btn.disabled = false;
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const domainAddr = getIbGibAddr({ ibGib: domainI });
|
|
251
|
+
const metaspace = await getGlobalMetaspace_waitIfNeeded();
|
|
252
|
+
const space = await metaspace.getLocalUserSpace({}) as any;
|
|
253
|
+
if (!space) { throw new Error("No default space."); }
|
|
254
|
+
|
|
255
|
+
const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
256
|
+
|
|
257
|
+
const senderPeer = new SyncPeerWebSocketSender_V1({
|
|
258
|
+
classname: 'SyncPeerWebSocketSender_V1',
|
|
259
|
+
httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
|
|
260
|
+
wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
const coordinator = new SyncSagaCoordinator();
|
|
264
|
+
const sagaId = await getUUID();
|
|
265
|
+
|
|
266
|
+
await senderPeer.initializeOpts({
|
|
267
|
+
localMetaspace: metaspace,
|
|
268
|
+
localSpace: space,
|
|
269
|
+
senderIdentity: domainI,
|
|
270
|
+
fnSenderSecret: async () => 'test-sender-secret-phase4-7b',
|
|
271
|
+
sagaId,
|
|
272
|
+
sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
|
|
273
|
+
sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
|
|
274
|
+
targetAddrs: [domainAddr]
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// Run Sync. Server has V2b, client has V2a. This will trigger optimistic graft merge!
|
|
278
|
+
const syncSaga = await coordinator.sync({
|
|
279
|
+
domainIbGibs: [targetAlphaV2a],
|
|
280
|
+
senderIdentity: domainI,
|
|
281
|
+
fnSenderSecret: async () => 'test-sender-secret-phase4-7b',
|
|
282
|
+
peer: senderPeer,
|
|
283
|
+
localSpace: space,
|
|
284
|
+
metaspace,
|
|
285
|
+
conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
|
|
286
|
+
});
|
|
287
|
+
await syncSaga.done;
|
|
288
|
+
|
|
289
|
+
devLog('✓ 4.7B Sync Execution Complete! Ready for 4.7B Check.');
|
|
290
|
+
btn.textContent = '✓ 4.7B Sync Run';
|
|
291
|
+
|
|
292
|
+
const checkBtn = document.getElementById('btn-4-7b-check') as HTMLButtonElement | null;
|
|
293
|
+
if (checkBtn) { checkBtn.disabled = false; }
|
|
294
|
+
|
|
295
|
+
} catch (error) {
|
|
296
|
+
devLog(`✗ 4.7B Sync FAILED: ${extractErrorMsg(error)}`);
|
|
297
|
+
console.error(error);
|
|
298
|
+
btn.disabled = false;
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export function init4_7bCheckButton(): void {
|
|
304
|
+
const btn = document.getElementById('btn-4-7b-check') as HTMLButtonElement | null;
|
|
305
|
+
if (!btn) { return; }
|
|
306
|
+
btn.addEventListener('click', async () => {
|
|
307
|
+
try {
|
|
308
|
+
btn.disabled = true;
|
|
309
|
+
devLog('4.7B Check: Verifying merged tip (V3) contains both edits on client and server...');
|
|
310
|
+
|
|
311
|
+
const domainI = state.domainI_latest;
|
|
312
|
+
const testRoot = state.testRoot;
|
|
313
|
+
const targetAlphaV2a = state.targetAlphaV2a;
|
|
314
|
+
const targetBetaV2b = state.targetBetaV2b;
|
|
315
|
+
if (!domainI || !testRoot || !targetAlphaV2a || !targetBetaV2b) {
|
|
316
|
+
devLog('⚠ 4.7B Check: Missing state. Did Setup and Sync run?');
|
|
317
|
+
btn.disabled = false;
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const domainAddr = getIbGibAddr({ ibGib: domainI });
|
|
322
|
+
const tjpAddr = getTjpAddr({ ibGib: testRoot, defaultIfNone: 'incomingAddr' }) ?? getIbGibAddr({ ibGib: testRoot });
|
|
323
|
+
|
|
324
|
+
const metaspace = await getGlobalMetaspace_waitIfNeeded();
|
|
325
|
+
const space = await metaspace.getLocalUserSpace({}) as any;
|
|
326
|
+
if (!space) { throw new Error("No default space."); }
|
|
327
|
+
|
|
328
|
+
// 1. Check client default space tip
|
|
329
|
+
const clientKV = await metaspace.getLocalUserSpace({}).then((space: any) => {
|
|
330
|
+
return new SyncSagaCoordinator().getKnowledgeMap({
|
|
331
|
+
space,
|
|
332
|
+
metaspace,
|
|
333
|
+
domainIbGibs: [testRoot]
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
const clientTipAddr = clientKV[tjpAddr];
|
|
337
|
+
devLog(`4.7B Check: Client tip address: ${clientTipAddr}`);
|
|
338
|
+
|
|
339
|
+
if (!clientTipAddr) {
|
|
340
|
+
throw new Error("Client default space is missing the timeline tip.");
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const resTip = await metaspace.get({ addr: clientTipAddr, space });
|
|
344
|
+
if (!resTip.success || !resTip.ibGibs || resTip.ibGibs.length === 0) {
|
|
345
|
+
throw new Error("Client tip not found in default local space.");
|
|
346
|
+
}
|
|
347
|
+
const clientTip = resTip.ibGibs[0];
|
|
348
|
+
|
|
349
|
+
if (!clientTip.data || !clientTip.data.fieldA || !clientTip.data.fieldB) {
|
|
350
|
+
throw new Error(`Merged client tip is missing expected data edits: fieldA: ${clientTip.data?.fieldA}, fieldB: ${clientTip.data?.fieldB}`);
|
|
351
|
+
}
|
|
352
|
+
devLog('4.7B Check: ✓ Client tip has both fieldA and fieldB edits.');
|
|
353
|
+
|
|
354
|
+
// Verify graftinfo rel8n exists
|
|
355
|
+
const graftInfoRel = clientTip.rel8ns?.[GRAFT_INFO_REL8N_NAME];
|
|
356
|
+
if (!graftInfoRel?.[0]) {
|
|
357
|
+
throw new Error("Client tip is missing graftinfo relations.");
|
|
358
|
+
}
|
|
359
|
+
const resGraft = await metaspace.get({ addr: graftInfoRel[0], space });
|
|
360
|
+
if (!resGraft.success || !resGraft.ibGibs || resGraft.ibGibs.length === 0) {
|
|
361
|
+
throw new Error("GraftInfo not found in local space.");
|
|
362
|
+
}
|
|
363
|
+
const graftInfo = resGraft.ibGibs[0];
|
|
364
|
+
const baseRel = graftInfo.rel8ns?.[GRAFT_BASE_REL8N_NAME];
|
|
365
|
+
const orphanRel = graftInfo.rel8ns?.[GRAFT_ORPHAN_REL8N_NAME];
|
|
366
|
+
|
|
367
|
+
if (!baseRel || !orphanRel) {
|
|
368
|
+
throw new Error("GraftInfo is missing graftbase or graftorphan relations.");
|
|
369
|
+
}
|
|
370
|
+
devLog('4.7B Check: ✓ Client graft base and orphan relations are correctly set.');
|
|
371
|
+
|
|
372
|
+
// 2. Check server tip
|
|
373
|
+
const apiBridge = new SpaceGibApiBridge();
|
|
374
|
+
devLog('4.7B Check: Fetching server timeline graph...');
|
|
375
|
+
const resServerGraph = await apiBridge.getIbGibGraph(domainAddr, clientTipAddr, true);
|
|
376
|
+
if (!resServerGraph.success || !resServerGraph.graph) {
|
|
377
|
+
throw new Error(`Failed to fetch merged graph from server: ${resServerGraph.message}`);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const serverTip = resServerGraph.graph[clientTipAddr];
|
|
381
|
+
if (!serverTip) {
|
|
382
|
+
throw new Error("Merged V3 tip is not present on the server!");
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (serverTip.data?.fieldA !== 'source_edit' || serverTip.data?.fieldB !== 'dest_edit') {
|
|
386
|
+
throw new Error("Server tip data edits do not match merged values.");
|
|
387
|
+
}
|
|
388
|
+
devLog('4.7B Check: ✓ Server tip has matching merged edits.');
|
|
389
|
+
|
|
390
|
+
devLog('✓ 4.7B Check SUCCESS: Divergent branches merged successfully on both client and server via optimistic graft!');
|
|
391
|
+
btn.textContent = '✓ 4.7B Check Success';
|
|
392
|
+
|
|
393
|
+
} catch (error) {
|
|
394
|
+
devLog(`✗ 4.7B Check FAILED: ${extractErrorMsg(error)}`);
|
|
395
|
+
console.error(error);
|
|
396
|
+
btn.disabled = false;
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
}
|