@ibgib/core-gib 0.1.48 → 0.1.50

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 (94) hide show
  1. package/dist/common/comment/comment-constants.d.mts +5 -0
  2. package/dist/common/comment/comment-constants.d.mts.map +1 -1
  3. package/dist/common/comment/comment-constants.mjs +5 -0
  4. package/dist/common/comment/comment-constants.mjs.map +1 -1
  5. package/dist/common/comment/comment-helper.d.mts +9 -1
  6. package/dist/common/comment/comment-helper.d.mts.map +1 -1
  7. package/dist/common/comment/comment-helper.mjs +7 -5
  8. package/dist/common/comment/comment-helper.mjs.map +1 -1
  9. package/dist/sync/sync-conflict-adv-multitimelines.respec.mjs +1 -1
  10. package/dist/sync/sync-conflict-adv-multitimelines.respec.mjs.map +1 -1
  11. package/dist/sync/sync-conflict-basic-divergence.respec.mjs +1 -1
  12. package/dist/sync/sync-conflict-basic-divergence.respec.mjs.map +1 -1
  13. package/dist/sync/sync-conflict-basic-multitimelines.respec.mjs +1 -1
  14. package/dist/sync/sync-conflict-basic-multitimelines.respec.mjs.map +1 -1
  15. package/dist/sync/sync-conflict-text-merge.respec.mjs +1 -1
  16. package/dist/sync/sync-conflict-text-merge.respec.mjs.map +1 -1
  17. package/dist/sync/sync-innerspace-constants.respec.mjs +1 -1
  18. package/dist/sync/sync-innerspace-constants.respec.mjs.map +1 -1
  19. package/dist/sync/sync-innerspace-deep-updates.respec.mjs +1 -1
  20. package/dist/sync/sync-innerspace-deep-updates.respec.mjs.map +1 -1
  21. package/dist/sync/sync-innerspace-dest-ahead-withid.respec.mjs +13 -13
  22. package/dist/sync/sync-innerspace-dest-ahead-withid.respec.mjs.map +1 -1
  23. package/dist/sync/sync-innerspace-dest-ahead.respec.mjs +1 -1
  24. package/dist/sync/sync-innerspace-dest-ahead.respec.mjs.map +1 -1
  25. package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs +1 -1
  26. package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs.map +1 -1
  27. package/dist/sync/sync-innerspace-partial-update.respec.mjs +1 -1
  28. package/dist/sync/sync-innerspace-partial-update.respec.mjs.map +1 -1
  29. package/dist/sync/sync-innerspace.respec.mjs +1 -1
  30. package/dist/sync/sync-innerspace.respec.mjs.map +1 -1
  31. package/dist/sync/sync-peer/sync-peer-http-receiver/sync-http-node-adapter.d.mts +57 -0
  32. package/dist/sync/sync-peer/sync-peer-http-receiver/sync-http-node-adapter.d.mts.map +1 -0
  33. package/dist/sync/sync-peer/sync-peer-http-receiver/sync-http-node-adapter.mjs +310 -0
  34. package/dist/sync/sync-peer/sync-peer-http-receiver/sync-http-node-adapter.mjs.map +1 -0
  35. package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-types.d.mts +27 -0
  36. package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-types.d.mts.map +1 -0
  37. package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-types.mjs +2 -0
  38. package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-types.mjs.map +1 -0
  39. package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.d.mts +29 -0
  40. package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.d.mts.map +1 -0
  41. package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.mjs +122 -0
  42. package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.mjs.map +1 -0
  43. package/dist/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-types.d.mts +27 -0
  44. package/dist/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-types.d.mts.map +1 -0
  45. package/dist/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-types.mjs +2 -0
  46. package/dist/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-types.mjs.map +1 -0
  47. package/dist/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-v1.d.mts +24 -0
  48. package/dist/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-v1.d.mts.map +1 -0
  49. package/dist/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-v1.mjs +111 -0
  50. package/dist/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-v1.mjs.map +1 -0
  51. package/dist/sync/sync-peer/sync-peer-http.respec.d.mts +8 -0
  52. package/dist/sync/sync-peer/sync-peer-http.respec.d.mts.map +1 -0
  53. package/dist/sync/sync-peer/sync-peer-http.respec.mjs +333 -0
  54. package/dist/sync/sync-peer/sync-peer-http.respec.mjs.map +1 -0
  55. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.d.mts.map +1 -1
  56. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs +8 -7
  57. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs.map +1 -1
  58. package/dist/sync/sync-peer/sync-peer-types.d.mts +5 -5
  59. package/dist/sync/sync-peer/sync-peer-types.d.mts.map +1 -1
  60. package/dist/sync/sync-peer/sync-peer-v1.d.mts +0 -2
  61. package/dist/sync/sync-peer/sync-peer-v1.d.mts.map +1 -1
  62. package/dist/sync/sync-peer/sync-peer-v1.mjs +21 -5
  63. package/dist/sync/sync-peer/sync-peer-v1.mjs.map +1 -1
  64. package/dist/sync/sync-saga-coordinator.mjs +1 -1
  65. package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
  66. package/ibgib-foundations.md +109 -89
  67. package/package.json +1 -1
  68. package/src/common/comment/comment-constants.mts +6 -0
  69. package/src/common/comment/comment-helper.mts +13 -4
  70. package/src/sync/sync-conflict-adv-multitimelines.respec.mts +1 -1
  71. package/src/sync/sync-conflict-basic-divergence.respec.mts +1 -1
  72. package/src/sync/sync-conflict-basic-multitimelines.respec.mts +1 -1
  73. package/src/sync/sync-conflict-text-merge.respec.mts +1 -1
  74. package/src/sync/sync-innerspace-constants.respec.mts +1 -1
  75. package/src/sync/sync-innerspace-deep-updates.respec.mts +1 -1
  76. package/src/sync/sync-innerspace-dest-ahead-withid.respec.mts +12 -12
  77. package/src/sync/sync-innerspace-dest-ahead.respec.mts +1 -1
  78. package/src/sync/sync-innerspace-multiple-timelines.respec.mts +1 -1
  79. package/src/sync/sync-innerspace-partial-update.respec.mts +1 -1
  80. package/src/sync/sync-innerspace.respec.mts +1 -1
  81. package/src/sync/sync-peer/sync-peer-http-receiver/sync-http-node-adapter.mts +319 -0
  82. package/src/sync/sync-peer/sync-peer-http-receiver/sync-http-node-adapter.mts.metadata.md +72 -0
  83. package/src/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-types.mts +30 -0
  84. package/src/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.mts +146 -0
  85. package/src/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.mts.metadata.md +71 -0
  86. package/src/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-types.mts +32 -0
  87. package/src/sync/sync-peer/sync-peer-http-sender/sync-peer-http-sender-v1.mts +129 -0
  88. package/src/sync/sync-peer/sync-peer-http.respec.mts +364 -0
  89. package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-types.mts +8 -8
  90. package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mts +10 -7
  91. package/src/sync/sync-peer/sync-peer-types.mts +11 -11
  92. package/src/sync/sync-peer/sync-peer-v1.mts +5 -7
  93. package/src/sync/sync-saga-coordinator.mts +1 -1
  94. package/tmp-certs/server.pfx +0 -0
@@ -6,102 +6,120 @@ This document serves as an onboarding guide and technical reference for the **ib
6
6
 
7
7
  At its lowest level, anything in the system is an **ibGib**.
8
8
 
9
- * **ib**: The "Metadata". Often a string like "comment", "pic", or "link". It can be descriptive or functional (e.g., class names).
10
- * **gib**: The "Hash". A cryptographic hash (SHA-256 in V1) of the entire ibGib record.
11
- * **ib^gib**: The content address. Uniquely identifies a record in the universe.
9
+ * **ib**: The "Metadata". Often a string like "comment", "pic", or "link". It can be descriptive or functional (e.g., class names).
10
+ * **gib**: The "Hash". A cryptographic hash (SHA-256 in V1) of the entire ibGib record.
11
+ * **ib^gib**: The content address. Uniquely identifies a record in the universe.
12
12
 
13
13
  ### `gib` Nuances: Punctiliar vs. TJP
14
14
  The `gib` is more than a single hash; it encodes timeline context.
15
- * **Punctiliar Hash**: The hash of *just* the current frame's content. Every ibgib has this.
16
- * **TJP Gib (Timeline ID)**: The `gib` of the **Temporal Junction Point (TJP)**—the very first frame (Genesis/Fork) of the timeline.
17
- * **Composite Address**: Use `ib^[punctiliar_hash].[tjp_gib]`.
18
- * Example: `comment^<CURRENT_HASH>.<GENESIS_HASH>`
19
- * This allows us to identify *which* timeline a frame belongs to simply by looking at its address.
20
- * The `tjp` frame itself has a single hash (since its punctiliar hash IS the tjp gib).
15
+ * **Punctiliar Hash**: The hash of *just* the current frame's content. Every ibgib has this.
16
+ * **TJP Gib (Timeline ID)**: The `gib` of the **Temporal Junction Point (TJP)**—the very first frame (Genesis/Fork) of the timeline.
17
+ * **Composite Address**: Use `ib^[punctiliar_hash].[tjp_gib]`.
18
+ * Example: `comment^<CURRENT_HASH>.<GENESIS_HASH>`
19
+ * This allows us to identify *which* timeline a frame belongs to simply by looking at its address.
20
+ * The `tjp` frame itself has a single hash (since its punctiliar hash IS the tjp gib).
21
21
 
22
22
  ### Structure
23
23
  An `IbGib_V1` object has two primary payload containers:
24
- 1. **data**: Intrinsic, immutable properties. (e.g., text content, configuration flags).
25
- 2. **rel8ns**: Extrinsic, Directed Acyclic Graph (DAG) links to other ibGibs.
26
- * Named edges (e.g., `past`, `ancestor`, `pic`).
27
- * Always stored as an array of addresses (`IbGibAddr[]`).
24
+ 1. **data**: Intrinsic, immutable properties. (e.g., text content, configuration flags).
25
+ 2. **rel8ns**: Extrinsic, Directed Acyclic Graph (DAG) links to other ibGibs.
26
+ * Named edges (e.g., `past`, `ancestor`, `pic`).
27
+ * Always stored as an array of addresses (`IbGibAddr[]`).
28
28
 
29
29
  ### Transforms (The "Verbs")
30
30
  State is never mutated in place; it is evolved via transforms.
31
- * **[fork](file:../libs/ts-gib/src/V1/transforms/fork.mts)**: Creates a new timeline.
32
- * **Crucial**: Appends to `ancestor` but **CLEARS** the `past` rel8n. This is what births a new timeline.
33
- * **[mut8](file:../libs/ts-gib/src/V1/transforms/mut8.mts)** (Mutate): Evolves intrinsic data.
34
- * **Accretive**: By default, it *appends* the new address to the `past` array. It does **not** create a linked list unless `linkedRel8ns` is explicitly used.
35
- * Access the immediate past via `ibgib.rel8ns.past.at(-1)`.
36
- * **[rel8](file:../libs/ts-gib/src/V1/transforms/rel8.mts)** (Relate): Evolves extrinsic relationships.
37
- * Also accretive by default.
31
+ * **[fork](file:../libs/ts-gib/src/V1/transforms/fork.mts)**: Creates a new timeline.
32
+ * **Crucial**: Appends to `ancestor` but **CLEARS** the `past` rel8n. This is what births a new timeline.
33
+ * **[mut8](file:../libs/ts-gib/src/V1/transforms/mut8.mts)** (Mutate): Evolves intrinsic data.
34
+ * **Accretive**: By default, it *appends* the new address to the `past` array. It does **not** create a linked list unless `linkedRel8ns` is explicitly used.
35
+ * Access the immediate past via `ibgib.rel8ns.past.at(-1)`.
36
+ * **[rel8](file:../libs/ts-gib/src/V1/transforms/rel8.mts)** (Relate): Evolves extrinsic relationships.
37
+ * Also accretive by default.
38
38
 
39
39
  ### DNA (The "How")
40
40
  The **`dna`** rel8n is a critical component for distributed consistency.
41
- * **Memoization**: It stores the *arguments* used to create a transform (e.g., the specific `dataToAddOrPatch` in a `mut8`).
42
- * **In-Structure History**: These arguments are embedded directly in the ibGib structure via the `dna` rel8n.
43
- * **Merge Strategy**: When resolving divergent timelines, we don't just compare the final state. We examine the `dna` to understand the *intent* of the divergence.
44
- * *Example*: Two users edit a comment. One fixes a typo, one adds a sentence. By examining the `dna` (the `mut8` args), we can construct a new transform that applies both changes, rather than one overwriting the other.
41
+ * **Memoization**: It stores the *arguments* used to create a transform (e.g., the specific `dataToAddOrPatch` in a `mut8`).
42
+ * **In-Structure History**: These arguments are embedded directly in the ibGib structure via the `dna` rel8n.
43
+ * **Merge Strategy**: When resolving divergent timelines, we don't just compare the final state. We examine the `dna` to understand the *intent* of the divergence.
44
+ * *Example*: Two users edit a comment. One fixes a typo, one adds a sentence. By examining the `dna` (the `mut8` args), we can construct a new transform that applies both changes, rather than one overwriting the other.
45
45
 
46
46
 
47
47
  ## 2. Higher-Level Architecture (`core-gib`)
48
48
 
49
49
  ### Witness Pattern
50
50
  The **[Witness](file:src/witness/witness-types.mts)** is the core functional paradigm.
51
- * **Concept**: An ibGib that "observes" (witnesses) another ibGib and produces a result.
52
- * **Benefits**:
53
- * **Memoization**: Enables memoizing inputs, outputs, and parameters of the witness class itself.
54
- * **Aspect-Oriented Composeability**: Provides a single interaction point for easy composition of behaviors (logging, security, permissions).
55
- * **Interface**: `witness(arg: IbGib) -> Promise<IbGib>`
51
+ * **Concept**: An ibGib that "observes" (witnesses) another ibGib and produces a result.
52
+ * **Benefits**:
53
+ * **Memoization**: Enables memoizing inputs, outputs, and parameters of the witness class itself.
54
+ * **Aspect-Oriented Composeability**: Provides a single interaction point for easy composition of behaviors (logging, security, permissions).
55
+ * **Interface**: `witness(arg: IbGib) -> Promise<IbGib>`
56
56
 
57
57
  ### Space Paradigm & Metaspace
58
58
  **[Space](file:src/witness/space/space-types.mts)** is a specialized Witness responsible for storage and retrieval.
59
- * **Commands**: `put`, `get`, `delete`.
60
- * **Locations**: `local`, `sync`, `innerspace` (memory-only/test).
59
+ * **Commands**: `put`, `get`, `delete`.
60
+ * **Locations**: `local`, `sync`, `innerspace` (memory-only/test).
61
61
 
62
62
  **[Metaspace](file:src/witness/space/metaspace/metaspace-types.mts)**
63
- * **Role**: Currently acts as a **Singleton Facade** for the runtime context.
64
- * Does NOT yet actively route "get from any space" requests (though planned).
65
- * Initializes default local spaces.
66
- * **Persistence vs. Indexing**:
67
- * `metaspace.put`: Persists the ibGib to the underlying space(s).
68
- * `metaspace.registerNewIbGib`: Updates the *index* (e.g., "Latest" pointers for timelines) and broadcasts the event via PubSub.
69
- * *Usage*: Always `put` first, then `register` if it's a new timeline tip.
63
+ * **Role**: Currently acts as a **Singleton Facade** for the runtime context.
64
+ * Does NOT yet actively route "get from any space" requests (though planned).
65
+ * Initializes default local spaces.
66
+ * **Persistence vs. Indexing**:
67
+ * `metaspace.put`: Persists the ibGib to the underlying space(s) via `putInSpace`.
68
+ * `metaspace.registerNewIbGib`: Updates the *index* (e.g., "Latest" pointers for timelines) and broadcasts the event via `registerNewIbGib` with the pre-configured `fnBroadcast` when metaspace is initialized.
69
+ * *Usage*: put first, then register (skipping register only in rare cases).
70
70
 
71
71
  ### Timeline Facade (`timeline-api`)
72
72
  **[Timeline API](file:src/timeline/timeline-api.mts)** acts as a consumer-friendly facade over the raw Witness/Transform calls.
73
- * **Purpose**: Simplifies common operations like "Update this timeline with new data" (`mut8Timeline`).
74
- * **Abstraction**: Hides the complexity of TJP lookup, generic transforms, and graph traversal.
75
-
76
- ### respec-gib Test Framework
77
-
78
- `respec-gib` is a custom, vastly simplified testing framework. Key points:
79
-
80
- - **No CLI arguments**: The test runner does NOT parse command-line arguments like `--testPathPattern` or other Jest-style flags.
81
- - **Focusing tests**: The ONLY way to focus/filter tests is via `ifWeMight(` regex pattern matching in the test runner script.
82
- - Commands: Use `npm run test:agent` to run all tests, or modify the `ifWeMight` regex in `src/respec-gib.node.mts` to focus specific test files. (`respec-gib`)
83
- **[respec-gib](file:src/respec-gib.node.mts)** is the custom BDD-style testing framework.
84
- * **Structure**:
85
- * `respecfully`: Top-level organizational block (must `await`).
86
- * `ifWe`: Leaf-node test block (must `await`).
87
- * `iReckon`: Assertions (synchronous, inside `ifWe`).
88
- * *Note*: The test runner crudely regex-searches for `"ifWeMight("`.
73
+ * **Purpose**: Simplifies common operations like "Update this timeline with new data" (`mut8Timeline`).
74
+ * **Abstraction**: Hides the complexity of TJP lookup, generic transforms, and graph traversal.
75
+
76
+ ### *respec-gib* Test Framework
77
+
78
+ Since `ibgib` has unique execution environment requirements and a high need for custom asynchronous block handling, it uses a custom testing framework located in `@ibgib/helper-gib/dist/respec-gib`. Each lib/app has its own test runner script located in [lib/app]/src/respec-gib.node.mts, e.g., libs/helper-gib/src/respec-gib.node.mts or libs/core-gib/src/respec-gib.node.mts.
79
+
80
+ Key features include:
81
+ * **`respecfully`**: The equivalent of `describe` or an outer test suite block.
82
+ * async call, MUST USE await
83
+ * organizational block
84
+ * YES can be nested
85
+ * **`ifWe`**: The equivalent of `it`, used for defining a specific test case block.
86
+ * async call, MUST USE await
87
+ * can NOT be nested
88
+ * **`ifWeMight`**: A focused test case (equivalent to `fit` or `it.only`). Using this will restrict execution to only the `ifWeMight` block(s) and skip all others.
89
+ * async call, MUST USE await
90
+ * can NOT be nested
91
+ * **`iReckon`**: The assertion fluent API (equivalent to `expect`).
92
+ * sync call, do NOT await
93
+ * Only specific assertion methods are available compared to other bigger (and funded/helped) testing frameworks:
94
+ * *Assertions*:
95
+ * `willEqual(expected)` - Tests deep equality or reference equality.
96
+ * `isGonnaBe(expected)` - Tests equality.
97
+ * `isGonnaBeTruthy()` / `isGonnaBeFalsy()` - Tests truthiness.
98
+ * `isGonnaBeTrue()` / `isGonnaBeFalse()` - Strict equality to true/false.
99
+ * `isGonnaBeUndefined()` - Strict equality to undefined.
100
+ * `includes(expected)` - Tests array or substring inclusion.
101
+ * *Modifiers*:
102
+ * **`.not`**: Can precede any assertion (e.g., `iReckon(sir, x).not.isGonnaBe(true)`).
103
+ * **`.asTo(label)`**: Used to add context to the error message (e.g., `iReckon(sir, x).asTo("Checking user ID").willEqual(5)`).
104
+ * Setup and Teardown methods run dynamically per suite context:
105
+ * `firstOfAll` / `lastOfAll` - Runs once per outer suite.
106
+ * `firstOfEach` / `lastOfEach` - Runs before/after each inner child (`respecfully` or `ifWe/Might`), or modify the `ifWeMight` regex in `src/respec-gib.node.mts` to focus specific test files.
89
107
 
90
108
  ### Timelines & Temporal Junction Points (TJPs)
91
- * **Accretion vs. Linked List**: Timelines are typically **accretive**. We carry the full history of addresses in the `past` array (`past: [h1, h2, h3...]`).
92
- * *Tradeoff*: Increases metadata size but avoids O(N) network fetches required to traverse a linked list history.
93
- * *Optimization*: Future storage engines will compress this redundancy.
94
- * **TJP**: The stable identifier. In code, the TJP's `gib` is often used as the **Lock Scope** to serialize transforms on that timeline.
109
+ * **Accretion vs. Linked List**: Timelines are typically **accretive**. We carry the full history of addresses in the `past` array (`past: [h1, h2, h3...]`).
110
+ * *Tradeoff*: Increases metadata size but avoids O(N) network fetches required to traverse a linked list history.
111
+ * *Optimization*: Future storage engines will compress this redundancy.
112
+ * **TJP**: The stable identifier. In code, the TJP's `gib` is often used as the **Lock Scope** to serialize transforms on that timeline.
95
113
 
96
114
  ### IMPORTANT: Ancestor vs. Previous Frame
97
115
  It is critical to distinguish between these two relationships:
98
- * **Previous Frame (`past`)**: Points to the immediate predecessor in the *same* timeline. This is the "parent" in the Git commit sense.
99
- * *Usage*: `mut8`, `rel8`.
100
- * *Meaning*: "I am the next step in this timeline."
101
- * **Ancestor (`ancestor`)**: Points to the source from which a *new* timeline was spawned.
102
- * *Usage*: **ONLY** `fork`.
103
- * *Meaning*: "I am the beginning of a *new* timeline that came from that timeline."
104
- * *Constraint*: A `fork` transform clears the `past` array and adds the source to `ancestor`.
116
+ * **Previous Frame (`past`)**: Points to the immediate predecessor in the *same* timeline. This is the "parent" in the Git commit sense.
117
+ * *Usage*: `mut8`, `rel8`.
118
+ * *Meaning*: "I am the next step in this timeline."
119
+ * **Ancestor (`ancestor`)**: Points to the source from which a *new* timeline was spawned.
120
+ * *Usage*: **ONLY** `fork`.
121
+ * *Meaning*: "I am the beginning of a *new* timeline that came from that timeline."
122
+ * *Constraint*: A `fork` transform clears the `past` array and adds the source to `ancestor`.
105
123
 
106
124
  > [!IMPORTANT]
107
125
  > Never use "ancestor" to refer to the previous frame in a timeline history. That is the "past". Ancestor implies a fork.
@@ -112,36 +130,38 @@ The Sync Protocol is a **Symmetric, Peer-to-Peer** protocol modeled as a "Saga".
112
130
  See: **[Sync README](file:src/sync/README.md)**
113
131
 
114
132
  ### Core Components
115
- * **[SyncSagaIbGib](file:src/sync/sync-types.mts)**: The timeline tracking the sync session itself. Acts as an audit trail.
116
- * **[SyncSagaCoordinator](file:src/sync/sync-saga-coordinator.mts)**: The State Machine driver. Code is identical on both "Alice" (Source) and "Bob" (Destination) nodes.
117
- * **Message Stones**: Immutable data packets passed between peers (Init, Ack, Delta, Commit).
133
+ * **[SyncSagaIbGib](file:src/sync/sync-types.mts)**: The timeline tracking the sync session itself. Acts as an audit trail.
134
+ * **[SyncSagaCoordinator](file:src/sync/sync-saga-coordinator.mts)**: The State Machine driver. Code is identical on both "Alice" (Source) and "Bob" (Destination) nodes.
135
+ * **Message Stones**: Immutable data packets passed between peers (Init, Ack, Delta, Commit).
118
136
 
119
137
  ### Protocol Flow
120
- 1. **Init**: Sender generates a **Knowledge Vector** (KV) summary.
121
- 2. **Gap Analysis**: Receiver compares KVs.
122
- * Sender behind -> **Push Offer**.
123
- * Sender ahead -> **Delta Request**.
124
- * Diverged -> **Conflict**.
125
- 3. **Ack**: Receiver sends back lists of needs/offers.
126
- 4. **Delta/Push**: Data exchange.
127
- 5. **Commit**: Session finalized.
138
+ 1. **Init**: Sender generates a **Knowledge Vector** (KV) summary.
139
+ 2. **Gap Analysis**: Receiver compares KVs.
140
+ * Sender behind -> **Push Offer**.
141
+ * Sender ahead -> **Delta Request**.
142
+ * Diverged -> **Conflict**.
143
+ 3. **Ack**: Receiver sends back lists of needs/offers.
144
+ 4. **Delta/Push**: Data exchange.
145
+ 5. **Commit**: Session finalized.
128
146
 
129
147
  ## 4. Identity (Keystone)
130
148
 
131
149
  **[Keystone](file:src/keystone/README.md)** is a novel, graph-native identity mechanism using **Hash-Based Cryptography** (Post-Quantum ready).
132
150
 
133
- * **Concept**: An identity is not a public key; it is a **Timeline** (Keystone). Verification is **Auditability**. To verify "Alice", you replay her Keystone timeline from Genesis to now, verifying proofs at each step.
134
- * **Mechanisms**:
135
- * **Hash-Reveal**: Uses schemes similar to **Lamport Signatures** or **Winternitz OTS**, but adapted for the ibGib graph.
136
- * **Merkle DAGs**: Efficiently communicates identity state by only syncing missing graph nodes.
137
- * **Sigma Protocols**: Can support zero-knowledge proofs for authentication without revealing private keys (future).
138
- * **Session Identity**: In Sync, we use ephemeral "Session Keystones" to sign the Saga, ensuring the integrity of the sync session without exposing long-term Master Identity keys.
151
+ * **Concept**: An identity is not a public key; it is a **Timeline** (Keystone). Verification is **Auditability**. To verify "Alice", you replay her Keystone timeline from Genesis to now, verifying proofs at each step.
152
+ * **Mechanisms**:
153
+ * **Hash-Reveal**: Uses schemes similar to **Lamport Signatures** or **Winternitz OTS**, but adapted for the ibGib graph.
154
+ * **Merkle DAGs**: Efficiently communicates identity state by only syncing missing graph nodes.
155
+ * **Sigma Protocols**: Can support zero-knowledge proofs for authentication without revealing private keys.
156
+ * Only partially implemented
157
+ * **Session Identity**: In Sync, we use ephemeral "Session Keystones" to sign the Saga, ensuring the integrity of the sync session without exposing long-term Master Identity keys.
158
+ * Only partially implemented
139
159
 
140
160
  ## Reference Links
141
- * **Core Types**: [libs/ts-gib/src/types.mts](file:../libs/ts-gib/src/types.mts)
142
- * **Transforms**: [libs/ts-gib/src/V1/transforms/](file:../libs/ts-gib/src/V1/transforms/)
143
- * **Witness**: [libs/core-gib/src/witness/witness-types.mts](file:src/witness/witness-types.mts)
144
- * **Space**: [libs/core-gib/src/witness/space/space-types.mts](file:src/witness/space/space-types.mts)
145
- * **Timeline API**: [libs/core-gib/src/timeline/timeline-api.mts](file:src/timeline/timeline-api.mts)
146
- * **Sync Coordinator**: [libs/core-gib/src/sync/sync-saga-coordinator.mts](file:src/sync/sync-saga-coordinator.mts)
147
- * **Keystone**: [libs/core-gib/src/keystone/README.md](file:src/keystone/README.md)
161
+ * **Core Types**: [libs/ts-gib/src/types.mts](file:../libs/ts-gib/src/types.mts)
162
+ * **Transforms**: [libs/ts-gib/src/V1/transforms/](file:../libs/ts-gib/src/V1/transforms/)
163
+ * **Witness**: [libs/core-gib/src/witness/witness-types.mts](file:src/witness/witness-types.mts)
164
+ * **Space**: [libs/core-gib/src/witness/space/space-types.mts](file:src/witness/space/space-types.mts)
165
+ * **Timeline API**: [libs/core-gib/src/timeline/timeline-api.mts](file:src/timeline/timeline-api.mts)
166
+ * **Sync Coordinator**: [libs/core-gib/src/sync/sync-saga-coordinator.mts](file:src/sync/sync-saga-coordinator.mts)
167
+ * **Keystone**: [libs/core-gib/src/keystone/README.md](file:src/keystone/README.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ibgib/core-gib",
3
- "version": "0.1.48",
3
+ "version": "0.1.50",
4
4
  "description": "ibgib core functionality, including base architecture for witnesses, spaces, apps, robbots, etc., as well as shared utility functions. Node v19+ needed for heavily-used isomorphic webcrypto hashing consumed in both node and browsers.",
5
5
  "funding": {
6
6
  "type": "individual",
@@ -8,3 +8,9 @@ export const DEFAULT_COMMENT_TEXT_IB_SUBSTRING_LENGTH = 20;
8
8
  * @example "comment thisisacomm here_is_addl_metadata"
9
9
  */
10
10
  export const DEFAULT_COMMENT_METADATA_IB_SUBSTRING_LENGTH = 128;
11
+
12
+ /**
13
+ * if whitespace-only comment ibgib is enabled, the ib will contain this in
14
+ * place of the whitespace text.
15
+ */
16
+ export const COMMENT_IB_WHITESPACE_ONLY_TEXT = '___whitespace___';
@@ -6,7 +6,7 @@ import { GLOBAL_LOG_A_LOT } from '../../core-constants.mjs';
6
6
  import { IbGibSpaceAny } from '../../witness/space/space-base-v1.mjs';
7
7
  import { persistTransformResult } from '../../witness/space/space-helper.mjs';
8
8
  import { CommentData_V1, CommentIbGib_V1 } from './comment-types.mjs';
9
- import { DEFAULT_COMMENT_METADATA_IB_SUBSTRING_LENGTH, DEFAULT_COMMENT_TEXT_IB_SUBSTRING_LENGTH } from './comment-constants.mjs';
9
+ import { COMMENT_IB_WHITESPACE_ONLY_TEXT, DEFAULT_COMMENT_METADATA_IB_SUBSTRING_LENGTH, DEFAULT_COMMENT_TEXT_IB_SUBSTRING_LENGTH } from './comment-constants.mjs';
10
10
 
11
11
  const logalot = GLOBAL_LOG_A_LOT || false;
12
12
 
@@ -100,6 +100,7 @@ export async function createCommentIbGib({
100
100
  addlMetadataText,
101
101
  saveInSpace,
102
102
  space,
103
+ dontTrimText,
103
104
  }: {
104
105
  /**
105
106
  * comment text
@@ -121,6 +122,14 @@ export async function createCommentIbGib({
121
122
  * this space.
122
123
  */
123
124
  space?: IbGibSpaceAny,
125
+ /**
126
+ * If true, stores `text` verbatim without trimming leading/trailing
127
+ * whitespace. Required for lossless chunking where rawTexts must tile the
128
+ * parent source exactly.
129
+ *
130
+ * Default: false (existing behaviour — trims whitespace).
131
+ */
132
+ dontTrimText?: boolean,
124
133
  }): Promise<TransformResult<CommentIbGib_V1>> {
125
134
  const lc = `[${createCommentIbGib.name}]`;
126
135
 
@@ -128,16 +137,16 @@ export async function createCommentIbGib({
128
137
  try {
129
138
  if (!text) { throw new Error(`text required (E: 3e3d0f555e1a83771a6548eb10943522)`); }
130
139
 
131
- text = text.trim();
140
+ if (!dontTrimText) { text = text.trim(); }
132
141
 
133
- if (!text) { throw new Error(`text cannot be only whitespace (E: d6db3537b9834294836aeb70987c908e)`); }
142
+ if (!text) { throw new Error(`text cannot be only whitespace when dontTrimText is falsy. (E: d6db3537b9834294836aeb70987c908e)`); }
134
143
 
135
144
  const data: CommentData_V1 = { text, textTimestamp: getTimestamp() };
136
145
 
137
146
  // create an ibgib with the filename and ext
138
147
  const opts: any = {
139
148
  parentIbGib: factory.primitive({ ib: 'comment' }),
140
- ib: getCommentIb({ commentText: text, addlMetadataText }),
149
+ ib: getCommentIb({ commentText: text.trim() || COMMENT_IB_WHITESPACE_ONLY_TEXT, addlMetadataText }),
141
150
  data,
142
151
  dna: true,
143
152
  tjp: { uuid: true, timestamp: true },
@@ -86,7 +86,7 @@ await respecfully(sir, `Multi-round/timeline permutations`, async () => {
86
86
  const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
87
87
  await peer.initialized;
88
88
  await peer.initializeOpts({
89
- senderSpace: sourceSpace,
89
+ localSpace: sourceSpace,
90
90
  receiverSpace: destSpace,
91
91
  receiverCoordinator: receiverCoordinator,
92
92
  receiverMetaspace: metaspace,
@@ -222,7 +222,7 @@ await respecfully(sir, `Two different fields`, async () => {
222
222
  const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
223
223
  await peer.initialized;
224
224
  await peer.initializeOpts({
225
- senderSpace: sourceSpace, // "Client"
225
+ localSpace: sourceSpace, // "Client"
226
226
  receiverSpace: destSpace, // "Server"
227
227
  receiverCoordinator,
228
228
  receiverMetaspace: metaspace,
@@ -208,7 +208,7 @@ await respecfully(sir, `Two different fields and rel8d`, async () => {
208
208
  const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
209
209
  await peer.initialized;
210
210
  await peer.initializeOpts({
211
- senderSpace: sourceSpace, // "Client"
211
+ localSpace: sourceSpace, // "Client"
212
212
  receiverSpace: destSpace, // "Server"
213
213
  receiverCoordinator,
214
214
  receiverMetaspace: metaspace,
@@ -88,7 +88,7 @@ await respecfully(sir, `Text merge (LCS) conflict resolution`, async () => {
88
88
  const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
89
89
  await peer.initialized;
90
90
  await peer.initializeOpts({
91
- senderSpace: sourceSpace,
91
+ localSpace: sourceSpace,
92
92
  receiverSpace: destSpace,
93
93
  receiverCoordinator: receiverCoordinator,
94
94
  receiverMetaspace: metaspace,
@@ -73,7 +73,7 @@ await respecfully(sir, `Sync Constants (No TJP)`, async () => {
73
73
  const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
74
74
  await peer.initialized;
75
75
  await peer.initializeOpts({
76
- senderSpace: sourceSpace, // "Client"
76
+ localSpace: sourceSpace, // "Client"
77
77
  receiverSpace: destSpace, // "Server"
78
78
  receiverCoordinator,
79
79
  receiverMetaspace: metaspace,
@@ -104,7 +104,7 @@ await respecfully(sir, `Sync InnerSpaces (Deep Updates)`, async () => {
104
104
  const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
105
105
  await peer.initialized;
106
106
  await peer.initializeOpts({
107
- senderSpace: sourceSpace, // "Client"
107
+ localSpace: sourceSpace, // "Client"
108
108
  receiverSpace: destSpace, // "Server"
109
109
  receiverCoordinator,
110
110
  receiverMetaspace: metaspace,
@@ -124,7 +124,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
124
124
  return resGet.success && resGet.ibGibs && resGet.ibGibs.length === 1;
125
125
  }
126
126
 
127
- await ifWeMight(sir, 'verify setup', async () => {
127
+ await ifWe(sir, 'verify setup', async () => {
128
128
  // Ensure V2 is ONLY in Dest (it is, per `space: destSpace`)
129
129
  // Ensure Source does NOT have V2
130
130
  iReckon(sir, await fnAddrExistsInSpace(addrV0, sourceSpace)).asTo('source has V0').isGonnaBeTrue();
@@ -143,7 +143,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
143
143
  const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
144
144
  await peer.initialized;
145
145
  await peer.initializeOpts({
146
- senderSpace: sourceSpace, // "Client"
146
+ localSpace: sourceSpace, // "Client"
147
147
  receiverSpace: destSpace, // "Server"
148
148
  receiverCoordinator,
149
149
  receiverMetaspace: metaspace,
@@ -193,7 +193,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
193
193
  // 5. Verify Sync (v2 should be in both source and dest now)
194
194
  console.log(`${lc} Verifying Sync...`);
195
195
 
196
- await ifWeMight(sir, `verify v2 now also in source`, async () => {
196
+ await ifWe(sir, `verify v2 now also in source`, async () => {
197
197
  // Verify Tip (V2)
198
198
 
199
199
  iReckon(sir, await fnAddrExistsInSpace(addrV0, sourceSpace)).asTo('source has V0').isGonnaBeTrue();
@@ -205,7 +205,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
205
205
 
206
206
  });
207
207
 
208
- await ifWeMight(sir, `dependency graphs the same`, async () => {
208
+ await ifWe(sir, `dependency graphs the same`, async () => {
209
209
 
210
210
  const sourceDepGraph = await getDependencyGraph({
211
211
  ibGibAddr: addrV2,
@@ -234,7 +234,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
234
234
  // For now, we'll retrieve from spaces after sync completes
235
235
  let sessionKeystoneAddr: IbGibAddr | undefined;
236
236
 
237
- await ifWeMight(sir, 'IDENTITY: session keystone exists in sender space', async () => {
237
+ await ifWe(sir, 'IDENTITY: session keystone exists in sender space', async () => {
238
238
  // TODO: Get saga IbGib and access sessionKeystones rel8n
239
239
  // Once saga access is implemented (per Bill's guidance), retrieve keystone addr from:
240
240
  // const keystoneAddrs = sagaIbGib.rel8ns?.sessionKeystones;
@@ -258,7 +258,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
258
258
  .isGonnaBeTrue();
259
259
  });
260
260
 
261
- await ifWeMight(sir, 'IDENTITY: session keystone exists in receiver space', async () => {
261
+ await ifWe(sir, 'IDENTITY: session keystone exists in receiver space', async () => {
262
262
  // Session keystone should be transferred to receiver's durable space
263
263
  iReckon(sir, sessionKeystoneAddr)
264
264
  .asTo('session keystone address was captured')
@@ -272,7 +272,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
272
272
  }
273
273
  });
274
274
 
275
- await ifWeMight(sir, 'IDENTITY: saga frames are signed', async () => {
275
+ await ifWe(sir, 'IDENTITY: saga frames are signed', async () => {
276
276
  // TODO: Get saga frames and check each has a proof
277
277
  // This will FAIL when we actually check - that's the point (TDD RED)
278
278
 
@@ -281,7 +281,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
281
281
  .isGonnaBeTrue();
282
282
  });
283
283
 
284
- await ifWeMight(sir, 'IDENTITY: frame signatures are valid', async () => {
284
+ await ifWe(sir, 'IDENTITY: frame signatures are valid', async () => {
285
285
  // TODO: For each saga frame, validate proof against session keystone
286
286
  // const isValid = await validateProofWithKeystone({
287
287
  // proof: frame.proof,
@@ -296,7 +296,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
296
296
  .isGonnaBeTrue();
297
297
  });
298
298
 
299
- await ifWeMight(sir, 'IDENTITY: session keystone challenges are depleted', async () => {
299
+ await ifWe(sir, 'IDENTITY: session keystone challenges are depleted', async () => {
300
300
  // TODO: Session keystone should evolve after signing frames
301
301
  // This will FAIL because keystone evolution not implemented yet
302
302
 
@@ -305,7 +305,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
305
305
  .isGonnaBeTrue();
306
306
  });
307
307
 
308
- await ifWeMight(sir, 'IDENTITY: frame timestamps are present and fresh', async () => {
308
+ await ifWe(sir, 'IDENTITY: frame timestamps are present and fresh', async () => {
309
309
  // TODO: Check each frame has timestamp in proof claim
310
310
  // const claim = JSON.parse(frame.proof.claim.scope);
311
311
  // iReckon(sir, claim.timestamp).asTo('has timestamp').isGonnaBeTruthy();
@@ -318,7 +318,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
318
318
  .isGonnaBeTrue();
319
319
  });
320
320
 
321
- await ifWeMight(sir, 'IDENTITY: keystone has no hard links to domain ibgibs', async () => {
321
+ await ifWe(sir, 'IDENTITY: keystone has no hard links to domain ibgibs', async () => {
322
322
  if (sessionKeystoneAddr) {
323
323
  const keystoneResult = await getFromSpace({
324
324
  addr: sessionKeystoneAddr,
@@ -343,7 +343,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
343
343
  }
344
344
  });
345
345
 
346
- await ifWeMight(sir, 'IDENTITY: saga frames have no hard links to domain ibgibs', async () => {
346
+ await ifWe(sir, 'IDENTITY: saga frames have no hard links to domain ibgibs', async () => {
347
347
  // Saga frames should NOT have hard links to domain ibgibs
348
348
  // This currently PASSES but will expose issues if hard links exist
349
349
 
@@ -135,7 +135,7 @@ await respecfully(sir, `Sync InnerSpaces (Dest Ahead)`, async () => {
135
135
  const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
136
136
  await peer.initialized;
137
137
  await peer.initializeOpts({
138
- senderSpace: sourceSpace, // "Client"
138
+ localSpace: sourceSpace, // "Client"
139
139
  receiverSpace: destSpace, // "Server"
140
140
  receiverCoordinator,
141
141
  receiverMetaspace: metaspace,
@@ -108,7 +108,7 @@ await respecfully(sir, `Sync InnerSpaces (Multiple Timelines)`, async () => {
108
108
  const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
109
109
  await peer.initialized;
110
110
  await peer.initializeOpts({
111
- senderSpace: sourceSpace, // "Client"
111
+ localSpace: sourceSpace, // "Client"
112
112
  receiverSpace: destSpace, // "Server"
113
113
  receiverCoordinator,
114
114
  receiverMetaspace: metaspace,
@@ -116,7 +116,7 @@ await respecfully(sir, `Sync InnerSpaces (Partial Update)`, async () => {
116
116
  const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
117
117
  await peer.initialized;
118
118
  await peer.initializeOpts({
119
- senderSpace: sourceSpace, // "Client"
119
+ localSpace: sourceSpace, // "Client"
120
120
  receiverSpace: destSpace, // "Server"
121
121
  receiverCoordinator,
122
122
  receiverMetaspace: metaspace,
@@ -108,7 +108,7 @@ await respecfully(sir, `Sync InnerSpaces`, async () => {
108
108
  const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
109
109
  await peer.initialized;
110
110
  await peer.initializeOpts({
111
- senderSpace: sourceSpace, // "Client"
111
+ localSpace: sourceSpace, // "Client"
112
112
  receiverSpace: destSpace, // "Server"
113
113
  receiverCoordinator,
114
114
  receiverMetaspace: metaspace,