holosphere 2.0.0-alpha1 โ†’ 2.0.0-alpha10

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 (418) hide show
  1. package/CHANGELOG.md +473 -0
  2. package/FEATURES.md +431 -0
  3. package/LICENSE +29 -166
  4. package/LICENSE-AGPL.md +180 -0
  5. package/README.md +97 -16
  6. package/dist/2019-D2OG2idw.js +6680 -0
  7. package/dist/2019-D2OG2idw.js.map +1 -0
  8. package/dist/2019-EION3wKo.cjs +8 -0
  9. package/dist/2019-EION3wKo.cjs.map +1 -0
  10. package/dist/_commonjsHelpers-C37NGDzP.cjs +2 -0
  11. package/dist/_commonjsHelpers-C37NGDzP.cjs.map +1 -0
  12. package/dist/_commonjsHelpers-CUmg6egw.js +7 -0
  13. package/dist/_commonjsHelpers-CUmg6egw.js.map +1 -0
  14. package/dist/browser-BSniCNqO.js +3058 -0
  15. package/dist/browser-BSniCNqO.js.map +1 -0
  16. package/dist/browser-Cq59Ij19.cjs +2 -0
  17. package/dist/browser-Cq59Ij19.cjs.map +1 -0
  18. package/dist/cdn/holosphere.min.js +55 -0
  19. package/dist/cdn/holosphere.min.js.map +1 -0
  20. package/dist/cjs/holosphere.cjs +2 -0
  21. package/dist/cjs/holosphere.cjs.map +1 -0
  22. package/dist/esm/holosphere.js +53 -0
  23. package/dist/esm/holosphere.js.map +1 -0
  24. package/dist/index-DDGt_V9o.cjs +12 -0
  25. package/dist/index-DDGt_V9o.cjs.map +1 -0
  26. package/dist/index-DJXftyvB.js +39841 -0
  27. package/dist/index-DJXftyvB.js.map +1 -0
  28. package/dist/index-DMbdcMtK.cjs +18 -0
  29. package/dist/index-DMbdcMtK.cjs.map +1 -0
  30. package/dist/index-DeZ1xz_s.js +15104 -0
  31. package/dist/index-DeZ1xz_s.js.map +1 -0
  32. package/dist/indexeddb-storage-BFt6hMeF.js +176 -0
  33. package/dist/indexeddb-storage-BFt6hMeF.js.map +1 -0
  34. package/dist/indexeddb-storage-BK5tv4Sh.cjs +2 -0
  35. package/dist/indexeddb-storage-BK5tv4Sh.cjs.map +1 -0
  36. package/dist/memory-storage-C9HuoL2E.js +91 -0
  37. package/dist/memory-storage-C9HuoL2E.js.map +1 -0
  38. package/dist/memory-storage-Dao7jfYG.cjs +2 -0
  39. package/dist/memory-storage-Dao7jfYG.cjs.map +1 -0
  40. package/dist/secp256k1-BbKzbLtD.cjs +12 -0
  41. package/dist/secp256k1-BbKzbLtD.cjs.map +1 -0
  42. package/dist/secp256k1-CreY7Pcl.js +1890 -0
  43. package/dist/secp256k1-CreY7Pcl.js.map +1 -0
  44. package/docs/CONTRACTS.md +797 -0
  45. package/docs/FOSDEM_PROPOSAL.md +388 -0
  46. package/docs/LOCALFIRST.md +266 -0
  47. package/docs/api/ai_aggregation.js.html +333 -0
  48. package/docs/api/ai_breakdown.js.html +524 -0
  49. package/docs/api/ai_classifier.js.html +231 -0
  50. package/docs/api/ai_council.js.html +246 -0
  51. package/docs/api/ai_embeddings.js.html +304 -0
  52. package/docs/api/ai_federation-ai.js.html +338 -0
  53. package/docs/api/ai_h3-ai.js.html +970 -0
  54. package/docs/api/ai_index.js.html +124 -0
  55. package/docs/api/ai_json-ops.js.html +241 -0
  56. package/docs/api/ai_llm-service.js.html +239 -0
  57. package/docs/api/ai_nl-query.js.html +236 -0
  58. package/docs/api/ai_relationships.js.html +367 -0
  59. package/docs/api/ai_schema-extractor.js.html +235 -0
  60. package/docs/api/ai_spatial.js.html +307 -0
  61. package/docs/api/ai_tts.js.html +214 -0
  62. package/docs/api/content_social-protocols.js.html +180 -0
  63. package/docs/api/core_holosphere.js.html +757 -0
  64. package/docs/api/crypto_nostr-utils.js.html +306 -0
  65. package/docs/api/crypto_secp256k1.js.html +267 -0
  66. package/docs/api/data/search.json +1 -0
  67. package/docs/api/federation_discovery.js.html +337 -0
  68. package/docs/api/federation_handshake.js.html +478 -0
  69. package/docs/api/federation_hologram.js.html +1053 -0
  70. package/docs/api/federation_registry.js.html +389 -0
  71. package/docs/api/fonts/Inconsolata-Regular.ttf +0 -0
  72. package/docs/api/fonts/OpenSans-Regular.ttf +0 -0
  73. package/docs/api/fonts/WorkSans-Bold.ttf +0 -0
  74. package/docs/api/global.html +3 -0
  75. package/docs/api/hierarchical_upcast.js.html +128 -0
  76. package/docs/api/index.html +265 -0
  77. package/docs/api/index.js.html +1868 -0
  78. package/docs/api/lib_ai-methods.js.html +660 -0
  79. package/docs/api/lib_contract-methods.js.html +445 -0
  80. package/docs/api/lib_errors.js.html +56 -0
  81. package/docs/api/lib_federation-methods.js.html +348 -0
  82. package/docs/api/lib_index.js.html +33 -0
  83. package/docs/api/module-ai.html +5 -0
  84. package/docs/api/module-ai_aggregation-SmartAggregation.html +6 -0
  85. package/docs/api/module-ai_aggregation.SmartAggregation.html +3 -0
  86. package/docs/api/module-ai_aggregation.html +3 -0
  87. package/docs/api/module-ai_breakdown-TaskBreakdown.html +5 -0
  88. package/docs/api/module-ai_breakdown.TaskBreakdown.html +3 -0
  89. package/docs/api/module-ai_breakdown.html +3 -0
  90. package/docs/api/module-ai_classifier-Classifier.html +6 -0
  91. package/docs/api/module-ai_classifier.Classifier.html +3 -0
  92. package/docs/api/module-ai_classifier.html +3 -0
  93. package/docs/api/module-ai_council-Council.html +6 -0
  94. package/docs/api/module-ai_council.Council.html +3 -0
  95. package/docs/api/module-ai_council.html +3 -0
  96. package/docs/api/module-ai_embeddings-Embeddings.html +5 -0
  97. package/docs/api/module-ai_embeddings.Embeddings.html +3 -0
  98. package/docs/api/module-ai_embeddings.html +3 -0
  99. package/docs/api/module-ai_federation-ai-FederationAdvisor.html +6 -0
  100. package/docs/api/module-ai_federation-ai.FederationAdvisor.html +3 -0
  101. package/docs/api/module-ai_federation-ai.html +3 -0
  102. package/docs/api/module-ai_h3-ai-H3AI.html +6 -0
  103. package/docs/api/module-ai_h3-ai.H3AI.html +3 -0
  104. package/docs/api/module-ai_h3-ai.html +3 -0
  105. package/docs/api/module-ai_json-ops-JSONOps.html +5 -0
  106. package/docs/api/module-ai_json-ops.JSONOps.html +3 -0
  107. package/docs/api/module-ai_json-ops.html +3 -0
  108. package/docs/api/module-ai_llm-service-LLMService.html +5 -0
  109. package/docs/api/module-ai_llm-service.LLMService.html +3 -0
  110. package/docs/api/module-ai_llm-service.html +3 -0
  111. package/docs/api/module-ai_nl-query-NLQuery.html +5 -0
  112. package/docs/api/module-ai_nl-query.NLQuery.html +3 -0
  113. package/docs/api/module-ai_nl-query.html +3 -0
  114. package/docs/api/module-ai_relationships-RelationshipDiscovery.html +6 -0
  115. package/docs/api/module-ai_relationships.RelationshipDiscovery.html +3 -0
  116. package/docs/api/module-ai_relationships.html +3 -0
  117. package/docs/api/module-ai_schema-extractor-SchemaExtractor.html +5 -0
  118. package/docs/api/module-ai_schema-extractor.SchemaExtractor.html +3 -0
  119. package/docs/api/module-ai_schema-extractor.html +3 -0
  120. package/docs/api/module-ai_spatial-SpatialAnalysis.html +6 -0
  121. package/docs/api/module-ai_spatial.SpatialAnalysis.html +3 -0
  122. package/docs/api/module-ai_spatial.html +3 -0
  123. package/docs/api/module-ai_tts-TTS.html +5 -0
  124. package/docs/api/module-ai_tts.TTS.html +3 -0
  125. package/docs/api/module-ai_tts.html +3 -0
  126. package/docs/api/module-content_social-protocols.html +3 -0
  127. package/docs/api/module-core_holosphere-HoloSphere.html +6 -0
  128. package/docs/api/module-core_holosphere.HoloSphere.html +3 -0
  129. package/docs/api/module-core_holosphere.html +3 -0
  130. package/docs/api/module-crypto_nostr-utils.html +3 -0
  131. package/docs/api/module-crypto_secp256k1.html +3 -0
  132. package/docs/api/module-federation_hologram.html +3 -0
  133. package/docs/api/module-hierarchical_upcast.html +3 -0
  134. package/docs/api/module-holosphere-HoloSphereBase.html +3 -0
  135. package/docs/api/module-holosphere.html +3 -0
  136. package/docs/api/module-lib_ai-methods.html +3 -0
  137. package/docs/api/module-lib_contract-methods.html +3 -0
  138. package/docs/api/module-lib_errors-AuthorizationError.html +3 -0
  139. package/docs/api/module-lib_errors-ValidationError.html +3 -0
  140. package/docs/api/module-lib_errors.AuthorizationError.html +3 -0
  141. package/docs/api/module-lib_errors.ValidationError.html +3 -0
  142. package/docs/api/module-lib_errors.html +3 -0
  143. package/docs/api/module-lib_federation-methods.html +3 -0
  144. package/docs/api/module-lib_index.html +3 -0
  145. package/docs/api/module-schema_validator-ValidationError.html +3 -0
  146. package/docs/api/module-schema_validator.ValidationError.html +3 -0
  147. package/docs/api/module-schema_validator.html +3 -0
  148. package/docs/api/module-spatial_h3-operations.html +4 -0
  149. package/docs/api/module-storage_backend-factory.BackendFactory.html +3 -0
  150. package/docs/api/module-storage_backend-factory.html +3 -0
  151. package/docs/api/module-storage_backend-interface-StorageBackend.html +3 -0
  152. package/docs/api/module-storage_backend-interface.StorageBackend.html +3 -0
  153. package/docs/api/module-storage_backend-interface.html +3 -0
  154. package/docs/api/module-storage_backends_activitypub-backend-ActivityPubBackend.html +7 -0
  155. package/docs/api/module-storage_backends_activitypub-backend.ActivityPubBackend.html +3 -0
  156. package/docs/api/module-storage_backends_activitypub-backend.html +3 -0
  157. package/docs/api/module-storage_backends_activitypub_server-ActivityPubServer.html +8 -0
  158. package/docs/api/module-storage_backends_activitypub_server.ActivityPubServer.html +3 -0
  159. package/docs/api/module-storage_backends_activitypub_server.html +3 -0
  160. package/docs/api/module-storage_backends_gundb-backend-GunDBBackend.html +7 -0
  161. package/docs/api/module-storage_backends_gundb-backend.GunDBBackend.html +3 -0
  162. package/docs/api/module-storage_backends_gundb-backend.html +3 -0
  163. package/docs/api/module-storage_backends_nostr-backend-NostrBackend.html +8 -0
  164. package/docs/api/module-storage_backends_nostr-backend.NostrBackend.html +3 -0
  165. package/docs/api/module-storage_backends_nostr-backend.html +3 -0
  166. package/docs/api/module-storage_filesystem-storage-FileSystemStorage.html +5 -0
  167. package/docs/api/module-storage_filesystem-storage-browser-FileSystemStorage.html +3 -0
  168. package/docs/api/module-storage_filesystem-storage-browser.FileSystemStorage.html +3 -0
  169. package/docs/api/module-storage_filesystem-storage-browser.html +3 -0
  170. package/docs/api/module-storage_filesystem-storage.FileSystemStorage.html +3 -0
  171. package/docs/api/module-storage_filesystem-storage.html +3 -0
  172. package/docs/api/module-storage_global-tables.html +3 -0
  173. package/docs/api/module-storage_gun-async.html +3 -0
  174. package/docs/api/module-storage_gun-auth-GunAuth.html +5 -0
  175. package/docs/api/module-storage_gun-auth.GunAuth.html +3 -0
  176. package/docs/api/module-storage_gun-auth.html +3 -0
  177. package/docs/api/module-storage_gun-federation.html +3 -0
  178. package/docs/api/module-storage_gun-references-GunReferenceHandler.html +5 -0
  179. package/docs/api/module-storage_gun-references.GunReferenceHandler.html +3 -0
  180. package/docs/api/module-storage_gun-references.html +3 -0
  181. package/docs/api/module-storage_gun-schema-GunSchemaValidator.html +5 -0
  182. package/docs/api/module-storage_gun-schema.GunSchemaValidator.html +3 -0
  183. package/docs/api/module-storage_gun-schema.html +3 -0
  184. package/docs/api/module-storage_gun-wrapper.html +11 -0
  185. package/docs/api/module-storage_indexeddb-storage-IndexedDBStorage.html +5 -0
  186. package/docs/api/module-storage_indexeddb-storage.IndexedDBStorage.html +3 -0
  187. package/docs/api/module-storage_indexeddb-storage.html +3 -0
  188. package/docs/api/module-storage_key-storage-simple.html +3 -0
  189. package/docs/api/module-storage_key-storage.html +4 -0
  190. package/docs/api/module-storage_memory-storage-MemoryStorage.html +5 -0
  191. package/docs/api/module-storage_memory-storage.MemoryStorage.html +3 -0
  192. package/docs/api/module-storage_memory-storage.html +3 -0
  193. package/docs/api/module-storage_migration-MigrationTool.html +6 -0
  194. package/docs/api/module-storage_migration.MigrationTool.html +3 -0
  195. package/docs/api/module-storage_migration.html +3 -0
  196. package/docs/api/module-storage_nostr-async.html +18 -0
  197. package/docs/api/module-storage_nostr-client-LRUCache.html +3 -0
  198. package/docs/api/module-storage_nostr-client-NostrClient.html +7 -0
  199. package/docs/api/module-storage_nostr-client.NostrClient.html +15 -0
  200. package/docs/api/module-storage_nostr-client.html +6 -0
  201. package/docs/api/module-storage_nostr-wrapper.html +3 -0
  202. package/docs/api/module-storage_outbox-queue-OutboxQueue.html +4 -0
  203. package/docs/api/module-storage_outbox-queue.OutboxQueue.html +3 -0
  204. package/docs/api/module-storage_outbox-queue.html +3 -0
  205. package/docs/api/module-storage_persistent-storage-PersistentStorage.html +3 -0
  206. package/docs/api/module-storage_persistent-storage.html +4 -0
  207. package/docs/api/module-storage_sync-service-SyncService.html +5 -0
  208. package/docs/api/module-storage_sync-service.SyncService.html +3 -0
  209. package/docs/api/module-storage_sync-service.html +3 -0
  210. package/docs/api/module-storage_unified-storage.html +3 -0
  211. package/docs/api/module-subscriptions_manager.SubscriptionRegistry.html +3 -0
  212. package/docs/api/module-subscriptions_manager.html +3 -0
  213. package/docs/api/schema_validator.js.html +113 -0
  214. package/docs/api/scripts/core.js +726 -0
  215. package/docs/api/scripts/core.min.js +23 -0
  216. package/docs/api/scripts/resize.js +90 -0
  217. package/docs/api/scripts/search.js +265 -0
  218. package/docs/api/scripts/search.min.js +6 -0
  219. package/docs/api/scripts/third-party/Apache-License-2.0.txt +202 -0
  220. package/docs/api/scripts/third-party/fuse.js +9 -0
  221. package/docs/api/scripts/third-party/hljs-line-num-original.js +369 -0
  222. package/docs/api/scripts/third-party/hljs-line-num.js +1 -0
  223. package/docs/api/scripts/third-party/hljs-original.js +5171 -0
  224. package/docs/api/scripts/third-party/hljs.js +1 -0
  225. package/docs/api/scripts/third-party/popper.js +5 -0
  226. package/docs/api/scripts/third-party/tippy.js +1 -0
  227. package/docs/api/scripts/third-party/tocbot.js +672 -0
  228. package/docs/api/scripts/third-party/tocbot.min.js +1 -0
  229. package/docs/api/spatial_h3-operations.js.html +129 -0
  230. package/docs/api/storage_backend-factory.js.html +133 -0
  231. package/docs/api/storage_backend-interface.js.html +164 -0
  232. package/docs/api/storage_backends_activitypub-backend.js.html +298 -0
  233. package/docs/api/storage_backends_activitypub_server.js.html +678 -0
  234. package/docs/api/storage_backends_gundb-backend.js.html +878 -0
  235. package/docs/api/storage_backends_nostr-backend.js.html +254 -0
  236. package/docs/api/storage_filesystem-storage-browser.js.html +83 -0
  237. package/docs/api/storage_filesystem-storage.js.html +207 -0
  238. package/docs/api/storage_global-tables.js.html +116 -0
  239. package/docs/api/storage_gun-async.js.html +344 -0
  240. package/docs/api/storage_gun-auth.js.html +376 -0
  241. package/docs/api/storage_gun-federation.js.html +788 -0
  242. package/docs/api/storage_gun-references.js.html +212 -0
  243. package/docs/api/storage_gun-schema.js.html +309 -0
  244. package/docs/api/storage_gun-wrapper.js.html +645 -0
  245. package/docs/api/storage_indexeddb-storage.js.html +224 -0
  246. package/docs/api/storage_key-storage-simple.js.html +102 -0
  247. package/docs/api/storage_key-storage.js.html +171 -0
  248. package/docs/api/storage_memory-storage.js.html +128 -0
  249. package/docs/api/storage_migration.js.html +354 -0
  250. package/docs/api/storage_nostr-async.js.html +1076 -0
  251. package/docs/api/storage_nostr-client.js.html +1598 -0
  252. package/docs/api/storage_nostr-wrapper.js.html +218 -0
  253. package/docs/api/storage_outbox-queue.js.html +248 -0
  254. package/docs/api/storage_persistent-storage.js.html +160 -0
  255. package/docs/api/storage_sync-service.js.html +201 -0
  256. package/docs/api/storage_unified-storage.js.html +157 -0
  257. package/docs/api/styles/clean-jsdoc-theme-base.css +1159 -0
  258. package/docs/api/styles/clean-jsdoc-theme-dark.css +412 -0
  259. package/docs/api/styles/clean-jsdoc-theme-light.css +482 -0
  260. package/docs/api/styles/clean-jsdoc-theme-scrollbar.css +30 -0
  261. package/docs/api/styles/clean-jsdoc-theme-without-scrollbar.min.css +1 -0
  262. package/docs/api/styles/clean-jsdoc-theme.min.css +1 -0
  263. package/docs/api/subscriptions_manager.js.html +162 -0
  264. package/docs/contracts/api-interface.md +793 -0
  265. package/docs/data-model.md +476 -0
  266. package/docs/gun-async-usage.md +338 -0
  267. package/docs/plan.md +349 -0
  268. package/docs/quickstart.md +674 -0
  269. package/docs/research.md +362 -0
  270. package/docs/spec.md +244 -0
  271. package/docs/storage-backends.md +326 -0
  272. package/docs/tasks.md +947 -0
  273. package/examples/demo.html +47 -0
  274. package/examples/holosphere-widget.js +1242 -0
  275. package/examples/widget-demo.html +274 -0
  276. package/examples/widget.html +703 -0
  277. package/jsdoc.json +26 -0
  278. package/package.json +25 -7
  279. package/src/ai/aggregation.js +13 -2
  280. package/src/ai/breakdown.js +12 -2
  281. package/src/ai/classifier.js +14 -3
  282. package/src/ai/council.js +22 -7
  283. package/src/ai/embeddings.js +37 -15
  284. package/src/ai/federation-ai.js +13 -2
  285. package/src/ai/h3-ai.js +14 -2
  286. package/src/ai/index.js +16 -7
  287. package/src/ai/json-ops.js +18 -5
  288. package/src/ai/llm-service.js +62 -31
  289. package/src/ai/nl-query.js +12 -2
  290. package/src/ai/relationships.js +13 -2
  291. package/src/ai/schema-extractor.js +24 -10
  292. package/src/ai/spatial.js +13 -2
  293. package/src/ai/tts.js +25 -8
  294. package/src/cdn-entry.js +22 -0
  295. package/src/content/social-protocols.js +34 -25
  296. package/src/contracts/abis/Appreciative.json +1280 -0
  297. package/src/contracts/abis/AppreciativeFactory.json +101 -0
  298. package/src/contracts/abis/Bundle.json +1438 -0
  299. package/src/contracts/abis/BundleFactory.json +106 -0
  300. package/src/contracts/abis/Holon.json +881 -0
  301. package/src/contracts/abis/Holons.json +330 -0
  302. package/src/contracts/abis/Managed.json +1262 -0
  303. package/src/contracts/abis/ManagedFactory.json +149 -0
  304. package/src/contracts/abis/Membrane.json +261 -0
  305. package/src/contracts/abis/Splitter.json +1624 -0
  306. package/src/contracts/abis/SplitterFactory.json +220 -0
  307. package/src/contracts/abis/TestToken.json +321 -0
  308. package/src/contracts/abis/Zoned.json +1461 -0
  309. package/src/contracts/abis/ZonedFactory.json +154 -0
  310. package/src/contracts/chain-manager.js +403 -0
  311. package/src/contracts/deployer.js +500 -0
  312. package/src/contracts/event-listener.js +539 -0
  313. package/src/contracts/holon-contracts.js +359 -0
  314. package/src/contracts/index.js +82 -0
  315. package/src/contracts/networks.js +229 -0
  316. package/src/contracts/operations.js +687 -0
  317. package/src/contracts/queries.js +638 -0
  318. package/src/core/holosphere.js +487 -6
  319. package/src/crypto/nostr-utils.js +303 -0
  320. package/src/crypto/secp256k1.js +7 -2
  321. package/src/federation/handshake.js +475 -0
  322. package/src/federation/hologram.js +117 -3
  323. package/src/hierarchical/upcast.js +40 -25
  324. package/src/index.js +1501 -1909
  325. package/src/lib/ai-methods.js +657 -0
  326. package/src/lib/contract-methods.js +442 -0
  327. package/src/lib/errors.js +53 -0
  328. package/src/lib/federation-methods.js +345 -0
  329. package/src/lib/index.js +30 -0
  330. package/src/schema/validator.js +22 -3
  331. package/src/spatial/h3-operations.js +19 -3
  332. package/src/storage/backend-factory.js +7 -2
  333. package/src/storage/backend-interface.js +21 -2
  334. package/src/storage/backends/activitypub/server.js +25 -3
  335. package/src/storage/backends/activitypub-backend.js +25 -2
  336. package/src/storage/backends/gundb-backend.js +692 -50
  337. package/src/storage/backends/nostr-backend.js +116 -1
  338. package/src/storage/filesystem-storage-browser.js +42 -2
  339. package/src/storage/filesystem-storage.js +72 -5
  340. package/src/storage/global-tables.js +35 -3
  341. package/src/storage/gun-async.js +75 -15
  342. package/src/storage/gun-auth.js +373 -0
  343. package/src/storage/gun-federation.js +785 -0
  344. package/src/storage/gun-references.js +209 -0
  345. package/src/storage/gun-schema.js +306 -0
  346. package/src/storage/gun-wrapper.js +475 -54
  347. package/src/storage/indexeddb-storage.js +112 -13
  348. package/src/storage/key-storage-simple.js +32 -9
  349. package/src/storage/key-storage.js +45 -13
  350. package/src/storage/memory-storage.js +68 -2
  351. package/src/storage/migration.js +20 -7
  352. package/src/storage/nostr-async.js +412 -122
  353. package/src/storage/nostr-client.js +749 -76
  354. package/src/storage/nostr-wrapper.js +6 -2
  355. package/src/storage/outbox-queue.js +55 -18
  356. package/src/storage/persistent-storage.js +62 -14
  357. package/src/storage/sync-service.js +51 -17
  358. package/src/storage/unified-storage.js +154 -0
  359. package/src/subscriptions/manager.js +34 -17
  360. package/types/index.d.ts +133 -0
  361. package/vite.config.cdn.js +60 -0
  362. package/tests/unit/ai/aggregation.test.js +0 -295
  363. package/tests/unit/ai/breakdown.test.js +0 -446
  364. package/tests/unit/ai/classifier.test.js +0 -294
  365. package/tests/unit/ai/council.test.js +0 -262
  366. package/tests/unit/ai/embeddings.test.js +0 -384
  367. package/tests/unit/ai/federation-ai.test.js +0 -344
  368. package/tests/unit/ai/h3-ai.test.js +0 -458
  369. package/tests/unit/ai/index.test.js +0 -304
  370. package/tests/unit/ai/json-ops.test.js +0 -307
  371. package/tests/unit/ai/llm-service.test.js +0 -390
  372. package/tests/unit/ai/nl-query.test.js +0 -383
  373. package/tests/unit/ai/relationships.test.js +0 -311
  374. package/tests/unit/ai/schema-extractor.test.js +0 -384
  375. package/tests/unit/ai/spatial.test.js +0 -279
  376. package/tests/unit/ai/tts.test.js +0 -279
  377. package/tests/unit/content.test.js +0 -332
  378. package/tests/unit/contract/core.test.js +0 -88
  379. package/tests/unit/contract/crypto.test.js +0 -198
  380. package/tests/unit/contract/data.test.js +0 -223
  381. package/tests/unit/contract/federation.test.js +0 -181
  382. package/tests/unit/contract/hierarchical.test.js +0 -113
  383. package/tests/unit/contract/schema.test.js +0 -114
  384. package/tests/unit/contract/social.test.js +0 -217
  385. package/tests/unit/contract/spatial.test.js +0 -110
  386. package/tests/unit/contract/subscriptions.test.js +0 -128
  387. package/tests/unit/contract/utils.test.js +0 -159
  388. package/tests/unit/core.test.js +0 -152
  389. package/tests/unit/crypto.test.js +0 -328
  390. package/tests/unit/federation.test.js +0 -234
  391. package/tests/unit/gun-async.test.js +0 -252
  392. package/tests/unit/hierarchical.test.js +0 -399
  393. package/tests/unit/integration/scenario-01-geographic-storage.test.js +0 -74
  394. package/tests/unit/integration/scenario-02-federation.test.js +0 -76
  395. package/tests/unit/integration/scenario-03-subscriptions.test.js +0 -102
  396. package/tests/unit/integration/scenario-04-validation.test.js +0 -129
  397. package/tests/unit/integration/scenario-05-hierarchy.test.js +0 -125
  398. package/tests/unit/integration/scenario-06-social.test.js +0 -135
  399. package/tests/unit/integration/scenario-07-persistence.test.js +0 -130
  400. package/tests/unit/integration/scenario-08-authorization.test.js +0 -161
  401. package/tests/unit/integration/scenario-09-cross-dimensional.test.js +0 -139
  402. package/tests/unit/integration/scenario-10-cross-holosphere-capabilities.test.js +0 -357
  403. package/tests/unit/integration/scenario-11-cross-holosphere-federation.test.js +0 -410
  404. package/tests/unit/integration/scenario-12-capability-federated-read.test.js +0 -719
  405. package/tests/unit/performance/benchmark.test.js +0 -85
  406. package/tests/unit/schema.test.js +0 -213
  407. package/tests/unit/spatial.test.js +0 -158
  408. package/tests/unit/storage.test.js +0 -195
  409. package/tests/unit/subscriptions.test.js +0 -328
  410. package/tests/unit/test-data-permanence-debug.js +0 -197
  411. package/tests/unit/test-data-permanence.js +0 -340
  412. package/tests/unit/test-key-persistence-fixed.js +0 -148
  413. package/tests/unit/test-key-persistence.js +0 -172
  414. package/tests/unit/test-relay-permanence.js +0 -376
  415. package/tests/unit/test-second-node.js +0 -95
  416. package/tests/unit/test-simple-write.js +0 -89
  417. /package/{cleanup-test-data.js โ†’ scripts/cleanup-test-data.js} +0 -0
  418. /package/{test-ai-real-api.js โ†’ scripts/test-ai-real-api.js} +0 -0
@@ -0,0 +1,1053 @@
1
+ <!DOCTYPE html><html lang="en" style="font-size:16px"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Source: federation/hologram.js</title><!--[if lt IE 9]>
2
+ <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
3
+ <![endif]--><script src="scripts/third-party/hljs.js" defer="defer"></script><script src="scripts/third-party/hljs-line-num.js" defer="defer"></script><script src="scripts/third-party/popper.js" defer="defer"></script><script src="scripts/third-party/tippy.js" defer="defer"></script><script src="scripts/third-party/tocbot.min.js"></script><script>var baseURL="/",locationPathname="";baseURL=(locationPathname=document.location.pathname).substr(0,locationPathname.lastIndexOf("/")+1)</script><link rel="stylesheet" href="styles/clean-jsdoc-theme.min.css"><svg aria-hidden="true" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:none"><defs><symbol id="copy-icon" viewbox="0 0 488.3 488.3"><g><path d="M314.25,85.4h-227c-21.3,0-38.6,17.3-38.6,38.6v325.7c0,21.3,17.3,38.6,38.6,38.6h227c21.3,0,38.6-17.3,38.6-38.6V124 C352.75,102.7,335.45,85.4,314.25,85.4z M325.75,449.6c0,6.4-5.2,11.6-11.6,11.6h-227c-6.4,0-11.6-5.2-11.6-11.6V124 c0-6.4,5.2-11.6,11.6-11.6h227c6.4,0,11.6,5.2,11.6,11.6V449.6z"/><path d="M401.05,0h-227c-21.3,0-38.6,17.3-38.6,38.6c0,7.5,6,13.5,13.5,13.5s13.5-6,13.5-13.5c0-6.4,5.2-11.6,11.6-11.6h227 c6.4,0,11.6,5.2,11.6,11.6v325.7c0,6.4-5.2,11.6-11.6,11.6c-7.5,0-13.5,6-13.5,13.5s6,13.5,13.5,13.5c21.3,0,38.6-17.3,38.6-38.6 V38.6C439.65,17.3,422.35,0,401.05,0z"/></g></symbol><symbol id="search-icon" viewBox="0 0 512 512"><g><g><path d="M225.474,0C101.151,0,0,101.151,0,225.474c0,124.33,101.151,225.474,225.474,225.474 c124.33,0,225.474-101.144,225.474-225.474C450.948,101.151,349.804,0,225.474,0z M225.474,409.323 c-101.373,0-183.848-82.475-183.848-183.848S124.101,41.626,225.474,41.626s183.848,82.475,183.848,183.848 S326.847,409.323,225.474,409.323z"/></g></g><g><g><path d="M505.902,476.472L386.574,357.144c-8.131-8.131-21.299-8.131-29.43,0c-8.131,8.124-8.131,21.306,0,29.43l119.328,119.328 c4.065,4.065,9.387,6.098,14.715,6.098c5.321,0,10.649-2.033,14.715-6.098C514.033,497.778,514.033,484.596,505.902,476.472z"/></g></g></symbol><symbol id="font-size-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11.246 15H4.754l-2 5H.6L7 4h2l6.4 16h-2.154l-2-5zm-.8-2L8 6.885 5.554 13h4.892zM21 12.535V12h2v8h-2v-.535a4 4 0 1 1 0-6.93zM19 18a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/></symbol><symbol id="add-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z"/></symbol><symbol id="minus-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M5 11h14v2H5z"/></symbol><symbol id="dark-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938 7.999 7.999 0 0 0 4 12z"/></symbol><symbol id="light-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z"/></symbol><symbol id="reset-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M18.537 19.567A9.961 9.961 0 0 1 12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10c0 2.136-.67 4.116-1.81 5.74L17 12h3a8 8 0 1 0-2.46 5.772l.997 1.795z"/></symbol><symbol id="down-icon" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M12.7803 6.21967C13.0732 6.51256 13.0732 6.98744 12.7803 7.28033L8.53033 11.5303C8.23744 11.8232 7.76256 11.8232 7.46967 11.5303L3.21967 7.28033C2.92678 6.98744 2.92678 6.51256 3.21967 6.21967C3.51256 5.92678 3.98744 5.92678 4.28033 6.21967L8 9.93934L11.7197 6.21967C12.0126 5.92678 12.4874 5.92678 12.7803 6.21967Z"></path></symbol><symbol id="codepen-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M16.5 13.202L13 15.535v3.596L19.197 15 16.5 13.202zM14.697 12L12 10.202 9.303 12 12 13.798 14.697 12zM20 10.869L18.303 12 20 13.131V10.87zM19.197 9L13 4.869v3.596l3.5 2.333L19.197 9zM7.5 10.798L11 8.465V4.869L4.803 9 7.5 10.798zM4.803 15L11 19.131v-3.596l-3.5-2.333L4.803 15zM4 13.131L5.697 12 4 10.869v2.262zM2 9a1 1 0 0 1 .445-.832l9-6a1 1 0 0 1 1.11 0l9 6A1 1 0 0 1 22 9v6a1 1 0 0 1-.445.832l-9 6a1 1 0 0 1-1.11 0l-9-6A1 1 0 0 1 2 15V9z"/></symbol><symbol id="close-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"/></symbol><symbol id="menu-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M3 4h18v2H3V4zm0 7h18v2H3v-2zm0 7h18v2H3v-2z"/></symbol></defs></svg></head><body data-theme="dark"><div class="sidebar-container"><div class="sidebar" id="sidebar"><div class="sidebar-items-container"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-ai.html">ai</a></div><div class="sidebar-section-children"><a href="module-ai_aggregation.html">ai/aggregation</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown.html">ai/breakdown</a></div><div class="sidebar-section-children"><a href="module-ai_classifier.html">ai/classifier</a></div><div class="sidebar-section-children"><a href="module-ai_council.html">ai/council</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings.html">ai/embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai.html">ai/federation-ai</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai.html">ai/h3-ai</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops.html">ai/json-ops</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service.html">ai/llm-service</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query.html">ai/nl-query</a></div><div class="sidebar-section-children"><a href="module-ai_relationships.html">ai/relationships</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor.html">ai/schema-extractor</a></div><div class="sidebar-section-children"><a href="module-ai_spatial.html">ai/spatial</a></div><div class="sidebar-section-children"><a href="module-ai_tts.html">ai/tts</a></div><div class="sidebar-section-children"><a href="module-content_social-protocols.html">content/social-protocols</a></div><div class="sidebar-section-children"><a href="module-core_holosphere.html">core/holosphere</a></div><div class="sidebar-section-children"><a href="module-crypto_nostr-utils.html">crypto/nostr-utils</a></div><div class="sidebar-section-children"><a href="module-crypto_secp256k1.html">crypto/secp256k1</a></div><div class="sidebar-section-children"><a href="module-federation_hologram.html">federation/hologram</a></div><div class="sidebar-section-children"><a href="module-hierarchical_upcast.html">hierarchical/upcast</a></div><div class="sidebar-section-children"><a href="module-holosphere.html">holosphere</a></div><div class="sidebar-section-children"><a href="module-lib_ai-methods.html">lib/ai-methods</a></div><div class="sidebar-section-children"><a href="module-lib_contract-methods.html">lib/contract-methods</a></div><div class="sidebar-section-children"><a href="module-lib_errors.html">lib/errors</a></div><div class="sidebar-section-children"><a href="module-lib_federation-methods.html">lib/federation-methods</a></div><div class="sidebar-section-children"><a href="module-lib_index.html">lib/index</a></div><div class="sidebar-section-children"><a href="module-schema_validator.html">schema/validator</a></div><div class="sidebar-section-children"><a href="module-spatial_h3-operations.html">spatial/h3-operations</a></div><div class="sidebar-section-children"><a href="module-storage_backend-factory.html">storage/backend-factory</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface.html">storage/backend-interface</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend.html">storage/backends/activitypub-backend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server.html">storage/backends/activitypub/server</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend.html">storage/backends/gundb-backend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend.html">storage/backends/nostr-backend</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage.html">storage/filesystem-storage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser.html">storage/filesystem-storage-browser</a></div><div class="sidebar-section-children"><a href="module-storage_global-tables.html">storage/global-tables</a></div><div class="sidebar-section-children"><a href="module-storage_gun-async.html">storage/gun-async</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth.html">storage/gun-auth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-federation.html">storage/gun-federation</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references.html">storage/gun-references</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema.html">storage/gun-schema</a></div><div class="sidebar-section-children"><a href="module-storage_gun-wrapper.html">storage/gun-wrapper</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage.html">storage/indexeddb-storage</a></div><div class="sidebar-section-children"><a href="module-storage_key-storage.html">storage/key-storage</a></div><div class="sidebar-section-children"><a href="module-storage_key-storage-simple.html">storage/key-storage-simple</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage.html">storage/memory-storage</a></div><div class="sidebar-section-children"><a href="module-storage_migration.html">storage/migration</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-async.html">storage/nostr-async</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client.html">storage/nostr-client</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-wrapper.html">storage/nostr-wrapper</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue.html">storage/outbox-queue</a></div><div class="sidebar-section-children"><a href="module-storage_persistent-storage.html">storage/persistent-storage</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service.html">storage/sync-service</a></div><div class="sidebar-section-children"><a href="module-storage_unified-storage.html">storage/unified-storage</a></div><div class="sidebar-section-children"><a href="module-subscriptions_manager.html">subscriptions/manager</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-classes"><div>Classes</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-ai_aggregation.SmartAggregation.html">SmartAggregation</a></div><div class="sidebar-section-children"><a href="module-ai_aggregation-SmartAggregation.html">SmartAggregation</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown.TaskBreakdown.html">TaskBreakdown</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown-TaskBreakdown.html">TaskBreakdown</a></div><div class="sidebar-section-children"><a href="module-ai_classifier.Classifier.html">Classifier</a></div><div class="sidebar-section-children"><a href="module-ai_classifier-Classifier.html">Classifier</a></div><div class="sidebar-section-children"><a href="module-ai_council.Council.html">Council</a></div><div class="sidebar-section-children"><a href="module-ai_council-Council.html">Council</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings.Embeddings.html">Embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings-Embeddings.html">Embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai.FederationAdvisor.html">FederationAdvisor</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai-FederationAdvisor.html">FederationAdvisor</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai.H3AI.html">H3AI</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai-H3AI.html">H3AI</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops.JSONOps.html">JSONOps</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops-JSONOps.html">JSONOps</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service.LLMService.html">LLMService</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service-LLMService.html">LLMService</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query.NLQuery.html">NLQuery</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query-NLQuery.html">NLQuery</a></div><div class="sidebar-section-children"><a href="module-ai_relationships.RelationshipDiscovery.html">RelationshipDiscovery</a></div><div class="sidebar-section-children"><a href="module-ai_relationships-RelationshipDiscovery.html">RelationshipDiscovery</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor.SchemaExtractor.html">SchemaExtractor</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor-SchemaExtractor.html">SchemaExtractor</a></div><div class="sidebar-section-children"><a href="module-ai_spatial.SpatialAnalysis.html">SpatialAnalysis</a></div><div class="sidebar-section-children"><a href="module-ai_spatial-SpatialAnalysis.html">SpatialAnalysis</a></div><div class="sidebar-section-children"><a href="module-ai_tts.TTS.html">TTS</a></div><div class="sidebar-section-children"><a href="module-ai_tts-TTS.html">TTS</a></div><div class="sidebar-section-children"><a href="module-core_holosphere.HoloSphere.html">HoloSphere</a></div><div class="sidebar-section-children"><a href="module-core_holosphere-HoloSphere.html">HoloSphere</a></div><div class="sidebar-section-children"><a href="module-holosphere-HoloSphereBase.html">HoloSphereBase</a></div><div class="sidebar-section-children"><a href="module-holosphere-HoloSphereBase.html">HoloSphereBase</a></div><div class="sidebar-section-children"><a href="module-lib_errors.AuthorizationError.html">AuthorizationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors.ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors-AuthorizationError.html">AuthorizationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors-ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-schema_validator.ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-schema_validator-ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-storage_backend-factory.BackendFactory.html">BackendFactory</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface.StorageBackend.html">StorageBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface-StorageBackend.html">StorageBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend.ActivityPubBackend.html">ActivityPubBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend-ActivityPubBackend.html">ActivityPubBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server.ActivityPubServer.html">ActivityPubServer</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server-ActivityPubServer.html">ActivityPubServer</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend.GunDBBackend.html">GunDBBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend-GunDBBackend.html">GunDBBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend.NostrBackend.html">NostrBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend-NostrBackend.html">NostrBackend</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser.FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser-FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage.FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth.GunAuth.html">GunAuth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth-GunAuth.html">GunAuth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references.GunReferenceHandler.html">GunReferenceHandler</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references-GunReferenceHandler.html">GunReferenceHandler</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema.GunSchemaValidator.html">GunSchemaValidator</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema-GunSchemaValidator.html">GunSchemaValidator</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage.IndexedDBStorage.html">IndexedDBStorage</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage-IndexedDBStorage.html">IndexedDBStorage</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage.MemoryStorage.html">MemoryStorage</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage-MemoryStorage.html">MemoryStorage</a></div><div class="sidebar-section-children"><a href="module-storage_migration.MigrationTool.html">MigrationTool</a></div><div class="sidebar-section-children"><a href="module-storage_migration-MigrationTool.html">MigrationTool</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client.NostrClient.html">NostrClient</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client-LRUCache.html">LRUCache</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client-NostrClient.html">NostrClient</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue.OutboxQueue.html">OutboxQueue</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue-OutboxQueue.html">OutboxQueue</a></div><div class="sidebar-section-children"><a href="module-storage_persistent-storage-PersistentStorage.html">PersistentStorage</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service.SyncService.html">SyncService</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service-SyncService.html">SyncService</a></div><div class="sidebar-section-children"><a href="module-subscriptions_manager.SubscriptionRegistry.html">SubscriptionRegistry</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-global"><div>Global</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="global.html#FederationRequestPayload">FederationRequestPayload</a></div><div class="sidebar-section-children"><a href="global.html#FederationResponsePayload">FederationResponsePayload</a></div><div class="sidebar-section-children"><a href="global.html#acceptFederationRequest">acceptFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#acceptFederationRequest">acceptFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#addFederatedPartner">addFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#cleanupExpiredCapabilities">cleanupExpiredCapabilities</a></div><div class="sidebar-section-children"><a href="global.html#createFederationRequest">createFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#createFederationResponse">createFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#declineFederationRequest">declineFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#getCapabilityForAuthor">getCapabilityForAuthor</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedAuthors">getFederatedAuthors</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedAuthorsForScope">getFederatedAuthorsForScope</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedPartner">getFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#getFederationRegistry">getFederationRegistry</a></div><div class="sidebar-section-children"><a href="global.html#getPendingFederationRequests">getPendingFederationRequests</a></div><div class="sidebar-section-children"><a href="global.html#initiateFederationHandshake">initiateFederationHandshake</a></div><div class="sidebar-section-children"><a href="global.html#isFederationRequest">isFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#isFederationResponse">isFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#rejectFederationRequest">rejectFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#removeFederatedPartner">removeFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#revokeOutboundCapability">revokeOutboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#saveFederationRegistry">saveFederationRegistry</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationRequest">sendFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationRequest">sendFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationResponse">sendFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#storeInboundCapability">storeInboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#storeOutboundCapability">storeOutboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationAcceptances">subscribeFederationAcceptances</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationDeclines">subscribeFederationDeclines</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationRequests">subscribeFederationRequests</a></div><div class="sidebar-section-children"><a href="global.html#subscribeToFederationDMs">subscribeToFederationDMs</a></div><div class="sidebar-section-children"><a href="global.html#updateDiscoverySettings">updateDiscoverySettings</a></div></div></div></div></div><div class="navbar-container" id="VuAckcnZhf"><nav class="navbar"><div class="navbar-left-items"></div><div class="navbar-right-items"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#light-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div><nav></nav></nav></div><div class="toc-container"><div class="toc-content"><span class="bold">On this page</span><div id="eed4d2a0bfd64539bb9df78095dec881"></div></div></div><div class="body-wrapper"><div class="main-content"><div class="main-wrapper"><section id="source-page" class="source-page"><header><h1 id="title" class="has-anchor">federation_hologram.js</h1></header><article><pre class="prettyprint source lang-js"><code>/**
4
+ * @fileoverview Federation and Hologram (Reference) Management.
5
+ *
6
+ * Provides hologram (lightweight reference) creation, resolution, and management.
7
+ * Holograms enable data to appear in multiple holons while maintaining a single
8
+ * source of truth. Supports circular reference detection and cross-holosphere
9
+ * federation with capability-based access control.
10
+ *
11
+ * @module federation/hologram
12
+ */
13
+
14
+ import { buildPath, write, read, update } from '../storage/unified-storage.js';
15
+ import { verifyCapability } from '../crypto/secp256k1.js';
16
+ import { getCapabilityForAuthor } from './registry.js';
17
+
18
+ /** @constant {number} Maximum depth for hologram resolution chain */
19
+ const MAX_RESOLUTION_DEPTH = 10;
20
+
21
+ /**
22
+ * Check if creating a hologram would result in a circular reference
23
+ * This follows the chain from the source to see if it eventually points back to the target
24
+ * @param {Object} client - Nostr client instance
25
+ * @param {string} appname - Application namespace
26
+ * @param {string} sourceHolon - Source holon ID (where original data lives)
27
+ * @param {string} targetHolon - Target holon ID (where hologram would be created)
28
+ * @param {string} lensName - Lens name
29
+ * @param {string} dataId - Data ID
30
+ * @returns {Promise&lt;Object>} Result with { isCircular, chain }
31
+ */
32
+ export async function wouldCreateCircularHologram(client, appname, sourceHolon, targetHolon, lensName, dataId) {
33
+ const visited = new Set();
34
+ const chain = [];
35
+
36
+ let currentHolon = sourceHolon;
37
+ let currentLens = lensName;
38
+ let currentDataId = dataId;
39
+ let currentAppname = appname;
40
+
41
+ // Follow the chain to see if we eventually reach targetHolon
42
+ while (visited.size &lt; MAX_RESOLUTION_DEPTH) {
43
+ const key = `${currentAppname}:${currentHolon}:${currentLens}:${currentDataId}`;
44
+
45
+ if (visited.has(key)) {
46
+ // Already visited this node - there's a cycle in the existing chain
47
+ return { isCircular: true, chain, reason: 'existing_cycle' };
48
+ }
49
+
50
+ visited.add(key);
51
+ chain.push({ holon: currentHolon, lens: currentLens, dataId: currentDataId });
52
+
53
+ // Check if current holon is our target - this would create a circular reference
54
+ if (currentHolon === targetHolon) {
55
+ return { isCircular: true, chain, reason: 'would_create_cycle' };
56
+ }
57
+
58
+ // Read the data at current location
59
+ const path = buildPath(currentAppname, currentHolon, currentLens, currentDataId);
60
+ const data = await read(client, path);
61
+
62
+ if (!data) {
63
+ // Data doesn't exist - no circular reference possible from this chain
64
+ return { isCircular: false, chain };
65
+ }
66
+
67
+ if (!data.hologram || !data.target) {
68
+ // Not a hologram - chain ends here, no circular reference
69
+ return { isCircular: false, chain };
70
+ }
71
+
72
+ // Follow the hologram to its target
73
+ currentAppname = data.target.appname || currentAppname;
74
+ currentHolon = data.target.holonId;
75
+ currentLens = data.target.lensName || currentLens;
76
+ currentDataId = data.target.dataId || currentDataId;
77
+ }
78
+
79
+ // Max depth reached - treat as potential circular to be safe
80
+ return { isCircular: true, chain, reason: 'max_depth_exceeded' };
81
+ }
82
+
83
+ /**
84
+ * Create a hologram (lightweight reference)
85
+ * @param {string} sourceHolon - Source holon ID
86
+ * @param {string} targetHolon - Target holon ID
87
+ * @param {string} lensName - Lens name
88
+ * @param {string} dataId - Data ID
89
+ * @param {string} appname - Application namespace
90
+ * @param {Object} options - Optional cross-holosphere settings
91
+ * @param {string} options.authorPubKey - Source author's public key (for cross-holosphere)
92
+ * @param {string} options.capability - Capability token (for cross-holosphere)
93
+ * @returns {Object} Hologram object
94
+ */
95
+ export function createHologram(sourceHolon, targetHolon, lensName, dataId, appname, options = {}) {
96
+ const { authorPubKey = null, capability = null } = options;
97
+
98
+ const soul = buildPath(appname, sourceHolon, lensName, dataId);
99
+
100
+ const hologram = {
101
+ id: dataId,
102
+ hologram: true,
103
+ soul,
104
+ target: {
105
+ appname,
106
+ holonId: sourceHolon,
107
+ lensName,
108
+ dataId,
109
+ },
110
+ _meta: {
111
+ created: Date.now(),
112
+ sourceHolon,
113
+ source: sourceHolon, // Alias for compatibility
114
+ },
115
+ };
116
+
117
+ // Cross-holosphere enhancements
118
+ if (authorPubKey) {
119
+ hologram.crossHolosphere = true;
120
+ hologram.target.authorPubKey = authorPubKey;
121
+ hologram._meta.sourcePubKey = authorPubKey;
122
+ }
123
+
124
+ if (capability) {
125
+ hologram.capability = capability;
126
+ hologram._meta.grantedAt = Date.now();
127
+ }
128
+
129
+ return hologram;
130
+ }
131
+
132
+ /**
133
+ * Resolve hologram to actual data, merging local overrides
134
+ * Supports cross-holosphere holograms with capability token verification
135
+ * @param {Object} client - Nostr client instance
136
+ * @param {Object} hologram - Hologram object
137
+ * @param {Set} visited - Visited souls (circular reference detection)
138
+ * @param {Array} chain - Chain of souls for debugging circular references
139
+ * @param {Object} options - Resolution options
140
+ * @param {string} options.appname - Application namespace (for registry lookup)
141
+ * @param {boolean} options.deleteCircular - If true, delete circular holograms when detected (default: true)
142
+ * @param {string} options.hologramPath - Path of the hologram being resolved (for deletion)
143
+ * @returns {Promise&lt;Object|null>} Resolved data with _hologram metadata, or null
144
+ */
145
+ export async function resolveHologram(client, hologram, visited = new Set(), chain = [], options = {}) {
146
+ const { deleteCircular = true, hologramPath = null } = options;
147
+
148
+ if (!hologram || !hologram.hologram) {
149
+ return hologram; // Not a hologram, return as-is
150
+ }
151
+
152
+ const { soul } = hologram;
153
+ const target = hologram.target || {};
154
+
155
+ // Circular reference detection
156
+ if (visited.has(soul)) {
157
+ const chainStr = [...chain, soul].join(' โ†’ ');
158
+ console.warn(`๐Ÿ”„ Circular reference detected - removing hologram`);
159
+ console.warn(` Soul: ${soul}`);
160
+ console.warn(` Chain: ${chainStr}`);
161
+ console.warn(` Source holon: ${target.holonId || 'unknown'}`);
162
+ console.warn(` Lens: ${target.lensName || 'unknown'}`);
163
+ console.warn(` Data ID: ${target.dataId || hologram.id || 'unknown'}`);
164
+ console.warn(` Resolution depth: ${visited.size}`);
165
+
166
+ // Delete the circular hologram
167
+ if (deleteCircular &amp;&amp; hologramPath) {
168
+ console.info(` ๐Ÿ—‘๏ธ Deleting circular hologram at: ${hologramPath}`);
169
+ await write(client, hologramPath, null);
170
+ }
171
+
172
+ return null;
173
+ }
174
+
175
+ if (visited.size >= MAX_RESOLUTION_DEPTH) {
176
+ const chainStr = [...chain, soul].join(' โ†’ ');
177
+ console.warn(`โš ๏ธ Max resolution depth (${MAX_RESOLUTION_DEPTH}) exceeded - removing hologram`);
178
+ console.warn(` Current soul: ${soul}`);
179
+ console.warn(` Chain: ${chainStr}`);
180
+ console.warn(` Source holon: ${target.holonId || 'unknown'}`);
181
+ console.warn(` Lens: ${target.lensName || 'unknown'}`);
182
+
183
+ // Delete the problematic hologram
184
+ if (deleteCircular &amp;&amp; hologramPath) {
185
+ console.info(` ๐Ÿ—‘๏ธ Deleting deep chain hologram at: ${hologramPath}`);
186
+ await write(client, hologramPath, null);
187
+ }
188
+
189
+ return null;
190
+ }
191
+
192
+ visited.add(soul);
193
+ chain.push(soul);
194
+
195
+ let sourceData;
196
+
197
+ // Handle cross-holosphere holograms
198
+ if (hologram.crossHolosphere &amp;&amp; target.authorPubKey) {
199
+ // Get capability - try embedded first, then registry fallback
200
+ let capability = hologram.capability;
201
+
202
+ if (!capability &amp;&amp; options.appname) {
203
+ // Fallback to registry lookup
204
+ const capEntry = await getCapabilityForAuthor(
205
+ client,
206
+ options.appname,
207
+ target.authorPubKey,
208
+ {
209
+ holonId: target.holonId,
210
+ lensName: target.lensName,
211
+ dataId: target.dataId,
212
+ }
213
+ );
214
+ if (capEntry) {
215
+ capability = capEntry.token;
216
+ }
217
+ }
218
+
219
+ // Verify capability before resolving
220
+ if (!capability) {
221
+ console.warn(`โŒ Cross-holosphere hologram missing capability: ${soul}`);
222
+ return null;
223
+ }
224
+
225
+ const isValid = await verifyCapability(
226
+ capability,
227
+ 'read',
228
+ {
229
+ holonId: target.holonId,
230
+ lensName: target.lensName,
231
+ dataId: target.dataId,
232
+ }
233
+ );
234
+
235
+ if (!isValid) {
236
+ console.warn(`โŒ Capability verification failed for cross-holosphere hologram: ${soul}`);
237
+ return null;
238
+ }
239
+
240
+ // Read from federated source (different author)
241
+ sourceData = await read(client, soul, {
242
+ authors: [target.authorPubKey]
243
+ });
244
+ } else {
245
+ // Same-holosphere resolution (original behavior)
246
+ sourceData = await read(client, soul);
247
+ }
248
+
249
+ if (!sourceData) {
250
+ return null;
251
+ }
252
+
253
+ // If source data is also a hologram, recursively resolve
254
+ if (sourceData.hologram) {
255
+ // Pass the soul as the hologramPath so circular holograms can be deleted
256
+ return resolveHologram(client, sourceData, visited, chain, { ...options, hologramPath: soul });
257
+ }
258
+
259
+ // Merge hologram with source data
260
+ return mergeHologramWithSource(hologram, sourceData);
261
+ }
262
+
263
+ /**
264
+ * Merge hologram local overrides with source data
265
+ * @private
266
+ * @param {Object} hologram - Hologram object
267
+ * @param {Object} sourceData - Source data
268
+ * @returns {Object} Merged data with _hologram metadata
269
+ */
270
+ function mergeHologramWithSource(hologram, sourceData) {
271
+ // Extract local overrides from the hologram (exclude hologram-specific fields)
272
+ const hologramOnlyFields = ['hologram', 'soul', 'target', '_meta', 'id', 'capability', 'crossHolosphere'];
273
+ const localOverrides = {};
274
+ const localOverrideKeys = [];
275
+
276
+ for (const key of Object.keys(hologram)) {
277
+ if (!hologramOnlyFields.includes(key)) {
278
+ localOverrides[key] = hologram[key];
279
+ localOverrideKeys.push(key);
280
+ }
281
+ }
282
+
283
+ // Merge: source data + local overrides + hologram metadata
284
+ const sourceHolon = hologram._meta?.sourceHolon || hologram._meta?.source || hologram.target?.holonId;
285
+ const resolved = {
286
+ ...sourceData, // Original data from source
287
+ ...localOverrides, // Local overrides (x, y, pinned, etc.)
288
+ _hologram: {
289
+ isHologram: true,
290
+ soul: hologram.soul,
291
+ sourceHolon: sourceHolon,
292
+ localOverrides: localOverrideKeys,
293
+ crossHolosphere: hologram.crossHolosphere || false,
294
+ sourcePubKey: hologram._meta?.sourcePubKey || null,
295
+ }
296
+ };
297
+
298
+ // Preserve original _meta and add source from hologram
299
+ if (sourceData._meta) {
300
+ resolved._meta = { ...sourceData._meta, source: sourceHolon };
301
+ } else {
302
+ resolved._meta = { source: sourceHolon };
303
+ }
304
+
305
+ return resolved;
306
+ }
307
+
308
+ /**
309
+ * Setup federation between holons
310
+ * @param {Object} client - Nostr client instance
311
+ * @param {string} appname - Application namespace
312
+ * @param {string} sourceHolon - Source holon ID
313
+ * @param {string} targetHolon - Target holon ID
314
+ * @param {string} lensName - Lens name
315
+ * @param {Object} options - Federation options
316
+ * @param {string} options.direction - 'inbound' or 'outbound'
317
+ * @param {string} options.mode - 'reference' or 'copy'
318
+ * @returns {Promise&lt;boolean>} Success indicator
319
+ */
320
+ export async function setupFederation(
321
+ client,
322
+ appname,
323
+ sourceHolon,
324
+ targetHolon,
325
+ lensName,
326
+ options = {}
327
+ ) {
328
+ const { direction = 'outbound', mode = 'reference' } = options;
329
+
330
+ const federationConfig = {
331
+ sourceHolon,
332
+ targetHolon,
333
+ lensName,
334
+ direction,
335
+ mode,
336
+ created: Date.now(),
337
+ };
338
+
339
+ // Store federation config
340
+ const configPath = buildPath(appname, sourceHolon, lensName, '_federation');
341
+ return write(client, configPath, federationConfig);
342
+ }
343
+
344
+ /**
345
+ * Propagate data to federated location
346
+ * @param {Object} client - Nostr client instance
347
+ * @param {string} appname - Application namespace
348
+ * @param {Object} data - Data to propagate
349
+ * @param {string} sourceHolon - Source holon ID
350
+ * @param {string} targetHolon - Target holon ID
351
+ * @param {string} lensName - Lens name
352
+ * @param {string} mode - 'reference' or 'copy'
353
+ * @returns {Promise&lt;boolean>} Success indicator
354
+ */
355
+ export async function propagateData(
356
+ client,
357
+ appname,
358
+ data,
359
+ sourceHolon,
360
+ targetHolon,
361
+ lensName,
362
+ mode = 'reference'
363
+ ) {
364
+ const dataId = data.id;
365
+
366
+ // Don't create hologram to the same holon - it would point to itself
367
+ if (sourceHolon === targetHolon) {
368
+ console.info(`โญ๏ธ Skipping propagation - source and target are the same holon: ${sourceHolon}`);
369
+ return true;
370
+ }
371
+
372
+ // Don't propagate holograms back to avoid circular references
373
+ // If this data is already a hologram pointing to the target, skip it
374
+ if (data.hologram === true) {
375
+ // Check if this hologram would create a circular reference
376
+ if (data.target &amp;&amp; data.target.holonId === targetHolon) {
377
+ console.info(`๐Ÿ”„ Skipping propagation - would create circular reference:`);
378
+ console.info(` Data ID: ${dataId}`);
379
+ console.info(` Source holon: ${sourceHolon}`);
380
+ console.info(` Target holon: ${targetHolon}`);
381
+ console.info(` Hologram points to: ${data.target.holonId}`);
382
+ console.info(` Lens: ${lensName}`);
383
+ console.info(` Original soul: ${data.soul || 'unknown'}`);
384
+ return true;
385
+ }
386
+
387
+ // Check if targetHolon is already in the original source's activeHolograms
388
+ // This prevents creating duplicate holograms when the target already has one
389
+ if (data.target) {
390
+ const originalSourcePath = buildPath(
391
+ data.target.appname || appname,
392
+ data.target.holonId,
393
+ data.target.lensName || lensName,
394
+ data.target.dataId || dataId
395
+ );
396
+ const originalSource = await read(client, originalSourcePath);
397
+
398
+ if (originalSource?._meta?.activeHolograms) {
399
+ const alreadyHasHologram = originalSource._meta.activeHolograms.some(
400
+ h => h.targetHolon === targetHolon
401
+ );
402
+ if (alreadyHasHologram) {
403
+ console.info(`โญ๏ธ Skipping propagation - target already in activeHolograms:`);
404
+ console.info(` Data ID: ${dataId}`);
405
+ console.info(` Original source: ${data.target.holonId}`);
406
+ console.info(` Target holon: ${targetHolon}`);
407
+ return true;
408
+ }
409
+ }
410
+ }
411
+
412
+ // Deep circular check for hologram copy - ensure the original source doesn't eventually point to target
413
+ const originalSourceHolon = data.target.holonId;
414
+ const originalDataId = data.target.dataId || dataId;
415
+ const originalLens = data.target.lensName || lensName;
416
+ const originalAppname = data.target.appname || appname;
417
+
418
+ const circularCheck = await wouldCreateCircularHologram(
419
+ client, originalAppname, originalSourceHolon, targetHolon, originalLens, originalDataId
420
+ );
421
+
422
+ if (circularCheck.isCircular) {
423
+ const chainStr = circularCheck.chain.map(c => c.holon).join(' โ†’ ');
424
+ console.warn(`๐Ÿ”„ Preventing circular hologram copy:`);
425
+ console.warn(` Data ID: ${dataId}`);
426
+ console.warn(` Original source: ${originalSourceHolon}`);
427
+ console.warn(` Would copy to: ${targetHolon}`);
428
+ console.warn(` Existing chain: ${chainStr}`);
429
+ console.warn(` Reason: ${circularCheck.reason}`);
430
+ return false;
431
+ }
432
+
433
+ // When propagating a hologram, copy it instead of creating a hologram of a hologram
434
+ // This maintains the reference to the original source
435
+ const targetPath = buildPath(appname, targetHolon, lensName, dataId);
436
+ const copiedHologram = {
437
+ ...data,
438
+ _meta: {
439
+ ...data._meta,
440
+ copiedFrom: sourceHolon,
441
+ copiedAt: Date.now()
442
+ }
443
+ };
444
+ const success = await write(client, targetPath, copiedHologram);
445
+
446
+ // Add this new location to the original source's activeHolograms
447
+ if (success &amp;&amp; data.target) {
448
+ await addActiveHologram(
449
+ client,
450
+ data.target.appname || appname,
451
+ data.target.holonId,
452
+ data.target.lensName || lensName,
453
+ data.target.dataId || dataId,
454
+ targetHolon
455
+ );
456
+ console.info(`๐Ÿ“‹ Copied hologram to ${targetHolon}:`);
457
+ console.info(` Data ID: ${dataId}`);
458
+ console.info(` Original source: ${data.target.holonId}`);
459
+ console.info(` Copied from: ${sourceHolon}`);
460
+ }
461
+
462
+ return success;
463
+ }
464
+
465
+ // For non-hologram data, check if targetHolon is already in activeHolograms
466
+ if (mode === 'reference' &amp;&amp; data._meta?.activeHolograms) {
467
+ const alreadyHasHologram = data._meta.activeHolograms.some(
468
+ h => h.targetHolon === targetHolon
469
+ );
470
+ if (alreadyHasHologram) {
471
+ console.info(`โญ๏ธ Skipping propagation - target already in activeHolograms:`);
472
+ console.info(` Data ID: ${dataId}`);
473
+ console.info(` Source holon: ${sourceHolon}`);
474
+ console.info(` Target holon: ${targetHolon}`);
475
+ return true;
476
+ }
477
+ }
478
+
479
+ if (mode === 'reference') {
480
+ // Deep circular reference check - follow the chain from source to see if it would loop back
481
+ const circularCheck = await wouldCreateCircularHologram(
482
+ client, appname, sourceHolon, targetHolon, lensName, dataId
483
+ );
484
+
485
+ if (circularCheck.isCircular) {
486
+ const chainStr = circularCheck.chain.map(c => c.holon).join(' โ†’ ');
487
+ console.warn(`๐Ÿ”„ Preventing circular hologram creation:`);
488
+ console.warn(` Data ID: ${dataId}`);
489
+ console.warn(` Would create: ${sourceHolon} โ†’ ${targetHolon}`);
490
+ console.warn(` Existing chain: ${chainStr}`);
491
+ console.warn(` Reason: ${circularCheck.reason}`);
492
+ return false;
493
+ }
494
+
495
+ // Create hologram in target
496
+ const hologram = createHologram(sourceHolon, targetHolon, lensName, dataId, appname);
497
+ const targetPath = buildPath(appname, targetHolon, lensName, dataId);
498
+ const success = await write(client, targetPath, hologram);
499
+
500
+ // Add hologram to source data's _meta.activeHolograms for tracking
501
+ if (success) {
502
+ await addActiveHologram(client, appname, sourceHolon, lensName, dataId, targetHolon);
503
+ }
504
+
505
+ return success;
506
+ } else {
507
+ // Copy data to target
508
+ const targetPath = buildPath(appname, targetHolon, lensName, dataId);
509
+ return write(client, targetPath, { ...data, _meta: { ...data._meta, source: sourceHolon } });
510
+ }
511
+ }
512
+
513
+ /**
514
+ * Update local overrides on an existing hologram
515
+ * This allows storing holon-specific data (position, pinned status, etc.) on a hologram
516
+ * @param {Object} client - Nostr client instance
517
+ * @param {string} appname - Application namespace
518
+ * @param {string} holonId - Holon where the hologram lives
519
+ * @param {string} lensName - Lens name
520
+ * @param {string} dataId - Data ID
521
+ * @param {Object} overrides - Local override fields to set (e.g., { x: 100, y: 200, pinned: true })
522
+ * @returns {Promise&lt;boolean>} Success indicator
523
+ */
524
+ export async function updateHologramOverrides(client, appname, holonId, lensName, dataId, overrides) {
525
+ const path = buildPath(appname, holonId, lensName, dataId);
526
+
527
+ // Read existing hologram
528
+ const existing = await read(client, path);
529
+
530
+ if (!existing) {
531
+ console.warn(`Hologram not found at ${path}`);
532
+ return false;
533
+ }
534
+
535
+ // Only update if it's actually a hologram
536
+ if (!existing.hologram) {
537
+ console.warn(`Data at ${path} is not a hologram, cannot update overrides`);
538
+ return false;
539
+ }
540
+
541
+ // Merge overrides into hologram (but don't allow overriding hologram-specific fields)
542
+ const protectedFields = ['hologram', 'soul', 'target', '_meta', 'id'];
543
+ const safeOverrides = {};
544
+
545
+ for (const [key, value] of Object.entries(overrides)) {
546
+ if (!protectedFields.includes(key)) {
547
+ safeOverrides[key] = value;
548
+ }
549
+ }
550
+
551
+ const updated = {
552
+ ...existing,
553
+ ...safeOverrides
554
+ };
555
+
556
+ return write(client, path, updated);
557
+ }
558
+
559
+ /**
560
+ * Check if data is a hologram (unresolved reference)
561
+ * @param {Object} data - Data to check
562
+ * @returns {boolean} True if data is an unresolved hologram
563
+ */
564
+ export function isHologram(data) {
565
+ return data &amp;&amp; data.hologram === true;
566
+ }
567
+
568
+ /**
569
+ * Check if data was resolved from a hologram
570
+ * @param {Object} data - Data to check
571
+ * @returns {boolean} True if data was resolved from a hologram
572
+ */
573
+ export function isResolvedHologram(data) {
574
+ return data &amp;&amp; data._hologram &amp;&amp; data._hologram.isHologram === true;
575
+ }
576
+
577
+ /**
578
+ * Get hologram source information from resolved data
579
+ * @param {Object} data - Resolved data
580
+ * @returns {Object|null} Source info { soul, sourceHolon, localOverrides } or null
581
+ */
582
+ export function getHologramSource(data) {
583
+ if (!isResolvedHologram(data)) {
584
+ return null;
585
+ }
586
+ return {
587
+ soul: data._hologram.soul,
588
+ sourceHolon: data._hologram.sourceHolon,
589
+ localOverrides: data._hologram.localOverrides || []
590
+ };
591
+ }
592
+
593
+ /**
594
+ * Add a hologram reference to the source data's _meta.activeHolograms
595
+ * This tracks all holograms pointing to this specific data item
596
+ * If the source is itself a hologram, follows the chain to find the real source
597
+ * @param {Object} client - Nostr client instance
598
+ * @param {string} appname - Application namespace
599
+ * @param {string} sourceHolon - Source holon ID (where original data lives)
600
+ * @param {string} lensName - Lens name
601
+ * @param {string} dataId - Data ID
602
+ * @param {string} targetHolon - Target holon ID (where hologram lives)
603
+ * @returns {Promise&lt;boolean>} Success indicator
604
+ */
605
+ export async function addActiveHologram(client, appname, sourceHolon, lensName, dataId, targetHolon) {
606
+ let currentAppname = appname;
607
+ let currentHolon = sourceHolon;
608
+ let currentLens = lensName;
609
+ let currentDataId = dataId;
610
+ let sourcePath = buildPath(currentAppname, currentHolon, currentLens, currentDataId);
611
+
612
+ // Read existing source data
613
+ let sourceData = await read(client, sourcePath);
614
+ if (!sourceData) {
615
+ console.warn(`Source data not found at ${sourcePath}`);
616
+ return false;
617
+ }
618
+
619
+ // If source is a hologram, follow the chain to find the real source
620
+ // This ensures activeHolograms is always tracked on the actual data, not on holograms
621
+ let depth = 0;
622
+ const maxDepth = 10;
623
+ while (sourceData.hologram === true &amp;&amp; sourceData.target &amp;&amp; depth &lt; maxDepth) {
624
+ depth++;
625
+ currentAppname = sourceData.target.appname || currentAppname;
626
+ currentHolon = sourceData.target.holonId;
627
+ currentLens = sourceData.target.lensName || currentLens;
628
+ currentDataId = sourceData.target.dataId || currentDataId;
629
+ sourcePath = buildPath(currentAppname, currentHolon, currentLens, currentDataId);
630
+
631
+ sourceData = await read(client, sourcePath);
632
+ if (!sourceData) {
633
+ console.warn(`Real source data not found at ${sourcePath}`);
634
+ return false;
635
+ }
636
+ }
637
+
638
+ if (depth > 0) {
639
+ console.info(`๐Ÿ“ Followed hologram chain (depth: ${depth}) to real source: ${currentHolon}/${currentLens}/${currentDataId}`);
640
+ }
641
+
642
+ // Initialize _meta and activeHolograms if needed
643
+ if (!sourceData._meta) {
644
+ sourceData._meta = {};
645
+ }
646
+ if (!Array.isArray(sourceData._meta.activeHolograms)) {
647
+ sourceData._meta.activeHolograms = [];
648
+ }
649
+
650
+ const now = Date.now();
651
+
652
+ // Check if this hologram already exists
653
+ const existingIndex = sourceData._meta.activeHolograms.findIndex(
654
+ h => h.targetHolon === targetHolon
655
+ );
656
+
657
+ if (existingIndex >= 0) {
658
+ // Update existing entry
659
+ sourceData._meta.activeHolograms[existingIndex].lastUpdated = now;
660
+ } else {
661
+ // Add new entry
662
+ sourceData._meta.activeHolograms.push({
663
+ targetHolon,
664
+ created: now,
665
+ lastUpdated: now
666
+ });
667
+ }
668
+
669
+ // Write to the real source path (not the original one if we followed a chain)
670
+ return write(client, sourcePath, sourceData);
671
+ }
672
+
673
+ /**
674
+ * Remove a hologram reference from the source data's _meta.activeHolograms
675
+ * If the source is itself a hologram, follows the chain to find the real source
676
+ * @param {Object} client - Nostr client instance
677
+ * @param {string} appname - Application namespace
678
+ * @param {string} sourceHolon - Source holon ID
679
+ * @param {string} lensName - Lens name
680
+ * @param {string} dataId - Data ID
681
+ * @param {string} targetHolon - Target holon ID
682
+ * @returns {Promise&lt;boolean>} Success indicator
683
+ */
684
+ export async function removeActiveHologram(client, appname, sourceHolon, lensName, dataId, targetHolon) {
685
+ let currentAppname = appname;
686
+ let currentHolon = sourceHolon;
687
+ let currentLens = lensName;
688
+ let currentDataId = dataId;
689
+ let sourcePath = buildPath(currentAppname, currentHolon, currentLens, currentDataId);
690
+
691
+ // Read existing source data
692
+ let sourceData = await read(client, sourcePath);
693
+ if (!sourceData) {
694
+ return false;
695
+ }
696
+
697
+ // If source is a hologram, follow the chain to find the real source
698
+ let depth = 0;
699
+ const maxDepth = 10;
700
+ while (sourceData.hologram === true &amp;&amp; sourceData.target &amp;&amp; depth &lt; maxDepth) {
701
+ depth++;
702
+ currentAppname = sourceData.target.appname || currentAppname;
703
+ currentHolon = sourceData.target.holonId;
704
+ currentLens = sourceData.target.lensName || currentLens;
705
+ currentDataId = sourceData.target.dataId || currentDataId;
706
+ sourcePath = buildPath(currentAppname, currentHolon, currentLens, currentDataId);
707
+
708
+ sourceData = await read(client, sourcePath);
709
+ if (!sourceData) {
710
+ return false;
711
+ }
712
+ }
713
+
714
+ if (!sourceData._meta || !Array.isArray(sourceData._meta.activeHolograms)) {
715
+ return false;
716
+ }
717
+
718
+ const initialLength = sourceData._meta.activeHolograms.length;
719
+ sourceData._meta.activeHolograms = sourceData._meta.activeHolograms.filter(
720
+ h => h.targetHolon !== targetHolon
721
+ );
722
+
723
+ // Only write if something changed
724
+ if (sourceData._meta.activeHolograms.length &lt; initialLength) {
725
+ return write(client, sourcePath, sourceData);
726
+ }
727
+
728
+ return false;
729
+ }
730
+
731
+ /**
732
+ * Refresh lastUpdated timestamps on all activeHolograms in source data
733
+ * Also updates the hologram objects in target holons
734
+ * Called when source data is updated
735
+ * @param {Object} client - Nostr client instance
736
+ * @param {string} appname - Application namespace
737
+ * @param {string} sourceHolon - Source holon ID
738
+ * @param {string} lensName - Lens name
739
+ * @param {string} dataId - Data ID that was updated
740
+ * @param {Object} sourceData - The source data object (already read, to avoid re-reading)
741
+ * @returns {Promise&lt;Object>} Result with refreshed count
742
+ */
743
+ export async function refreshActiveHolograms(client, appname, sourceHolon, lensName, dataId, sourceData = null) {
744
+ // Read source data if not provided
745
+ if (!sourceData) {
746
+ const sourcePath = buildPath(appname, sourceHolon, lensName, dataId);
747
+ sourceData = await read(client, sourcePath);
748
+ }
749
+
750
+ if (!sourceData || !sourceData._meta || !Array.isArray(sourceData._meta.activeHolograms)) {
751
+ return { refreshed: 0, holograms: [] };
752
+ }
753
+
754
+ const now = Date.now();
755
+ const refreshed = [];
756
+
757
+ // Update timestamps on all activeHolograms
758
+ for (const hologramEntry of sourceData._meta.activeHolograms) {
759
+ hologramEntry.lastUpdated = now;
760
+
761
+ // Also update the hologram itself in the target holon
762
+ const hologramPath = buildPath(appname, hologramEntry.targetHolon, lensName, dataId);
763
+ const hologram = await read(client, hologramPath);
764
+
765
+ if (hologram &amp;&amp; hologram.hologram === true) {
766
+ // Update hologram's _meta.lastUpdated
767
+ if (!hologram._meta) hologram._meta = {};
768
+ hologram._meta.lastUpdated = now;
769
+ await write(client, hologramPath, hologram);
770
+ refreshed.push({
771
+ targetHolon: hologramEntry.targetHolon,
772
+ dataId,
773
+ timestamp: now
774
+ });
775
+ }
776
+ }
777
+
778
+ // Source data's activeHolograms timestamps are updated in-place
779
+ // The caller should save sourceData if needed
780
+
781
+ return { refreshed: refreshed.length, holograms: refreshed, sourceData };
782
+ }
783
+
784
+ /**
785
+ * Delete a hologram and clean up the activeHolograms list on the original source
786
+ * @param {Object} client - Nostr client instance
787
+ * @param {string} appname - Application namespace
788
+ * @param {string} holonId - Holon where the hologram lives (to be deleted from)
789
+ * @param {string} lensName - Lens name
790
+ * @param {string} dataId - Data ID of the hologram
791
+ * @param {Object} options - Optional settings
792
+ * @param {boolean} options.deleteData - If true, actually delete the data (default: true)
793
+ * @returns {Promise&lt;Object>} Result with deletion info
794
+ */
795
+ export async function deleteHologram(client, appname, holonId, lensName, dataId, options = {}) {
796
+ const { deleteData = true } = options;
797
+ const path = buildPath(appname, holonId, lensName, dataId);
798
+ const result = {
799
+ success: false,
800
+ wasHologram: false,
801
+ sourceHolon: null,
802
+ activeHologramsUpdated: false,
803
+ error: null
804
+ };
805
+
806
+ try {
807
+ // Read the hologram to get source information
808
+ const hologram = await read(client, path);
809
+
810
+ if (!hologram) {
811
+ console.warn(`๐Ÿ—‘๏ธ Hologram not found at ${path}`);
812
+ result.error = 'Hologram not found';
813
+ return result;
814
+ }
815
+
816
+ // Check if it's actually a hologram
817
+ if (hologram.hologram === true &amp;&amp; hologram.target) {
818
+ result.wasHologram = true;
819
+ result.sourceHolon = hologram.target.holonId;
820
+
821
+ console.info(`๐Ÿ—‘๏ธ Deleting hologram:`);
822
+ console.info(` Path: ${path}`);
823
+ console.info(` Data ID: ${dataId}`);
824
+ console.info(` From holon: ${holonId}`);
825
+ console.info(` Source holon: ${hologram.target.holonId}`);
826
+ console.info(` Lens: ${lensName}`);
827
+
828
+ // Remove from source's activeHolograms list
829
+ const removed = await removeActiveHologram(
830
+ client,
831
+ hologram.target.appname || appname,
832
+ hologram.target.holonId,
833
+ hologram.target.lensName || lensName,
834
+ hologram.target.dataId || dataId,
835
+ holonId
836
+ );
837
+
838
+ result.activeHologramsUpdated = removed;
839
+
840
+ if (removed) {
841
+ console.info(` โœ“ Removed from activeHolograms on source`);
842
+ } else {
843
+ console.warn(` โš ๏ธ Could not update activeHolograms on source (may already be removed)`);
844
+ }
845
+ } else {
846
+ console.info(`๐Ÿ—‘๏ธ Deleting non-hologram data at ${path}`);
847
+ }
848
+
849
+ // Delete the hologram data if requested
850
+ if (deleteData) {
851
+ // Write null to delete (or use a delete function if available)
852
+ const deleted = await write(client, path, null);
853
+ result.success = deleted;
854
+
855
+ if (deleted) {
856
+ console.info(` โœ“ Hologram deleted successfully`);
857
+ } else {
858
+ console.warn(` โš ๏ธ Failed to delete hologram data`);
859
+ result.error = 'Failed to delete hologram data';
860
+ }
861
+ } else {
862
+ result.success = true;
863
+ }
864
+
865
+ return result;
866
+ } catch (error) {
867
+ console.error(`โŒ Error deleting hologram at ${path}:`, error);
868
+ result.error = error.message || 'Unknown error';
869
+ return result;
870
+ }
871
+ }
872
+
873
+ /**
874
+ * Cleanup circular holograms in a holon's lens
875
+ * This detects and removes holograms that create circular references (Aโ†’Bโ†’A)
876
+ * Useful for cleaning up existing bad data created before circular reference prevention was added
877
+ * @param {Object} client - Nostr client instance
878
+ * @param {string} appname - Application namespace
879
+ * @param {string} holonId - Holon to clean up
880
+ * @param {string} lensName - Lens name to check
881
+ * @param {Object} options - Optional settings
882
+ * @param {boolean} options.dryRun - If true, only report what would be deleted (default: false)
883
+ * @returns {Promise&lt;Object>} Result with cleanup info
884
+ */
885
+ export async function cleanupCircularHolograms(client, appname, holonId, lensName, options = {}) {
886
+ const { dryRun = false } = options;
887
+ const result = {
888
+ scanned: 0,
889
+ circularFound: 0,
890
+ deleted: 0,
891
+ errors: [],
892
+ details: []
893
+ };
894
+
895
+ console.info(`๐Ÿงน ${dryRun ? '[DRY RUN] ' : ''}Cleaning up circular holograms in ${holonId}/${lensName}...`);
896
+
897
+ try {
898
+ // Get all data in this lens
899
+ const basePath = buildPath(appname, holonId, lensName);
900
+ // We need to iterate through all items - this requires listing capability
901
+ // For now, we'll rely on the caller to provide a list of IDs to check
902
+ // or we can use a different approach
903
+
904
+ // Alternative: Read the lens index if it exists
905
+ const lensIndexPath = buildPath(appname, holonId, lensName, '_index');
906
+ const lensIndex = await read(client, lensIndexPath);
907
+
908
+ if (!lensIndex || !Array.isArray(lensIndex.items)) {
909
+ console.warn(` No index found for ${holonId}/${lensName}, cannot scan for circular references`);
910
+ console.info(` Tip: Provide specific IDs to check using cleanupCircularHologramsByIds()`);
911
+ return result;
912
+ }
913
+
914
+ for (const itemId of lensIndex.items) {
915
+ result.scanned++;
916
+ const itemPath = buildPath(appname, holonId, lensName, itemId);
917
+ const item = await read(client, itemPath);
918
+
919
+ if (!item || item.hologram !== true || !item.target) {
920
+ continue; // Not a hologram, skip
921
+ }
922
+
923
+ // This is a hologram - check if it creates a circular reference
924
+ const sourceHolon = item.target.holonId;
925
+ const sourceDataId = item.target.dataId || itemId;
926
+ const sourceLens = item.target.lensName || lensName;
927
+
928
+ // Read the source data
929
+ const sourcePath = buildPath(item.target.appname || appname, sourceHolon, sourceLens, sourceDataId);
930
+ const sourceData = await read(client, sourcePath);
931
+
932
+ if (sourceData &amp;&amp; sourceData.hologram === true &amp;&amp; sourceData.target) {
933
+ // Source is also a hologram - check if it points back
934
+ if (sourceData.target.holonId === holonId) {
935
+ result.circularFound++;
936
+ const detail = {
937
+ itemId,
938
+ path: itemPath,
939
+ pointsTo: `${sourceHolon}/${sourceLens}/${sourceDataId}`,
940
+ circularWith: `${sourceData.target.holonId}/${sourceData.target.lensName}/${sourceData.target.dataId}`
941
+ };
942
+ result.details.push(detail);
943
+
944
+ console.warn(` ๐Ÿ”„ Found circular hologram:`);
945
+ console.warn(` ${holonId}/${lensName}/${itemId} โ†’ ${sourceHolon}/${sourceLens}/${sourceDataId} โ†’ ${holonId}`);
946
+
947
+ if (!dryRun) {
948
+ // Delete this hologram
949
+ const deleteResult = await deleteHologram(client, appname, holonId, lensName, itemId);
950
+ if (deleteResult.success) {
951
+ result.deleted++;
952
+ console.info(` โœ“ Deleted circular hologram`);
953
+ } else {
954
+ result.errors.push({ itemId, error: deleteResult.error });
955
+ console.error(` โŒ Failed to delete: ${deleteResult.error}`);
956
+ }
957
+ }
958
+ }
959
+ }
960
+ }
961
+
962
+ console.info(`๐Ÿงน Cleanup complete for ${holonId}/${lensName}:`);
963
+ console.info(` Scanned: ${result.scanned}`);
964
+ console.info(` Circular found: ${result.circularFound}`);
965
+ console.info(` Deleted: ${result.deleted}`);
966
+ if (result.errors.length > 0) {
967
+ console.warn(` Errors: ${result.errors.length}`);
968
+ }
969
+
970
+ return result;
971
+ } catch (error) {
972
+ console.error(`โŒ Error during cleanup:`, error);
973
+ result.errors.push({ error: error.message });
974
+ return result;
975
+ }
976
+ }
977
+
978
+ /**
979
+ * Cleanup circular holograms for a specific list of IDs
980
+ * Use this when you don't have an index but know which IDs to check
981
+ * @param {Object} client - Nostr client instance
982
+ * @param {string} appname - Application namespace
983
+ * @param {string} holonId - Holon to clean up
984
+ * @param {string} lensName - Lens name
985
+ * @param {string[]} dataIds - Array of data IDs to check
986
+ * @param {Object} options - Optional settings
987
+ * @param {boolean} options.dryRun - If true, only report what would be deleted
988
+ * @returns {Promise&lt;Object>} Result with cleanup info
989
+ */
990
+ export async function cleanupCircularHologramsByIds(client, appname, holonId, lensName, dataIds, options = {}) {
991
+ const { dryRun = false } = options;
992
+ const result = {
993
+ scanned: 0,
994
+ circularFound: 0,
995
+ deleted: 0,
996
+ errors: [],
997
+ details: []
998
+ };
999
+
1000
+ console.info(`๐Ÿงน ${dryRun ? '[DRY RUN] ' : ''}Cleaning up circular holograms for ${dataIds.length} IDs in ${holonId}/${lensName}...`);
1001
+
1002
+ for (const itemId of dataIds) {
1003
+ result.scanned++;
1004
+ const itemPath = buildPath(appname, holonId, lensName, itemId);
1005
+ const item = await read(client, itemPath);
1006
+
1007
+ if (!item || item.hologram !== true || !item.target) {
1008
+ continue; // Not a hologram, skip
1009
+ }
1010
+
1011
+ // This is a hologram - check if it creates a circular reference
1012
+ const sourceHolon = item.target.holonId;
1013
+ const sourceDataId = item.target.dataId || itemId;
1014
+ const sourceLens = item.target.lensName || lensName;
1015
+
1016
+ // Read the source data
1017
+ const sourcePath = buildPath(item.target.appname || appname, sourceHolon, sourceLens, sourceDataId);
1018
+ const sourceData = await read(client, sourcePath);
1019
+
1020
+ if (sourceData &amp;&amp; sourceData.hologram === true &amp;&amp; sourceData.target) {
1021
+ // Source is also a hologram - check if it points back
1022
+ if (sourceData.target.holonId === holonId) {
1023
+ result.circularFound++;
1024
+ const detail = {
1025
+ itemId,
1026
+ path: itemPath,
1027
+ pointsTo: `${sourceHolon}/${sourceLens}/${sourceDataId}`,
1028
+ circularWith: `${sourceData.target.holonId}/${sourceData.target.lensName}/${sourceData.target.dataId}`
1029
+ };
1030
+ result.details.push(detail);
1031
+
1032
+ console.warn(` ๐Ÿ”„ Found circular hologram: ${itemId}`);
1033
+ console.warn(` Chain: ${holonId} โ†’ ${sourceHolon} โ†’ ${holonId}`);
1034
+
1035
+ if (!dryRun) {
1036
+ // Delete this hologram
1037
+ const deleteResult = await deleteHologram(client, appname, holonId, lensName, itemId);
1038
+ if (deleteResult.success) {
1039
+ result.deleted++;
1040
+ console.info(` โœ“ Deleted`);
1041
+ } else {
1042
+ result.errors.push({ itemId, error: deleteResult.error });
1043
+ console.error(` โŒ Failed: ${deleteResult.error}`);
1044
+ }
1045
+ }
1046
+ }
1047
+ }
1048
+ }
1049
+
1050
+ console.info(`๐Ÿงน Cleanup complete: scanned=${result.scanned}, circular=${result.circularFound}, deleted=${result.deleted}`);
1051
+ return result;
1052
+ }
1053
+ </code></pre></article></section></div></div></div><div class="search-container" id="PkfLWpAbet" style="display:none"><div class="wrapper" id="iCxFxjkHbP"><button class="icon-button search-close-button" id="VjLlGakifb" aria-label="close search"><svg><use xlink:href="#close-icon"></use></svg></button><div class="search-box-c"><svg><use xlink:href="#search-icon"></use></svg> <input type="text" id="vpcKVYIppa" class="search-input" placeholder="Search..." autofocus></div><div class="search-result-c" id="fWwVHRuDuN"><span class="search-result-c-text">Type anything to view search result</span></div></div></div><div class="mobile-menu-icon-container"><button class="icon-button" id="mobile-menu" data-isopen="false" aria-label="menu"><svg><use xlink:href="#menu-icon"></use></svg></button></div><div id="mobile-sidebar" class="mobile-sidebar-container"><div class="mobile-sidebar-wrapper"><div class="mobile-nav-links"></div><div class="mobile-sidebar-items-c"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-ai.html">ai</a></div><div class="sidebar-section-children"><a href="module-ai_aggregation.html">ai/aggregation</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown.html">ai/breakdown</a></div><div class="sidebar-section-children"><a href="module-ai_classifier.html">ai/classifier</a></div><div class="sidebar-section-children"><a href="module-ai_council.html">ai/council</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings.html">ai/embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai.html">ai/federation-ai</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai.html">ai/h3-ai</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops.html">ai/json-ops</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service.html">ai/llm-service</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query.html">ai/nl-query</a></div><div class="sidebar-section-children"><a href="module-ai_relationships.html">ai/relationships</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor.html">ai/schema-extractor</a></div><div class="sidebar-section-children"><a href="module-ai_spatial.html">ai/spatial</a></div><div class="sidebar-section-children"><a href="module-ai_tts.html">ai/tts</a></div><div class="sidebar-section-children"><a href="module-content_social-protocols.html">content/social-protocols</a></div><div class="sidebar-section-children"><a href="module-core_holosphere.html">core/holosphere</a></div><div class="sidebar-section-children"><a href="module-crypto_nostr-utils.html">crypto/nostr-utils</a></div><div class="sidebar-section-children"><a href="module-crypto_secp256k1.html">crypto/secp256k1</a></div><div class="sidebar-section-children"><a href="module-federation_hologram.html">federation/hologram</a></div><div class="sidebar-section-children"><a href="module-hierarchical_upcast.html">hierarchical/upcast</a></div><div class="sidebar-section-children"><a href="module-holosphere.html">holosphere</a></div><div class="sidebar-section-children"><a href="module-lib_ai-methods.html">lib/ai-methods</a></div><div class="sidebar-section-children"><a href="module-lib_contract-methods.html">lib/contract-methods</a></div><div class="sidebar-section-children"><a href="module-lib_errors.html">lib/errors</a></div><div class="sidebar-section-children"><a href="module-lib_federation-methods.html">lib/federation-methods</a></div><div class="sidebar-section-children"><a href="module-lib_index.html">lib/index</a></div><div class="sidebar-section-children"><a href="module-schema_validator.html">schema/validator</a></div><div class="sidebar-section-children"><a href="module-spatial_h3-operations.html">spatial/h3-operations</a></div><div class="sidebar-section-children"><a href="module-storage_backend-factory.html">storage/backend-factory</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface.html">storage/backend-interface</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend.html">storage/backends/activitypub-backend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server.html">storage/backends/activitypub/server</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend.html">storage/backends/gundb-backend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend.html">storage/backends/nostr-backend</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage.html">storage/filesystem-storage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser.html">storage/filesystem-storage-browser</a></div><div class="sidebar-section-children"><a href="module-storage_global-tables.html">storage/global-tables</a></div><div class="sidebar-section-children"><a href="module-storage_gun-async.html">storage/gun-async</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth.html">storage/gun-auth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-federation.html">storage/gun-federation</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references.html">storage/gun-references</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema.html">storage/gun-schema</a></div><div class="sidebar-section-children"><a href="module-storage_gun-wrapper.html">storage/gun-wrapper</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage.html">storage/indexeddb-storage</a></div><div class="sidebar-section-children"><a href="module-storage_key-storage.html">storage/key-storage</a></div><div class="sidebar-section-children"><a href="module-storage_key-storage-simple.html">storage/key-storage-simple</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage.html">storage/memory-storage</a></div><div class="sidebar-section-children"><a href="module-storage_migration.html">storage/migration</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-async.html">storage/nostr-async</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client.html">storage/nostr-client</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-wrapper.html">storage/nostr-wrapper</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue.html">storage/outbox-queue</a></div><div class="sidebar-section-children"><a href="module-storage_persistent-storage.html">storage/persistent-storage</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service.html">storage/sync-service</a></div><div class="sidebar-section-children"><a href="module-storage_unified-storage.html">storage/unified-storage</a></div><div class="sidebar-section-children"><a href="module-subscriptions_manager.html">subscriptions/manager</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-classes"><div>Classes</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-ai_aggregation.SmartAggregation.html">SmartAggregation</a></div><div class="sidebar-section-children"><a href="module-ai_aggregation-SmartAggregation.html">SmartAggregation</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown.TaskBreakdown.html">TaskBreakdown</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown-TaskBreakdown.html">TaskBreakdown</a></div><div class="sidebar-section-children"><a href="module-ai_classifier.Classifier.html">Classifier</a></div><div class="sidebar-section-children"><a href="module-ai_classifier-Classifier.html">Classifier</a></div><div class="sidebar-section-children"><a href="module-ai_council.Council.html">Council</a></div><div class="sidebar-section-children"><a href="module-ai_council-Council.html">Council</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings.Embeddings.html">Embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings-Embeddings.html">Embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai.FederationAdvisor.html">FederationAdvisor</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai-FederationAdvisor.html">FederationAdvisor</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai.H3AI.html">H3AI</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai-H3AI.html">H3AI</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops.JSONOps.html">JSONOps</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops-JSONOps.html">JSONOps</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service.LLMService.html">LLMService</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service-LLMService.html">LLMService</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query.NLQuery.html">NLQuery</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query-NLQuery.html">NLQuery</a></div><div class="sidebar-section-children"><a href="module-ai_relationships.RelationshipDiscovery.html">RelationshipDiscovery</a></div><div class="sidebar-section-children"><a href="module-ai_relationships-RelationshipDiscovery.html">RelationshipDiscovery</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor.SchemaExtractor.html">SchemaExtractor</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor-SchemaExtractor.html">SchemaExtractor</a></div><div class="sidebar-section-children"><a href="module-ai_spatial.SpatialAnalysis.html">SpatialAnalysis</a></div><div class="sidebar-section-children"><a href="module-ai_spatial-SpatialAnalysis.html">SpatialAnalysis</a></div><div class="sidebar-section-children"><a href="module-ai_tts.TTS.html">TTS</a></div><div class="sidebar-section-children"><a href="module-ai_tts-TTS.html">TTS</a></div><div class="sidebar-section-children"><a href="module-core_holosphere.HoloSphere.html">HoloSphere</a></div><div class="sidebar-section-children"><a href="module-core_holosphere-HoloSphere.html">HoloSphere</a></div><div class="sidebar-section-children"><a href="module-holosphere-HoloSphereBase.html">HoloSphereBase</a></div><div class="sidebar-section-children"><a href="module-holosphere-HoloSphereBase.html">HoloSphereBase</a></div><div class="sidebar-section-children"><a href="module-lib_errors.AuthorizationError.html">AuthorizationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors.ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors-AuthorizationError.html">AuthorizationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors-ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-schema_validator.ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-schema_validator-ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-storage_backend-factory.BackendFactory.html">BackendFactory</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface.StorageBackend.html">StorageBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface-StorageBackend.html">StorageBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend.ActivityPubBackend.html">ActivityPubBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend-ActivityPubBackend.html">ActivityPubBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server.ActivityPubServer.html">ActivityPubServer</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server-ActivityPubServer.html">ActivityPubServer</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend.GunDBBackend.html">GunDBBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend-GunDBBackend.html">GunDBBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend.NostrBackend.html">NostrBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend-NostrBackend.html">NostrBackend</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser.FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser-FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage.FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth.GunAuth.html">GunAuth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth-GunAuth.html">GunAuth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references.GunReferenceHandler.html">GunReferenceHandler</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references-GunReferenceHandler.html">GunReferenceHandler</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema.GunSchemaValidator.html">GunSchemaValidator</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema-GunSchemaValidator.html">GunSchemaValidator</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage.IndexedDBStorage.html">IndexedDBStorage</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage-IndexedDBStorage.html">IndexedDBStorage</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage.MemoryStorage.html">MemoryStorage</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage-MemoryStorage.html">MemoryStorage</a></div><div class="sidebar-section-children"><a href="module-storage_migration.MigrationTool.html">MigrationTool</a></div><div class="sidebar-section-children"><a href="module-storage_migration-MigrationTool.html">MigrationTool</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client.NostrClient.html">NostrClient</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client-LRUCache.html">LRUCache</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client-NostrClient.html">NostrClient</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue.OutboxQueue.html">OutboxQueue</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue-OutboxQueue.html">OutboxQueue</a></div><div class="sidebar-section-children"><a href="module-storage_persistent-storage-PersistentStorage.html">PersistentStorage</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service.SyncService.html">SyncService</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service-SyncService.html">SyncService</a></div><div class="sidebar-section-children"><a href="module-subscriptions_manager.SubscriptionRegistry.html">SubscriptionRegistry</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-global"><div>Global</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="global.html#FederationRequestPayload">FederationRequestPayload</a></div><div class="sidebar-section-children"><a href="global.html#FederationResponsePayload">FederationResponsePayload</a></div><div class="sidebar-section-children"><a href="global.html#acceptFederationRequest">acceptFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#acceptFederationRequest">acceptFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#addFederatedPartner">addFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#cleanupExpiredCapabilities">cleanupExpiredCapabilities</a></div><div class="sidebar-section-children"><a href="global.html#createFederationRequest">createFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#createFederationResponse">createFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#declineFederationRequest">declineFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#getCapabilityForAuthor">getCapabilityForAuthor</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedAuthors">getFederatedAuthors</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedAuthorsForScope">getFederatedAuthorsForScope</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedPartner">getFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#getFederationRegistry">getFederationRegistry</a></div><div class="sidebar-section-children"><a href="global.html#getPendingFederationRequests">getPendingFederationRequests</a></div><div class="sidebar-section-children"><a href="global.html#initiateFederationHandshake">initiateFederationHandshake</a></div><div class="sidebar-section-children"><a href="global.html#isFederationRequest">isFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#isFederationResponse">isFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#rejectFederationRequest">rejectFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#removeFederatedPartner">removeFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#revokeOutboundCapability">revokeOutboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#saveFederationRegistry">saveFederationRegistry</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationRequest">sendFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationRequest">sendFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationResponse">sendFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#storeInboundCapability">storeInboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#storeOutboundCapability">storeOutboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationAcceptances">subscribeFederationAcceptances</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationDeclines">subscribeFederationDeclines</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationRequests">subscribeFederationRequests</a></div><div class="sidebar-section-children"><a href="global.html#subscribeToFederationDMs">subscribeToFederationDMs</a></div><div class="sidebar-section-children"><a href="global.html#updateDiscoverySettings">updateDiscoverySettings</a></div></div></div><div class="mobile-navbar-actions"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#light-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div></div></div><script type="text/javascript" src="scripts/core.min.js"></script><script src="scripts/search.min.js" defer="defer"></script><script src="scripts/third-party/fuse.js" defer="defer"></script><script type="text/javascript">var tocbotInstance=tocbot.init({tocSelector:"#eed4d2a0bfd64539bb9df78095dec881",contentSelector:".main-content",headingSelector:"h1, h2, h3",hasInnerContainers:!0,scrollContainer:".main-content",headingsOffset:130,onClick:bringLinkToView})</script></body></html>