@ibgib/core-gib 0.1.41 → 0.1.43

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.
Files changed (28) hide show
  1. package/dist/sync/sync-conflict-adv-multitimelines.respec.mjs +2 -2
  2. package/dist/sync/sync-conflict-adv-multitimelines.respec.mjs.map +1 -1
  3. package/dist/sync/sync-conflict-text-merge.respec.d.mts +4 -1
  4. package/dist/sync/sync-conflict-text-merge.respec.d.mts.map +1 -1
  5. package/dist/sync/sync-conflict-text-merge.respec.mjs +314 -181
  6. package/dist/sync/sync-conflict-text-merge.respec.mjs.map +1 -1
  7. package/dist/sync/sync-innerspace-dest-ahead-withid.respec.d.mts +7 -0
  8. package/dist/sync/sync-innerspace-dest-ahead-withid.respec.d.mts.map +1 -0
  9. package/dist/sync/sync-innerspace-dest-ahead-withid.respec.mjs +252 -0
  10. package/dist/sync/sync-innerspace-dest-ahead-withid.respec.mjs.map +1 -0
  11. package/dist/sync/sync-saga-coordinator.mjs +3 -3
  12. package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
  13. package/dist/test/mock-space.d.mts +1 -38
  14. package/dist/test/mock-space.d.mts.map +1 -1
  15. package/dist/test/mock-space.mjs +73 -78
  16. package/dist/test/mock-space.mjs.map +1 -1
  17. package/package.json +1 -1
  18. package/src/keystone/README.md +118 -0
  19. package/src/keystone/docs/architecture.md +30 -1
  20. package/src/sync/README.md +122 -5
  21. package/src/sync/docs/architecture.md +2 -2
  22. package/src/sync/{SYNC_TESTING.md → docs/testing.md} +113 -28
  23. package/src/sync/sync-conflict-adv-multitimelines.respec.mts +3 -3
  24. package/src/sync/sync-conflict-text-merge.respec.mts +326 -164
  25. package/src/sync/sync-innerspace-dest-ahead-withid.respec.mts +316 -0
  26. package/src/sync/sync-saga-coordinator.mts +4 -4
  27. package/src/test/mock-space.mts +72 -72
  28. package/src/sync/docs/verification.md +0 -43
@@ -0,0 +1,316 @@
1
+ /**
2
+ * @module sync-innerspace-dest-ahead.respec
3
+ *
4
+ * Verifies Sync Scenario where the receiver is ahead, with identity enabled.
5
+ */
6
+
7
+ import {
8
+ respecfully, lastOfAll, ifWe, iReckon,
9
+ ifWeMight
10
+ } from '@ibgib/helper-gib/dist/respec-gib/respec-gib.mjs';
11
+ const maam = `[${import.meta.url}]`, sir = maam;
12
+ import { clone, delay, extractErrorMsg, pretty } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
13
+ import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
14
+ import { IbGibAddr } from '@ibgib/ts-gib/dist/types.mjs';
15
+
16
+ import { SyncSagaCoordinator } from './sync-saga-coordinator.mjs';
17
+ import { putInSpace, getFromSpace, registerNewIbGib } from '../witness/space/space-helper.mjs';
18
+ import { Metaspace_Innerspace } from '../witness/space/metaspace/metaspace-innerspace/metaspace-innerspace.mjs';
19
+ import { InnerSpace_V1 } from '../witness/space/inner-space/inner-space-v1.mjs';
20
+ import { createTimelineRootTestHelper, getTestKeystoneServiceHelper } from '../test-helpers.mjs';
21
+ import { mut8Timeline } from '../timeline/timeline-api.mjs';
22
+ import { DEFAULT_INNER_SPACE_DATA_V1 } from '../witness/space/inner-space/inner-space-types.mjs';
23
+ import { toDto } from '../common/other/ibgib-helper.mjs';
24
+ import { SyncPeerInnerspace_V1 } from './sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs';
25
+ import { SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1 } from './sync-peer/sync-peer-innerspace/sync-peer-innerspace-constants.mjs';
26
+ import { GetIbGibResult } from '../common/other/other-types.mjs';
27
+ import { IbGibSpaceAny } from '../witness/space/space-base-v1.mjs';
28
+ import { getDependencyGraph } from '../common/other/graph-helper.mjs';
29
+
30
+ const logalot = false;
31
+ const lc = `[sync-innerspace-dest-ahead.respec]`;
32
+
33
+ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
34
+
35
+ let metaspace: Metaspace_Innerspace;
36
+ let sourceSpace: InnerSpace_V1;
37
+ let destSpace: InnerSpace_V1;
38
+
39
+ interface TestData {
40
+ type: string;
41
+ label?: string;
42
+ uuid?: string;
43
+ n?: number;
44
+ }
45
+
46
+ await respecfully(sir, `Dest Ahead (Remote Newer)`, async () => {
47
+ // 1. Setup Spaces
48
+ metaspace = new Metaspace_Innerspace(undefined);
49
+ await metaspace.initialize({
50
+ getFnAlert: () => async ({ title, msg }) => { },
51
+ getFnPrompt: () => async ({ title, msg }) => { return ''; },
52
+ getFnPromptPassword: () => async (title, msg) => { return null; },
53
+ });
54
+ while (!metaspace.initialized) { await delay(10); }
55
+
56
+ const defaultLocalUserSpace = await metaspace.getLocalUserSpace({ lock: false });
57
+ await defaultLocalUserSpace!.initialized;
58
+
59
+ sourceSpace = new InnerSpace_V1({
60
+ ...DEFAULT_INNER_SPACE_DATA_V1,
61
+ name: 'source',
62
+ uuid: 'source_uuid',
63
+ description: 'source test space',
64
+ });
65
+ await sourceSpace.initialized;
66
+
67
+ destSpace = new InnerSpace_V1({
68
+ ...DEFAULT_INNER_SPACE_DATA_V1,
69
+ name: 'dest',
70
+ uuid: 'dest_uuid',
71
+ description: 'dest test space',
72
+ });
73
+ await destSpace.initialized;
74
+
75
+ // 2. Seed Data
76
+ // Root -> V1 (Shared) -> V2 (Dest has New)
77
+ // Source only has V1.
78
+
79
+ const v0 = await createTimelineRootTestHelper<TestData>({
80
+ ib: 'timeline_root_ff',
81
+ data: { type: 'root', label: 'Root' },
82
+ space: sourceSpace,
83
+ });
84
+ const addrV0 = getIbGibAddr({ ibGib: v0 });
85
+ console.log(pretty(v0));
86
+
87
+ // V1 (Both have it, but we create in source and copy to dest)
88
+ const v1 = await mut8Timeline<TestData>({
89
+ timeline: v0,
90
+ mut8Opts: { dataToAddOrPatch: { type: 'comment', label: 'V1' } },
91
+ metaspace,
92
+ space: sourceSpace,
93
+ });
94
+ const addrV1 = getIbGibAddr({ ibGib: v1 });
95
+ console.log(pretty(v1));
96
+
97
+
98
+ // Transfer Root & V1 to Dest
99
+ const initialDepGraph = await getDependencyGraph({ ibGibs: [v0, v1], space: sourceSpace });
100
+ await putInSpace({ space: destSpace, ibGibs: Object.values(initialDepGraph) }); // Naive seeding
101
+ await registerNewIbGib({ space: destSpace, ibGib: v0 });
102
+ await registerNewIbGib({ space: destSpace, ibGib: v1 });
103
+
104
+ // V2 (Created in Dest ONLY)
105
+ const v2 = await mut8Timeline<TestData>({
106
+ timeline: v1, // v1 is in memory, linked to source, but we want to Mutate IN DEST SPACE
107
+ mut8Opts: { dataToAddOrPatch: { type: 'comment', label: 'V2' } },
108
+ metaspace,
109
+ space: destSpace, // Mutate in Dest
110
+ });
111
+ const addrV2 = getIbGibAddr({ ibGib: v2 });
112
+ console.log(pretty(v2));
113
+
114
+ const fnAddrExistsInSpace = async (addr: IbGibAddr, space: IbGibSpaceAny) => {
115
+ const resGet = await getFromSpace({ addr, space });
116
+ return resGet.success && resGet.ibGibs && resGet.ibGibs.length === 1;
117
+ }
118
+
119
+ await ifWeMight(sir, 'verify setup', async () => {
120
+ // Ensure V2 is ONLY in Dest (it is, per `space: destSpace`)
121
+ // Ensure Source does NOT have V2
122
+ iReckon(sir, await fnAddrExistsInSpace(addrV0, sourceSpace)).asTo('source has V0').isGonnaBeTrue();
123
+ iReckon(sir, await fnAddrExistsInSpace(addrV1, sourceSpace)).asTo('source has V1').isGonnaBeTrue();
124
+ iReckon(sir, await fnAddrExistsInSpace(addrV2, sourceSpace)).asTo('source has V2').isGonnaBeFalse();
125
+ iReckon(sir, await fnAddrExistsInSpace(addrV0, destSpace)).asTo('dest has V0').isGonnaBeTrue();
126
+ iReckon(sir, await fnAddrExistsInSpace(addrV1, destSpace)).asTo('dest has V1').isGonnaBeTrue();
127
+ iReckon(sir, await fnAddrExistsInSpace(addrV2, destSpace)).asTo('dest has V2').isGonnaBeTrue();
128
+ });
129
+
130
+ // 3. Setup Sync
131
+ const mockKeystone = await getTestKeystoneServiceHelper();
132
+ const senderCoordinator = new SyncSagaCoordinator(mockKeystone);
133
+ const receiverCoordinator = new SyncSagaCoordinator(mockKeystone);
134
+
135
+ const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
136
+ await peer.initialized;
137
+ await peer.initializeSender({
138
+ senderSpace: sourceSpace, // "Client"
139
+ receiverSpace: destSpace, // "Server"
140
+ receiverCoordinator,
141
+ receiverMetaspace: metaspace,
142
+ });
143
+
144
+ // 4. Run Sync (Source Pushes V1)
145
+ console.log(`${lc} Running Sync...`);
146
+ const { done, sagaId, updates$ } = await senderCoordinator.sync({
147
+ peer: peer,
148
+ localSpace: sourceSpace,
149
+ metaspace: metaspace,
150
+ domainIbGibs: [v1], // Source tries to push V1
151
+ useSessionIdentity: true,
152
+ });
153
+ await done;
154
+
155
+ // 5. Verify Sync (v2 should be in both source and dest now)
156
+ console.log(`${lc} Verifying Sync...`);
157
+
158
+ await ifWeMight(sir, `verify v2 now also in source`, async () => {
159
+ // Verify Tip (V2)
160
+
161
+ iReckon(sir, await fnAddrExistsInSpace(addrV0, sourceSpace)).asTo('source has V0').isGonnaBeTrue();
162
+ iReckon(sir, await fnAddrExistsInSpace(addrV1, sourceSpace)).asTo('source has V1').isGonnaBeTrue();
163
+ iReckon(sir, await fnAddrExistsInSpace(addrV2, sourceSpace)).asTo('source has V2').isGonnaBeTrue();
164
+ iReckon(sir, await fnAddrExistsInSpace(addrV0, destSpace)).asTo('dest has V0').isGonnaBeTrue();
165
+ iReckon(sir, await fnAddrExistsInSpace(addrV1, destSpace)).asTo('dest has V1').isGonnaBeTrue();
166
+ iReckon(sir, await fnAddrExistsInSpace(addrV2, destSpace)).asTo('dest has V2').isGonnaBeTrue();
167
+
168
+ });
169
+
170
+ await ifWeMight(sir, `dependency graphs the same`, async () => {
171
+
172
+ const sourceDepGraph = await getDependencyGraph({
173
+ ibGibAddr: addrV2,
174
+ space: sourceSpace,
175
+ });
176
+ const destDepGraph = await getDependencyGraph({
177
+ ibGibAddr: addrV2,
178
+ space: destSpace,
179
+ });
180
+
181
+ const sourceDepGraphAddrs = Object.keys(sourceDepGraph);
182
+ const destDepGraphAddrs = Object.keys(destDepGraph);
183
+
184
+ iReckon(sir, sourceDepGraphAddrs.length === destDepGraphAddrs.length).asTo('dep graphs same size').isGonnaBeTrue();
185
+
186
+ sourceDepGraphAddrs.forEach(sourceDepAddr => {
187
+ iReckon(sir, destDepGraphAddrs.includes(sourceDepAddr)).asTo(`${sourceDepAddr} is both graphs`).isGonnaBeTrue();
188
+ });
189
+ });
190
+
191
+ // ========================================================================
192
+ // IDENTITY-RELATED ASSERTIONS (TDD - Expose Implementation Gaps)
193
+ // ========================================================================
194
+
195
+ // Need to capture session identity and saga context from sync result
196
+ // For now, we'll retrieve from spaces after sync completes
197
+ let sessionKeystoneAddr: IbGibAddr | undefined;
198
+
199
+ await ifWeMight(sir, 'IDENTITY: session keystone exists in sender space', async () => {
200
+ // Session keystone should be in sender's durable space
201
+ // Since we can't enumerate space easily, we verify indirectly:
202
+ // The fact that sync completed means keystone was findable
203
+
204
+ // TODO: Capture sessionKeystoneAddr from sync() return value
205
+ // For now, placeholder passes
206
+ iReckon(sir, true)
207
+ .asTo('sync completed (keystone must exist)')
208
+ .isGonnaBeTrue();
209
+ });
210
+
211
+ await ifWeMight(sir, 'IDENTITY: session keystone exists in receiver space', async () => {
212
+ // Session keystone should be transferred to receiver's durable space
213
+ iReckon(sir, sessionKeystoneAddr)
214
+ .asTo('session keystone address was captured')
215
+ .isGonnaBeTruthy();
216
+
217
+ if (sessionKeystoneAddr) {
218
+ const destResult = await getFromSpace({ addr: sessionKeystoneAddr, space: destSpace });
219
+ iReckon(sir, destResult.success)
220
+ .asTo('receiver has session keystone')
221
+ .isGonnaBeTrue();
222
+ }
223
+ });
224
+
225
+ await ifWeMight(sir, 'IDENTITY: saga frames are signed', async () => {
226
+ // TODO: Get saga frames and check each has a proof
227
+ // This will FAIL when we actually check - that's the point (TDD RED)
228
+
229
+ iReckon(sir, false)
230
+ .asTo('saga frames have proofs (NOT IMPLEMENTED - should fail)')
231
+ .isGonnaBeTrue();
232
+ });
233
+
234
+ await ifWeMight(sir, 'IDENTITY: frame signatures are valid', async () => {
235
+ // TODO: For each saga frame, validate proof against session keystone
236
+ // const isValid = await validateProofWithKeystone({
237
+ // proof: frame.proof,
238
+ // keystone: sessionKeystone,
239
+ // targetFrame: frame
240
+ // });
241
+ // iReckon(sir, isValid).asTo('proof is valid').isGonnaBeTrue();
242
+
243
+ // Placeholder for now
244
+ iReckon(sir, true)
245
+ .asTo('proof validation not yet implemented')
246
+ .isGonnaBeTrue();
247
+ });
248
+
249
+ await ifWeMight(sir, 'IDENTITY: session keystone challenges are depleted', async () => {
250
+ // TODO: Session keystone should evolve after signing frames
251
+ // This will FAIL because keystone evolution not implemented yet
252
+
253
+ iReckon(sir, false)
254
+ .asTo('challenges depleted (NOT IMPLEMENTED - should fail)')
255
+ .isGonnaBeTrue();
256
+ });
257
+
258
+ await ifWeMight(sir, 'IDENTITY: frame timestamps are present and fresh', async () => {
259
+ // TODO: Check each frame has timestamp in proof claim
260
+ // const claim = JSON.parse(frame.proof.claim.scope);
261
+ // iReckon(sir, claim.timestamp).asTo('has timestamp').isGonnaBeTruthy();
262
+ // const age = Date.now() - claim.timestamp;
263
+ // iReckon(sir, age < 60000).asTo('timestamp is fresh (<60s)').isGonnaBeTrue();
264
+
265
+ // Placeholder
266
+ iReckon(sir, true)
267
+ .asTo('timestamp validation not yet implemented')
268
+ .isGonnaBeTrue();
269
+ });
270
+
271
+ await ifWeMight(sir, 'IDENTITY: keystone has no hard links to domain ibgibs', async () => {
272
+ if (sessionKeystoneAddr) {
273
+ const keystoneResult = await getFromSpace({
274
+ addr: sessionKeystoneAddr,
275
+ space: sourceSpace
276
+ });
277
+
278
+ if (keystoneResult.success && keystoneResult.ibGibs && keystoneResult.ibGibs.length > 0) {
279
+ const keystone = keystoneResult.ibGibs[0];
280
+ const rel8ns = keystone.rel8ns || {};
281
+ const allRel8nAddrs = Object.values(rel8ns)
282
+ .flat()
283
+ .filter(addr => typeof addr === 'string');
284
+
285
+ const domainAddrs = [addrV0, addrV1, addrV2];
286
+
287
+ for (const domainAddr of domainAddrs) {
288
+ iReckon(sir, allRel8nAddrs.includes(domainAddr))
289
+ .asTo(`keystone does not hard link to ${domainAddr}`)
290
+ .isGonnaBeFalse();
291
+ }
292
+ }
293
+ }
294
+ });
295
+
296
+ await ifWeMight(sir, 'IDENTITY: saga frames have no hard links to domain ibgibs', async () => {
297
+ // Saga frames should NOT have hard links to domain ibgibs
298
+ // This currently PASSES but will expose issues if hard links exist
299
+
300
+ iReckon(sir, true)
301
+ .asTo('hard link validation (placeholder)')
302
+ .isGonnaBeTrue();
303
+
304
+ // TODO: Get saga frames and check their rel8ns
305
+ // for (const frame of sagaFrames) {
306
+ // const rel8nAddrs = Object.values(frame.rel8ns || {}).flat();
307
+ // for (const domainAddr of [addrV0, addrV1, addrV2]) {
308
+ // iReckon(sir, rel8nAddrs.includes(domainAddr)).asTo get('no hard link').isGonnaBeFalse();
309
+ // }
310
+ // }
311
+ });
312
+
313
+
314
+ });
315
+
316
+ });
@@ -197,7 +197,7 @@ export class SyncSagaCoordinator {
197
197
 
198
198
  // BOOTSTRAP IDENTITY (Session Keystone)
199
199
  const sessionIdentity = useSessionIdentity
200
- ? await this.getSessionIdentity({ sagaId, metaspace, tempSpace })
200
+ ? await this.getSessionIdentity({ sagaId, metaspace, localSpace })
201
201
  : undefined;
202
202
  // if (logalot) { console.log(`${lc} sessionIdentity: ${sessionIdentity ? pretty(sessionIdentity) : 'undefined'} (I: abc01872800b3a66b819a05898bba826)`); }
203
203
 
@@ -328,11 +328,11 @@ export class SyncSagaCoordinator {
328
328
  private async getSessionIdentity({
329
329
  sagaId,
330
330
  metaspace,
331
- tempSpace,
331
+ localSpace,
332
332
  }: {
333
333
  sagaId: string,
334
334
  metaspace: MetaspaceService,
335
- tempSpace: IbGibSpaceAny,
335
+ localSpace: IbGibSpaceAny,
336
336
  }): Promise<KeystoneIbGib_V1> {
337
337
  const lc = `${this.lc}[${this.getSessionIdentity.name}]`;
338
338
  try {
@@ -349,7 +349,7 @@ export class SyncSagaCoordinator {
349
349
  masterSecret: sagaId,
350
350
  configs: [config],
351
351
  metaspace,
352
- space: tempSpace
352
+ space: localSpace // ✅ FIXED: Use durable space, not temp space
353
353
  });
354
354
 
355
355
  return sessionIdentity;
@@ -1,85 +1,85 @@
1
- import { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
2
- import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
1
+ // import { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
2
+ // import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
3
3
 
4
- /**
5
- * A simple in-memory map acting as a Space.
6
- * Pure Storage. No Indexing logic.
7
- *
8
- * Copied/Adapted from Keystone Respecs.
9
- */
10
- export class MockIbGibSpace {
11
- store = new Map<string, IbGib_V1>();
4
+ // /**
5
+ // * A simple in-memory map acting as a Space.
6
+ // * Pure Storage. No Indexing logic.
7
+ // *
8
+ // * Copied/Adapted from Keystone Respecs.
9
+ // */
10
+ // export class MockIbGibSpace {
11
+ // store = new Map<string, IbGib_V1>();
12
12
 
13
- constructor(public name: string = "mock_space") { }
13
+ // constructor(public name: string = "mock_space") { }
14
14
 
15
- async put({ ibGib }: { ibGib: IbGib_V1 }): Promise<void> {
16
- const addr = getIbGibAddr({ ibGib });
17
- this.store.set(addr, JSON.parse(JSON.stringify(ibGib))); // Deep copy
18
- }
15
+ // async put({ ibGib }: { ibGib: IbGib_V1 }): Promise<void> {
16
+ // const addr = getIbGibAddr({ ibGib });
17
+ // this.store.set(addr, JSON.parse(JSON.stringify(ibGib))); // Deep copy
18
+ // }
19
19
 
20
- async get({ addr }: { addr: string }): Promise<IbGib_V1 | null> {
21
- const data = this.store.get(addr);
22
- return data ? JSON.parse(JSON.stringify(data)) : null;
23
- }
20
+ // async get({ addr }: { addr: string }): Promise<IbGib_V1 | null> {
21
+ // const data = this.store.get(addr);
22
+ // return data ? JSON.parse(JSON.stringify(data)) : null;
23
+ // }
24
24
 
25
- async witness(arg: any): Promise<any> {
26
- const cmd = arg.data?.cmd;
27
- if (cmd === 'get') {
28
- const addrs = arg.data.ibGibAddrs || [];
29
- const ibGibs: IbGib_V1[] = [];
30
- for (const addr of addrs) {
31
- const ig = await this.get({ addr });
32
- if (ig) ibGibs.push(ig);
33
- }
34
- return { ibGibs };
35
- }
36
- if (cmd === 'put') {
37
- const ibGibs = arg.ibGibs || [];
38
- for (const ibGib of ibGibs) {
39
- await this.put({ ibGib });
40
- }
41
- return { ibGibs: [] }; // Return empty result or whatever witness expects
42
- }
43
- return undefined;
44
- }
45
- }
25
+ // async witness(arg: any): Promise<any> {
26
+ // const cmd = arg.data?.cmd;
27
+ // if (cmd === 'get') {
28
+ // const addrs = arg.data.ibGibAddrs || [];
29
+ // const ibGibs: IbGib_V1[] = [];
30
+ // for (const addr of addrs) {
31
+ // const ig = await this.get({ addr });
32
+ // if (ig) ibGibs.push(ig);
33
+ // }
34
+ // return { ibGibs };
35
+ // }
36
+ // if (cmd === 'put') {
37
+ // const ibGibs = arg.ibGibs || [];
38
+ // for (const ibGib of ibGibs) {
39
+ // await this.put({ ibGib });
40
+ // }
41
+ // return { ibGibs: [] }; // Return empty result or whatever witness expects
42
+ // }
43
+ // return undefined;
44
+ // }
45
+ // }
46
46
 
47
- /**
48
- * A partial mock of Metaspace.
49
- */
50
- export class MockMetaspaceService {
47
+ // /**
48
+ // * A partial mock of Metaspace.
49
+ // */
50
+ // export class MockMetaspaceService {
51
51
 
52
- /**
53
- * Map of TJP Gib (Timeline ID) -> Latest IbGib Addr (Head)
54
- */
55
- timelineHeads = new Map<string, string>();
52
+ // /**
53
+ // * Map of TJP Gib (Timeline ID) -> Latest IbGib Addr (Head)
54
+ // */
55
+ // timelineHeads = new Map<string, string>();
56
56
 
57
- constructor(public space: MockIbGibSpace) { }
57
+ // constructor(public space: MockIbGibSpace) { }
58
58
 
59
- async getLocalUserSpace({ lock }: { lock: boolean }): Promise<MockIbGibSpace> {
60
- return this.space;
61
- }
59
+ // async getLocalUserSpace({ lock }: { lock: boolean }): Promise<MockIbGibSpace> {
60
+ // return this.space;
61
+ // }
62
62
 
63
- async put(args: any): Promise<void> {
64
- const target = args.space || this.space;
65
- return target.put(args);
66
- }
63
+ // async put(args: any): Promise<void> {
64
+ // const target = args.space || this.space;
65
+ // return target.put(args);
66
+ // }
67
67
 
68
- async registerNewIbGib(args: { ibGib: IbGib_V1, space?: any }): Promise<void> {
69
- const { ibGib } = args;
70
- const targetSpace = args.space || this.space;
68
+ // async registerNewIbGib(args: { ibGib: IbGib_V1, space?: any }): Promise<void> {
69
+ // const { ibGib } = args;
70
+ // const targetSpace = args.space || this.space;
71
71
 
72
- // 1. Ensure it is stored
73
- await targetSpace.put({ ibGib });
72
+ // // 1. Ensure it is stored
73
+ // await targetSpace.put({ ibGib });
74
74
 
75
- // 2. Extract TJP
76
- const gib = ibGib.gib || '';
77
- let tjpGib = gib;
78
- if (gib.includes('.')) {
79
- const parts = gib.split('.');
80
- tjpGib = parts.slice(1).join('.');
81
- }
82
- const addr = getIbGibAddr({ ibGib });
83
- this.timelineHeads.set(tjpGib, addr);
84
- }
85
- }
75
+ // // 2. Extract TJP
76
+ // const gib = ibGib.gib || '';
77
+ // let tjpGib = gib;
78
+ // if (gib.includes('.')) {
79
+ // const parts = gib.split('.');
80
+ // tjpGib = parts.slice(1).join('.');
81
+ // }
82
+ // const addr = getIbGibAddr({ ibGib });
83
+ // this.timelineHeads.set(tjpGib, addr);
84
+ // }
85
+ // }
@@ -1,43 +0,0 @@
1
- # Sync Protocol Verification
2
-
3
- This document outlines the testing strategy and verification results for the Symmetric Sync Protocol.
4
-
5
- ## Testing Strategy
6
- We use `respec-gib` (a BDD-style framework) with **In-Memory Simulation (`InnerSpace`)** to verify logic. This allows us to test complex graph scenarios without network or disk I/O overhead.
7
-
8
- ### Key Test Files
9
- * `sync-innerspace.respec.mts`: Basic Push/Pull scenarios.
10
- * `sync-innerspace-multiple-timelines.respec.mts`: Handling multiple independent timelines in one Saga.
11
- * `sync-innerspace-deep-updates.respec.mts`: Syncing timelines with extensive history (ensuring `past` links are traversed).
12
- * `sync-innerspace-partial-update.respec.mts`: **Smart Diff** verification (Sender uses Receiver's context to send only deltas).
13
- * `sync-innerspace-dest-ahead.respec.mts`: Verifying "Fast-Backward" or "Push Offer" logic (Sender offers update, Receiver accepts).
14
- * `sync-innerspace-constants.respec.mts`: Verifying synchronization of **Stones** (Constants/Non-TJPs).
15
-
16
- ## Verification Matrix
17
-
18
- ### 1. Basic Scenarios
19
- | Feature | Description | Status | Test File |
20
- | :--- | :--- | :--- | :--- |
21
- | **Push** | Source syncs a new timeline to an empty Dest. | ✅ Verified | `sync-innerspace.respec.mts` |
22
- | **Pull** | Dest requests data from Source (Reverse Sync). | ⏳ Pending | `sync-innerspace.respec.mts` |
23
- | **Dest Ahead** | Dest has newer data; Source offers Push. | ✅ Verified | `sync-innerspace-dest-ahead.respec.mts` |
24
-
25
- ### 2. Complex Graph Scenarios
26
- | Feature | Description | Status | Test File |
27
- | :--- | :--- | :--- | :--- |
28
- | **Multi-Timeline** | Syncing multiple separate timelines. | ✅ Verified | `sync-innerspace-multiple-timelines.respec.mts` |
29
- | **Deep Updates** | Syncing deep dependency chains (Ancestors). | ✅ Verified | `sync-innerspace-deep-updates.respec.mts` |
30
- | **Smart Diff** | Sender skips data Receiver already has. | ✅ Verified | `sync-innerspace-partial-update.respec.mts` |
31
- | **Constants** | Syncing immutable stones (no TJP). | ✅ Verified | `sync-innerspace-constants.respec.mts` |
32
-
33
- ### 3. Failure & Edge Cases
34
- | Feature | Description | Status | Test File |
35
- | :--- | :--- | :--- | :--- |
36
- | **Validation** | Verifying Integrity Checks (ib/gib). | ⏳ Pending | - |
37
- | **Conflicts** | Divergent branches (Merge Strategy). | ⏳ Pending | - |
38
-
39
- ## Recent Verifications
40
- ### Sync Constants (2026-01-08)
41
- * **Goal**: Ensure constants (ibGibs without `tjp` or `past`) are synced.
42
- * **Result**: Passed.
43
- * **Fixes**: Updated `handleInitFrame` to request missing stones; updated `handleAckFrame` to include "tip" stones in payload even without dependencies.