noteconnection 1.7.0 → 1.9.0

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 (328) hide show
  1. package/LICENSE +674 -21
  2. package/README.md +260 -1626
  3. package/dist/src/agent_workspace.contract.parity.test.js +159 -0
  4. package/dist/src/agent_workspace.frontend.test.js +10388 -0
  5. package/dist/src/agent_workspace.locale.contract.test.js +95 -0
  6. package/dist/src/agent_workspace.runtime.behavior.test.js +5072 -0
  7. package/dist/src/android.knowledgebase.picker.contract.test.js +102 -0
  8. package/dist/src/appimage.patchelf.test.js +113 -0
  9. package/dist/src/appimage.portability.test.js +156 -0
  10. package/dist/src/backend/FileLoader.js +18 -4
  11. package/dist/src/backend/FileLoader.test.js +125 -0
  12. package/dist/src/backend/GraphBuilder.identity.test.js +86 -0
  13. package/dist/src/backend/GraphBuilder.js +66 -18
  14. package/dist/src/backend/GraphBuilder.matching.test.js +127 -0
  15. package/dist/src/backend/GraphMetrics.js +0 -3
  16. package/dist/src/backend/ResourceIdentity.js +155 -0
  17. package/dist/src/backend/ResourceIdentity.test.js +113 -0
  18. package/dist/src/backend/algorithms/CycleDetection.js +0 -1
  19. package/dist/src/backend/algorithms/HybridEngine.js +0 -3
  20. package/dist/src/backend/algorithms/LayoutEngine.js +0 -1
  21. package/dist/src/backend/algorithms/StatisticalAnalyzer.js +0 -4
  22. package/dist/src/backend/algorithms/TopologicalSort.js +0 -2
  23. package/dist/src/backend/build_dag.js +0 -1
  24. package/dist/src/capacitor.bridge.serialization.contract.test.js +3 -0
  25. package/dist/src/capacitor.runtime.contract.test.js +11 -2
  26. package/dist/src/copy.assets.contract.test.js +130 -0
  27. package/dist/src/core/Graph.js +138 -42
  28. package/dist/src/core/Graph.test.js +74 -0
  29. package/dist/src/core/NoteConnection.js +2 -2
  30. package/dist/src/core/PathBridge.js +293 -5
  31. package/dist/src/core/ResourceReference.js +17 -0
  32. package/dist/src/desktop.godot.pack.test.js +142 -0
  33. package/dist/src/desktop.runtime.graph.test.js +66 -0
  34. package/dist/src/export/WorkspaceExportBundle.js +1174 -0
  35. package/dist/src/export/WorkspaceExportBundle.test.js +1541 -0
  36. package/dist/src/export/index.js +18 -0
  37. package/dist/src/export/types.js +2 -0
  38. package/dist/src/fixrisk.issue.verifier.contract.test.js +3 -1
  39. package/dist/src/foundation.ann.runtime.contract.test.js +81 -0
  40. package/dist/src/foundation.release.evidence.contract.test.js +524 -0
  41. package/dist/src/foundation.sqlite.runtime.contract.test.js +88 -0
  42. package/dist/src/frontend/README.md +260 -1626
  43. package/dist/src/frontend/agent_workspace.js +6011 -0
  44. package/dist/src/frontend/agent_workspace_runtime.js +4434 -0
  45. package/dist/src/frontend/analysis.js +31 -4
  46. package/dist/src/frontend/app.js +2178 -62
  47. package/dist/src/frontend/focus_mode_interactions.js +33 -0
  48. package/dist/src/frontend/godot_future_path_renderer.js +540 -0
  49. package/dist/src/frontend/godot_tree_interactions.js +178 -0
  50. package/dist/src/frontend/graph_state.mjs +105 -0
  51. package/dist/src/frontend/hosted_future_path_runtime.js +157 -0
  52. package/dist/src/frontend/i18n.mjs +186 -0
  53. package/dist/src/frontend/index.html +672 -268
  54. package/dist/src/frontend/knowledge_projection_contract.js +230 -0
  55. package/dist/src/frontend/knowledge_projection_store.js +214 -0
  56. package/dist/src/frontend/layout_gpu.js +12 -4
  57. package/dist/src/frontend/libs/path_core.js +158 -42
  58. package/dist/src/frontend/locales/en.json +753 -5
  59. package/dist/src/frontend/locales/zh.json +753 -5
  60. package/dist/src/frontend/main.mjs +60 -0
  61. package/dist/src/frontend/markdown_runtime.js +827 -0
  62. package/dist/src/frontend/mobile_budget_runtime.js +33 -0
  63. package/dist/src/frontend/mobile_exact_analyzer.js +393 -0
  64. package/dist/src/frontend/mobile_identity_contract.js +221 -0
  65. package/dist/src/frontend/mobile_semantic_comparator.js +264 -0
  66. package/dist/src/frontend/notemd.css +49 -0
  67. package/dist/src/frontend/notemd.html +7 -1
  68. package/dist/src/frontend/notemd.js +64 -0
  69. package/dist/src/frontend/path.html +113 -2
  70. package/dist/src/frontend/path_app.js +2108 -130
  71. package/dist/src/frontend/path_layout.mjs +143 -0
  72. package/dist/src/frontend/path_mermaid_utils.mjs +108 -0
  73. package/dist/src/frontend/path_modules_bridge.js +486 -0
  74. package/dist/src/frontend/path_state.mjs +118 -0
  75. package/dist/src/frontend/path_styles.css +146 -0
  76. package/dist/src/frontend/path_worker_bridge.mjs +85 -0
  77. package/dist/src/frontend/reader.js +393 -33
  78. package/dist/src/frontend/runtime_bridge.js +67 -54
  79. package/dist/src/frontend/runtime_bridge.mjs +279 -0
  80. package/dist/src/frontend/settings.js +130 -12
  81. package/dist/src/frontend/simulationWorker.js +1 -1
  82. package/dist/src/frontend/source_manager.js +297 -22
  83. package/dist/src/frontend/storage_provider.js +661 -71
  84. package/dist/src/frontend/styles.css +2814 -72
  85. package/dist/src/frontend/workbench_state.mjs +101 -0
  86. package/dist/src/frontend/workspace_panes.js +10272 -0
  87. package/dist/src/frontend.locale.contract.test.js +62 -0
  88. package/dist/src/frontend.runtime.assets.contract.test.js +81 -0
  89. package/dist/src/godot.sidecar.bootstrap.contract.test.js +244 -0
  90. package/dist/src/graph.answer.operator.contract.test.js +72 -0
  91. package/dist/src/index.js +6 -2
  92. package/dist/src/index.knowledge-root.test.js +118 -0
  93. package/dist/src/indexing/IndexLifecycle.js +217 -0
  94. package/dist/src/indexing/IndexLifecycle.test.js +73 -0
  95. package/dist/src/indexing/SegmentBuilder.js +64 -0
  96. package/dist/src/indexing/UnitBuilder.js +48 -0
  97. package/dist/src/indexing/types.js +2 -0
  98. package/dist/src/knowledge.api.contract.test.js +172 -0
  99. package/dist/src/knowledge_projection.contract.test.js +134 -0
  100. package/dist/src/knowledge_projection_store.test.js +200 -0
  101. package/dist/src/learning/AnswerQualityEvaluation.js +153 -0
  102. package/dist/src/learning/AnswerQualityEvaluation.test.js +118 -0
  103. package/dist/src/learning/KnowledgeLearningPlatform.js +11181 -0
  104. package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +745 -0
  105. package/dist/src/learning/KnowledgeLearningPlatform.program-f.test.js +99 -0
  106. package/dist/src/learning/KnowledgeLearningPlatform.test.js +3208 -0
  107. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +2998 -0
  108. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +3936 -0
  109. package/dist/src/learning/MeasurementEvidenceConflicts.test.js +78 -0
  110. package/dist/src/learning/PublicAnswerContract.test.js +85 -0
  111. package/dist/src/learning/PublicEvidenceSelection.test.js +94 -0
  112. package/dist/src/learning/PublicMeasurementDisclosure.test.js +54 -0
  113. package/dist/src/learning/agentConversationExecution.js +211 -0
  114. package/dist/src/learning/agentConversationExecution.test.js +209 -0
  115. package/dist/src/learning/agentConversationSerialization.js +266 -0
  116. package/dist/src/learning/agentConversationSerialization.test.js +165 -0
  117. package/dist/src/learning/agentResponseBudget.js +179 -0
  118. package/dist/src/learning/agentResponseBudget.test.js +97 -0
  119. package/dist/src/learning/agentWorkspaceCapabilityContracts.js +65 -0
  120. package/dist/src/learning/answerReleaseReview.js +5260 -0
  121. package/dist/src/learning/answerReleaseReview.test.js +4174 -0
  122. package/dist/src/learning/answerTaskPlan.js +473 -0
  123. package/dist/src/learning/api.js +2 -0
  124. package/dist/src/learning/conversationComposer.js +1721 -0
  125. package/dist/src/learning/conversationComposer.test.js +3220 -0
  126. package/dist/src/learning/domains/ConversationManager.js +53 -0
  127. package/dist/src/learning/domains/KnowledgeIngestor.js +238 -0
  128. package/dist/src/learning/domains/KnowledgeQuerier.js +187 -0
  129. package/dist/src/learning/domains/MasteryEngine.js +387 -0
  130. package/dist/src/learning/domains/MemoryPolicyManager.js +408 -0
  131. package/dist/src/learning/domains/QualityEvaluator.js +307 -0
  132. package/dist/src/learning/domains/TutorRouter.js +313 -0
  133. package/dist/src/learning/domains/index.js +33 -0
  134. package/dist/src/learning/domains/types.js +7 -0
  135. package/dist/src/learning/errors.js +29 -0
  136. package/dist/src/learning/evidenceContextAssembler.js +1368 -0
  137. package/dist/src/learning/evidenceContextAssembler.test.js +6332 -0
  138. package/dist/src/learning/graphAnswerCoverage.js +37 -0
  139. package/dist/src/learning/graphAnswerCoverage.test.js +93 -0
  140. package/dist/src/learning/graphAnswerCoverageCalibration.js +59 -0
  141. package/dist/src/learning/graphAnswerCoverageCalibration.test.js +46 -0
  142. package/dist/src/learning/graphAnswerFacts.js +94 -0
  143. package/dist/src/learning/graphAnswerFacts.test.js +39 -0
  144. package/dist/src/learning/graphAnswerPlan.js +908 -0
  145. package/dist/src/learning/graphAnswerPlan.test.js +907 -0
  146. package/dist/src/learning/graphAnswerQualityCalibration.js +255 -0
  147. package/dist/src/learning/graphAnswerQualityCalibration.test.js +72 -0
  148. package/dist/src/learning/graphAnswerQualityPolicy.js +30 -0
  149. package/dist/src/learning/graphClaimMatcher.js +104 -0
  150. package/dist/src/learning/graphConditionedContext.js +109 -0
  151. package/dist/src/learning/graphConditionedContext.test.js +99 -0
  152. package/dist/src/learning/graphContextAssembler.js +860 -0
  153. package/dist/src/learning/graphContextAssembler.test.js +1033 -0
  154. package/dist/src/learning/graphExpansionPolicy.js +22 -0
  155. package/dist/src/learning/graphExpansionPolicy.test.js +33 -0
  156. package/dist/src/learning/identityMetadata.test.js +26 -0
  157. package/dist/src/learning/index.js +29 -0
  158. package/dist/src/learning/mobileAnswerProjection.js +104 -0
  159. package/dist/src/learning/mobileAnswerProjection.test.js +102 -0
  160. package/dist/src/learning/queryBackend.js +1922 -0
  161. package/dist/src/learning/queryBackend.test.js +976 -0
  162. package/dist/src/learning/ragContextPack.js +356 -0
  163. package/dist/src/learning/ragContextPack.test.js +311 -0
  164. package/dist/src/learning/ragEvidenceQuality.js +96 -0
  165. package/dist/src/learning/ragEvidenceQuality.test.js +29 -0
  166. package/dist/src/learning/ragPublicText.js +101 -0
  167. package/dist/src/learning/ragPublicText.test.js +57 -0
  168. package/dist/src/learning/ragSufficiencyJudge.js +171 -0
  169. package/dist/src/learning/ragSufficiencyJudge.test.js +177 -0
  170. package/dist/src/learning/ragSufficiencyProviderJudge.js +217 -0
  171. package/dist/src/learning/ragSufficiencyProviderJudge.test.js +207 -0
  172. package/dist/src/learning/requestNormalization.js +304 -0
  173. package/dist/src/learning/requestNormalization.test.js +101 -0
  174. package/dist/src/learning/runtimeCapability.js +4677 -0
  175. package/dist/src/learning/runtimeCapability.test.js +3635 -0
  176. package/dist/src/learning/store.js +1344 -0
  177. package/dist/src/learning/store.test.js +1425 -0
  178. package/dist/src/learning/tutorAdapter.js +2 -0
  179. package/dist/src/learning/types.js +2 -0
  180. package/dist/src/learning/vectorAccelerationAdapter.js +958 -0
  181. package/dist/src/learning/vectorAccelerationAdapter.test.js +412 -0
  182. package/dist/src/learning/workspaceHydration.js +168 -0
  183. package/dist/src/learning/workspaceHydration.test.js +30 -0
  184. package/dist/src/lfs.asset.policy.contract.test.js +153 -0
  185. package/dist/src/license.policy.contract.test.js +71 -0
  186. package/dist/src/markdown/MarkdownGateway.js +4 -0
  187. package/dist/src/markdown/MarkdownGateway.test.js +59 -0
  188. package/dist/src/memory/MemoryGovernance.js +74 -0
  189. package/dist/src/memory/MemoryGovernance.test.js +46 -0
  190. package/dist/src/memory/types.js +2 -0
  191. package/dist/src/mermaid.frontend.guard.contract.test.js +77 -0
  192. package/dist/src/middleware/SseResponseWriter.js +122 -0
  193. package/dist/src/middleware/SseResponseWriter.test.js +54 -0
  194. package/dist/src/middleware/auth.js +38 -0
  195. package/dist/src/middleware/auth.test.js +33 -0
  196. package/dist/src/middleware/body-parser.js +45 -0
  197. package/dist/src/middleware/cors.js +44 -0
  198. package/dist/src/middleware/index.js +22 -0
  199. package/dist/src/middleware/request-trace.js +96 -0
  200. package/dist/src/mobile.android.evidence.contract.test.js +146 -0
  201. package/dist/src/mobile.android.signing.contract.test.js +66 -0
  202. package/dist/src/mobile.artifact.contract.test.js +144 -0
  203. package/dist/src/mobile.budget.contract.test.js +90 -0
  204. package/dist/src/mobile.canonical-id.readiness.test.js +54 -0
  205. package/dist/src/mobile.graph.parity.contract.test.js +207 -0
  206. package/dist/src/mobile.identity.contract.test.js +66 -0
  207. package/dist/src/mobile.identity.corpus.manifest.test.js +72 -0
  208. package/dist/src/mobile.identity.corpus.test.js +40 -0
  209. package/dist/src/mobile.native.recovery.contract.test.js +64 -0
  210. package/dist/src/mobile.pipeline.test.js +11 -1
  211. package/dist/src/mobile.profile.contract.test.js +225 -0
  212. package/dist/src/mobile.semantic.parity.test.js +92 -0
  213. package/dist/src/mobile_exact_analyzer.test.js +113 -0
  214. package/dist/src/notemd/AppConfigToml.js +6 -4
  215. package/dist/src/notemd/ContentGenerator.js +4 -9
  216. package/dist/src/notemd/FileProcessor.js +4 -9
  217. package/dist/src/notemd/MermaidProcessor.js +400 -50
  218. package/dist/src/notemd/NotemdService.js +506 -26
  219. package/dist/src/notemd/PromptManager.js +15 -0
  220. package/dist/src/notemd/Translator.js +4 -9
  221. package/dist/src/notemd/cli/commands.js +357 -0
  222. package/dist/src/notemd/cli/dispatcher.js +225 -0
  223. package/dist/src/notemd/cli/index.js +169 -0
  224. package/dist/src/notemd/cli/parser.js +68 -0
  225. package/dist/src/notemd/cli/types.js +2 -0
  226. package/dist/src/notemd/constants.js +43 -0
  227. package/dist/src/notemd/diagram/diagramGenerationService.js +78 -0
  228. package/dist/src/notemd/diagram/diagramSpec.js +79 -0
  229. package/dist/src/notemd/diagram/diagramSpecResponseParser.js +131 -0
  230. package/dist/src/notemd/diagram/intent.js +95 -0
  231. package/dist/src/notemd/diagram/planner.js +71 -0
  232. package/dist/src/notemd/diagram/prompts/diagramSpecPrompt.js +42 -0
  233. package/dist/src/notemd/diagram/types.js +18 -0
  234. package/dist/src/notemd/index.js +26 -0
  235. package/dist/src/notemd/operations/capabilityManifest.js +23 -0
  236. package/dist/src/notemd/operations/cliContracts.js +17 -0
  237. package/dist/src/notemd/operations/configProfileCommands.js +85 -0
  238. package/dist/src/notemd/operations/registry.contract.test.js +95 -0
  239. package/dist/src/notemd/operations/registry.js +991 -0
  240. package/dist/src/notemd/operations/types.js +2 -0
  241. package/dist/src/notemd/progressReporter.js +9 -0
  242. package/dist/src/notemd/providerDiagnostics.js +220 -0
  243. package/dist/src/notemd/providerProfiles.js +42 -0
  244. package/dist/src/notemd/providerTemplates.js +231 -0
  245. package/dist/src/notemd/search/DuckDuckGoProvider.js +39 -0
  246. package/dist/src/notemd/search/SearchManager.js +13 -0
  247. package/dist/src/notemd/search/SearchProvider.js +2 -0
  248. package/dist/src/notemd/search/TavilyProvider.js +44 -0
  249. package/dist/src/notemd.agent.manifest.test.js +85 -0
  250. package/dist/src/notemd.api.contract.test.js +14 -1
  251. package/dist/src/notemd.app_config_toml.test.js +2 -1
  252. package/dist/src/notemd.batch.workflow.test.js +117 -0
  253. package/dist/src/notemd.cli.e2e.test.js +136 -0
  254. package/dist/src/notemd.core.test.js +51 -0
  255. package/dist/src/notemd.diagram.pipeline.test.js +233 -0
  256. package/dist/src/notemd.providerTemplates.test.js +34 -0
  257. package/dist/src/notemd.server.integration.test.js +262 -39
  258. package/dist/src/notemd.workflow.pipeline.test.js +162 -0
  259. package/dist/src/pathbridge.handshake.contract.test.js +45 -2
  260. package/dist/src/pathbridge.host-adapter.contract.test.js +133 -0
  261. package/dist/src/pathcore.bundle.contract.test.js +8 -0
  262. package/dist/src/pathmode.background.contract.test.js +69 -0
  263. package/dist/src/pathmode.settings.api.contract.test.js +9 -0
  264. package/dist/src/pkg.sidecar.contract.test.js +9 -3
  265. package/dist/src/platform/ExportProfile.js +86 -0
  266. package/dist/src/platform/MobileBudget.js +11 -0
  267. package/dist/src/platform/PlatformCapabilities.js +59 -0
  268. package/dist/src/platform/PlatformCapabilities.test.js +36 -0
  269. package/dist/src/platform/RenderMaterializer.js +33 -0
  270. package/dist/src/platform/RenderMaterializer.test.js +32 -0
  271. package/dist/src/query_backend.external_http.integration.test.js +410 -0
  272. package/dist/src/reader_renderer.js +404 -3
  273. package/dist/src/reader_renderer.test.js +87 -0
  274. package/dist/src/release.godot.mirror.contract.test.js +97 -0
  275. package/dist/src/resources/ResourceRegistry.js +263 -0
  276. package/dist/src/resources/ResourceRegistry.test.js +97 -0
  277. package/dist/src/resources/types.js +2 -0
  278. package/dist/src/routes/agentWorkspaceDiagnostics.js +173 -0
  279. package/dist/src/routes/index.js +19 -0
  280. package/dist/src/routes/knowledge.js +981 -0
  281. package/dist/src/routes/knowledgePayload.js +185 -0
  282. package/dist/src/routes/knowledgePayload.test.js +53 -0
  283. package/dist/src/routes/markdown.js +295 -0
  284. package/dist/src/routes/notemd.js +1321 -0
  285. package/dist/src/routes/registry.contract.test.js +133 -0
  286. package/dist/src/routes/registry.shadow.contract.test.js +22 -0
  287. package/dist/src/routes/render.js +248 -0
  288. package/dist/src/routes/runtimeRunbookRouteOps.js +149 -0
  289. package/dist/src/routes/runtimeRunbookRouteOps.test.js +194 -0
  290. package/dist/src/routes/settings.js +6 -0
  291. package/dist/src/routes/staticFiles.js +94 -0
  292. package/dist/src/routes/types.js +2 -0
  293. package/dist/src/runtime.capabilities.test.js +18 -2
  294. package/dist/src/runtime.transport.adapter.contract.test.js +81 -0
  295. package/dist/src/server.js +10342 -1325
  296. package/dist/src/server.migration.test.js +584 -10
  297. package/dist/src/server.port.fallback.contract.test.js +63 -0
  298. package/dist/src/session/SessionStateStore.js +81 -0
  299. package/dist/src/session/SessionStateStore.test.js +58 -0
  300. package/dist/src/session/types.js +2 -0
  301. package/dist/src/settings.runtime.contract.test.js +50 -0
  302. package/dist/src/shared/types.contract.test.js +107 -0
  303. package/dist/src/shared/types.js +22 -0
  304. package/dist/src/sidecar.build.lock.contract.test.js +201 -0
  305. package/dist/src/sidecar.freshness.contract.test.js +184 -0
  306. package/dist/src/sidecar.replacement.boundary.contract.test.js +131 -0
  307. package/dist/src/sidecar.supply.readiness.contract.test.js +155 -0
  308. package/dist/src/simulation.worker.offline.test.js +104 -0
  309. package/dist/src/source_manager.loadflow.test.js +46 -0
  310. package/dist/src/startup.layout.snapshot.contract.test.js +57 -0
  311. package/dist/src/storage.provider.capacitor.content.contract.test.js +4 -1
  312. package/dist/src/storage.provider.contract.test.js +152 -1
  313. package/dist/src/tauri.frontend.build.contract.test.js +68 -0
  314. package/dist/src/tauri.sidecar.cleanup.contract.test.js +21 -0
  315. package/dist/src/tauri.window.evidence.execution.test.js +68 -0
  316. package/dist/src/utils/RuntimePaths.js +10 -13
  317. package/dist/src/utils/RuntimePaths.test.js +27 -0
  318. package/dist/src/utils/platform.js +153 -0
  319. package/dist/src/windows.installer.build.test.js +109 -0
  320. package/dist/src/windows.installer.payload.test.js +76 -0
  321. package/dist/src/windows.installer.runtime.test.js +69 -0
  322. package/dist/src/workflows/WorkflowArtifactStore.js +96 -0
  323. package/dist/src/workflows/WorkflowArtifactStore.test.js +80 -0
  324. package/dist/src/workflows/types.js +2 -0
  325. package/dist/src/workspace/WorkspaceRegistry.js +135 -0
  326. package/dist/src/workspace/WorkspaceRegistry.test.js +29 -0
  327. package/dist/src/workspace/types.js +2 -0
  328. package/package.json +80 -15
@@ -0,0 +1,745 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const fs = __importStar(require("fs"));
37
+ const os = __importStar(require("os"));
38
+ const path = __importStar(require("path"));
39
+ const KnowledgeLearningPlatform_1 = require("./KnowledgeLearningPlatform");
40
+ const store_1 = require("./store");
41
+ function deferredSignal() {
42
+ let resolve;
43
+ const promise = new Promise((complete) => { resolve = complete; });
44
+ return { promise, resolve };
45
+ }
46
+ describe('KnowledgeLearningPlatform persistence', () => {
47
+ let tempRoot;
48
+ let snapshotPath;
49
+ let nowIso;
50
+ beforeEach(() => {
51
+ tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), 'knowledge-platform-'));
52
+ snapshotPath = path.join(tempRoot, 'runtime_data', 'knowledge_graph_store.v1.json');
53
+ nowIso = '2026-03-31T10:00:00.000Z';
54
+ });
55
+ afterEach(() => {
56
+ fs.rmSync(tempRoot, { recursive: true, force: true });
57
+ });
58
+ test('preserves an acknowledged memory write when a concurrent ingest commit fails', async () => {
59
+ const store = (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath });
60
+ const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({ store, nowProvider: () => new Date(nowIso) });
61
+ await platform.ingestKnowledge({ documents: [{
62
+ documentId: 'committed', sourcePath: 'isolation/committed.md',
63
+ content: '# Committed\nThe committed document must survive a failed write.',
64
+ }] });
65
+ const entered = deferredSignal();
66
+ const resume = deferredSignal();
67
+ jest.spyOn(store, 'saveSnapshot').mockImplementationOnce(async () => {
68
+ entered.resolve();
69
+ await resume.promise;
70
+ throw new Error('injected commit failure');
71
+ });
72
+ const ingest = platform.ingestKnowledge({ documents: [{
73
+ documentId: 'uncommitted', sourcePath: 'isolation/uncommitted.md',
74
+ content: '# Uncommitted\nThis document belongs to the failed commit.',
75
+ }] }).catch((error) => error);
76
+ await entered.promise;
77
+ const visibleDocumentCount = platform.getKnowledgeState().documents;
78
+ const memory = platform.addConversationMemory({
79
+ userId: 'isolation-user', namespace: 'project', content: 'An acknowledged memory survives.',
80
+ });
81
+ await new Promise((resolve) => setImmediate(resolve));
82
+ resume.resolve();
83
+ expect(await ingest).toEqual(expect.objectContaining({ message: 'injected commit failure' }));
84
+ expect((await memory).added).toBe(true);
85
+ const reopened = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({
86
+ store: (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath }),
87
+ nowProvider: () => new Date(nowIso),
88
+ });
89
+ const persisted = await reopened.listConversationMemory({ userId: 'isolation-user', namespace: 'project' });
90
+ expect(visibleDocumentCount).toBe(1);
91
+ expect(persisted.entries).toEqual(expect.arrayContaining([
92
+ expect.objectContaining({ content: 'An acknowledged memory survives.' }),
93
+ ]));
94
+ expect(reopened.getKnowledgeState().documents).toBe(1);
95
+ });
96
+ test('query and export wait for a complete committed revision', async () => {
97
+ const store = (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath });
98
+ const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({ store, nowProvider: () => new Date(nowIso) });
99
+ await platform.ingestKnowledge({ documents: [{
100
+ documentId: 'first', sourcePath: 'isolated/first.md', workspaceId: 'isolated', corpusId: 'isolated',
101
+ content: '# First\nThe initial committed document.',
102
+ }] });
103
+ const entered = deferredSignal();
104
+ const resume = deferredSignal();
105
+ const save = store.saveSnapshot.bind(store);
106
+ jest.spyOn(store, 'saveSnapshot').mockImplementationOnce(async (snapshot) => {
107
+ entered.resolve();
108
+ await resume.promise;
109
+ await save(snapshot);
110
+ });
111
+ const ingest = platform.ingestKnowledge({ documents: [{
112
+ documentId: 'second', sourcePath: 'isolated/second.md', workspaceId: 'isolated', corpusId: 'isolated',
113
+ content: '# Second\nThe second committed document.',
114
+ }] });
115
+ await entered.promise;
116
+ let queryCompleted = false;
117
+ let exportCompleted = false;
118
+ const query = platform.queryKnowledge({ query: 'second', scope: { documentIds: ['second'] } })
119
+ .then((response) => { queryCompleted = true; return response; });
120
+ const exported = platform.buildWorkspaceExportBundle({ workspaceId: 'isolated', exportProfileId: 'mobile-slim' })
121
+ .then((response) => { exportCompleted = true; return response; });
122
+ await new Promise((resolve) => setImmediate(resolve));
123
+ const completedBeforeCommit = { queryCompleted, exportCompleted };
124
+ resume.resolve();
125
+ await ingest;
126
+ expect((await query).items.some((item) => item.atom.documentId === 'second')).toBe(true);
127
+ await exported;
128
+ expect(completedBeforeCommit).toEqual({ queryCompleted: false, exportCompleted: false });
129
+ });
130
+ test('nested conversation writes commit once and the queue continues after failure', async () => {
131
+ const store = (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath });
132
+ const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({ store, nowProvider: () => new Date(nowIso) });
133
+ await platform.ingestKnowledge({ documents: [{
134
+ documentId: 'nested', sourcePath: 'nested.md', content: '# Nested\nNested transactions preserve memory.',
135
+ }] });
136
+ const save = jest.spyOn(store, 'saveSnapshot');
137
+ await platform.agentConversation({
138
+ userId: 'nested-user', sessionId: 'nested-session', message: 'What is nested?', persistMemory: true,
139
+ });
140
+ expect(save).toHaveBeenCalledTimes(1);
141
+ save.mockRejectedValueOnce(new Error('snapshot unavailable'));
142
+ await expect(platform.addConversationMemory({ userId: 'nested-user', content: 'must roll back' }))
143
+ .rejects.toThrow('snapshot unavailable');
144
+ await platform.addConversationMemory({ userId: 'nested-user', content: 'queue still accepts writes' });
145
+ const memory = await platform.listConversationMemory({ userId: 'nested-user' });
146
+ expect(memory.entries.some((entry) => entry.content === 'must roll back')).toBe(false);
147
+ expect(memory.entries.some((entry) => entry.content === 'queue still accepts writes')).toBe(true);
148
+ });
149
+ test('surfaces commit and rollback failures together and retains the prior state for recovery', async () => {
150
+ const store = (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath });
151
+ const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({ store });
152
+ await platform.ingestKnowledge({ documents: [{ documentId: 'prior', sourcePath: 'prior.md', content: '# Prior\nAcknowledged state.' }] });
153
+ const save = jest.spyOn(store, 'saveSnapshot')
154
+ .mockRejectedValueOnce(new Error('commit storage unavailable'))
155
+ .mockRejectedValueOnce(new Error('rollback storage unavailable'));
156
+ await expect(platform.ingestKnowledge({ documents: [{ documentId: 'failed', sourcePath: 'failed.md', content: '# Failed\nUncommitted state.' }] }))
157
+ .rejects.toThrow('commit storage unavailable; rollback: rollback storage unavailable');
158
+ expect(platform.getKnowledgeState().documents).toBe(1);
159
+ save.mockRestore();
160
+ expect((await platform.addConversationMemory({ userId: 'recovery', content: 'Recovered after storage became available.' })).added).toBe(true);
161
+ const reopened = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({ store: (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath }) });
162
+ expect((await reopened.queryKnowledge({ query: 'Acknowledged state' })).items.some(item => item.atom.documentId === 'prior')).toBe(true);
163
+ expect(reopened.getKnowledgeState().documents).toBe(1);
164
+ });
165
+ test('restores ingested graph and learner state from local file store', async () => {
166
+ const store = (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath });
167
+ const platformA = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({
168
+ nowProvider: () => new Date(nowIso),
169
+ store,
170
+ });
171
+ const ingestResult = await platformA.ingestKnowledge({
172
+ incremental: true,
173
+ documents: [
174
+ {
175
+ documentId: 'doc_persist',
176
+ sourcePath: 'Knowledge_Base/persist.md',
177
+ language: 'en',
178
+ content: '# Persistence Layer\nKnowledge graph snapshots should survive restarts.',
179
+ },
180
+ ],
181
+ });
182
+ const atomId = ingestResult.atoms[0]?.id;
183
+ expect(atomId).toBeDefined();
184
+ await platformA.diagnoseMastery({
185
+ userId: 'user_persist',
186
+ observations: [
187
+ {
188
+ atomId,
189
+ outcome: 'incorrect',
190
+ errorTag: 'recall_gap',
191
+ },
192
+ ],
193
+ });
194
+ await platformA.applyMemoryPolicy({
195
+ userId: 'user_persist',
196
+ layer: 'session',
197
+ operation: 'write',
198
+ entries: [
199
+ {
200
+ key: 'persist-note',
201
+ value: 'Learner missed core definition.',
202
+ tags: ['misconception'],
203
+ confidence: 0.8,
204
+ references: [atomId],
205
+ createdAt: nowIso,
206
+ updatedAt: nowIso,
207
+ },
208
+ ],
209
+ });
210
+ await platformA.queryKnowledge({
211
+ query: 'persistence graph snapshots',
212
+ topK: 2,
213
+ });
214
+ const firstConversation = await platformA.agentConversation({
215
+ userId: 'user_persist',
216
+ sessionId: 'persist_session_scope',
217
+ message: 'Explain the persistence snapshot behavior.',
218
+ scope: {
219
+ sourcePathPrefixes: ['Knowledge_Base/persist'],
220
+ },
221
+ persistMemory: true,
222
+ });
223
+ expect(firstConversation.summary.appliedMemoryCount).toBeGreaterThan(0);
224
+ await platformA.recordGraphFocusRenderDiagnostics({
225
+ userId: 'user_persist',
226
+ sessionId: 'persist_session_scope',
227
+ workspaceId: 'persist',
228
+ corpusId: 'persist',
229
+ title: 'Persistence Layer',
230
+ requestedSourcePath: 'Knowledge_Base/persist-old.md',
231
+ resolvedSourcePath: 'Knowledge_Base/persist.md',
232
+ candidateSourcePaths: [
233
+ 'Knowledge_Base/persist-old.md',
234
+ 'Knowledge_Base/persist.md',
235
+ ],
236
+ attemptedSourcePaths: [
237
+ 'Knowledge_Base/persist-old.md',
238
+ 'Knowledge_Base/persist.md',
239
+ ],
240
+ fallbackSourcePathUsed: true,
241
+ matchedSpanCount: 1,
242
+ highlightTermCount: 1,
243
+ highlightedNodeCount: 1,
244
+ markdownRuntimeAvailable: true,
245
+ storageProviderAvailable: true,
246
+ readSucceeded: true,
247
+ renderSucceeded: true,
248
+ usedFallback: false,
249
+ failureReason: '',
250
+ recordedAt: nowIso,
251
+ });
252
+ await platformA.executeStudySessionAction({
253
+ userId: 'user_persist',
254
+ action: {
255
+ atomId,
256
+ kind: 'quiz',
257
+ source: 'mastery_path',
258
+ answer: 'xylophone quasar nebula',
259
+ },
260
+ persistMemory: true,
261
+ memoryLayer: 'session',
262
+ });
263
+ const sessionPlan = await platformA.buildStudySession({
264
+ userId: 'user_persist',
265
+ focusAtomIds: [atomId],
266
+ maxActions: 2,
267
+ includeDivergence: false,
268
+ includeRetrain: false,
269
+ });
270
+ await platformA.executeStudySessionPlan({
271
+ userId: 'user_persist',
272
+ executionKind: 'session',
273
+ sessionPlan,
274
+ actionLimit: 1,
275
+ persistMemory: true,
276
+ memoryLayer: 'session',
277
+ });
278
+ expect(fs.existsSync(snapshotPath)).toBe(true);
279
+ const snapshotJson = JSON.parse(fs.readFileSync(snapshotPath, 'utf8'));
280
+ expect(Array.isArray(snapshotJson.conversationSessions)).toBe(true);
281
+ expect(Array.isArray(snapshotJson.conversationTurns)).toBe(true);
282
+ expect(Array.isArray(snapshotJson.conversationInvocations)).toBe(true);
283
+ expect(Array.isArray(snapshotJson.resourceRegistry?.resources)).toBe(true);
284
+ expect(Array.isArray(snapshotJson.resourceRegistry?.projections)).toBe(true);
285
+ expect(Array.isArray(snapshotJson.workspaceRegistry?.workspaces)).toBe(true);
286
+ expect(Array.isArray(snapshotJson.workspaceRegistry?.bindings)).toBe(true);
287
+ expect(Array.isArray(snapshotJson.indexLifecycle?.units)).toBe(true);
288
+ expect(Array.isArray(snapshotJson.indexLifecycle?.segments)).toBe(true);
289
+ expect(Array.isArray(snapshotJson.sessionStateSnapshot?.sessionStates)).toBe(true);
290
+ expect(Array.isArray(snapshotJson.workflowArtifacts?.artifacts)).toBe(true);
291
+ expect(Array.isArray(snapshotJson.memoryAuditRecords)).toBe(true);
292
+ expect(snapshotJson.conversationSessions.length).toBeGreaterThan(0);
293
+ expect(snapshotJson.conversationTurns.length).toBeGreaterThan(0);
294
+ expect(snapshotJson.conversationInvocations.length).toBeGreaterThan(0);
295
+ expect(snapshotJson.workflowArtifacts.artifacts.some((artifact) => artifact.kind === 'knowledge_run')).toBe(true);
296
+ expect(snapshotJson.workflowArtifacts.artifacts.some((artifact) => artifact.kind === 'flashcard_batch')).toBe(true);
297
+ expect(snapshotJson.conversationTurns[0]?.response?.trace?.graphContext).toBeDefined();
298
+ expect(snapshotJson.sessionStateSnapshot.sessionStates[0]?.panelState?.graphFocusReports).toEqual(expect.arrayContaining([
299
+ expect.objectContaining({
300
+ title: 'Persistence Layer',
301
+ requestedSourcePath: 'Knowledge_Base/persist-old.md',
302
+ resolvedSourcePath: 'Knowledge_Base/persist.md',
303
+ fallbackSourcePathUsed: true,
304
+ }),
305
+ ]));
306
+ nowIso = '2026-03-31T11:00:00.000Z';
307
+ const platformB = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({
308
+ nowProvider: () => new Date(nowIso),
309
+ store: (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath }),
310
+ });
311
+ await platformB.ensureReady();
312
+ const state = platformB.getKnowledgeState();
313
+ expect(state.documents).toBe(1);
314
+ expect(state.activeAtoms).toBeGreaterThan(0);
315
+ expect(state.masteryStates).toBeGreaterThan(0);
316
+ expect(state.memoryEntries.session).toBeGreaterThan(0);
317
+ expect(state.ingestTelemetry.ingestCount).toBeGreaterThan(0);
318
+ expect(state.retrievalTelemetry.queryCount).toBeGreaterThan(0);
319
+ expect(state.sessionActionTelemetry.executionCount).toBeGreaterThan(0);
320
+ expect(state.sessionActionTelemetry.analyzedAnswerCount).toBeGreaterThan(0);
321
+ expect(state.sessionExecutionHistoryRecords).toBeGreaterThan(0);
322
+ const queryResult = await platformB.queryKnowledge({
323
+ query: 'persistence snapshots restarts',
324
+ topK: 2,
325
+ });
326
+ expect(queryResult.items.length).toBeGreaterThan(0);
327
+ const restoredConversation = await platformB.agentConversation({
328
+ userId: 'user_persist',
329
+ sessionId: 'persist_session_scope',
330
+ message: 'Explain the persistence snapshot behavior again.',
331
+ scope: {
332
+ sourcePathPrefixes: ['Knowledge_Base/persist'],
333
+ },
334
+ persistMemory: false,
335
+ });
336
+ expect(restoredConversation.trace.recalledMemoryCount).toBeGreaterThan(0);
337
+ expect(restoredConversation.trace.workspaceReadiness).toEqual(expect.objectContaining({
338
+ status: 'ready',
339
+ }));
340
+ expect(restoredConversation.trace.usedScope.readiness).toEqual(expect.objectContaining({
341
+ status: 'ready',
342
+ }));
343
+ expect(restoredConversation.trace.graphContext).toEqual(expect.objectContaining({
344
+ anchorAtomId: atomId,
345
+ }));
346
+ const restoredBundle = await platformB.buildWorkspaceExportBundle({
347
+ workspaceId: 'persist',
348
+ userId: 'user_persist',
349
+ exportProfileId: 'mobile-slim',
350
+ });
351
+ expect(restoredBundle.readiness.ready).toBe(true);
352
+ expect(restoredBundle.resources.length).toBeGreaterThan(0);
353
+ expect(restoredBundle.index.units.length).toBeGreaterThan(0);
354
+ expect(restoredBundle.runtime.workflowArtifacts.length).toBeGreaterThan(0);
355
+ expect(restoredBundle.runtime.workflowArtifacts.some((artifact) => artifact.kind === 'knowledge_run')).toBe(true);
356
+ expect(restoredBundle.runtime.workflowArtifacts.some((artifact) => artifact.kind === 'flashcard_batch')).toBe(true);
357
+ expect(restoredBundle.memory.auditRecords.length).toBeGreaterThan(0);
358
+ expect(restoredBundle.runtime.conversationTurns.some((turn) => Boolean(turn.response.trace.graphContext))).toBe(true);
359
+ expect(restoredBundle.runtime.graphFocusReports).toEqual(expect.arrayContaining([
360
+ expect.objectContaining({
361
+ sessionId: 'persist_session_scope',
362
+ title: 'Persistence Layer',
363
+ requestedSourcePath: 'Knowledge_Base/persist-old.md',
364
+ resolvedSourcePath: 'Knowledge_Base/persist.md',
365
+ signal: expect.objectContaining({
366
+ fallbackSourcePathUsed: true,
367
+ usedFallback: false,
368
+ }),
369
+ }),
370
+ ]));
371
+ const storeDiagnostics = await platformB.getStoreDiagnostics();
372
+ expect(storeDiagnostics.storeType).toBe('file');
373
+ expect(storeDiagnostics.exists).toBe(true);
374
+ expect(storeDiagnostics.loaded).toBe(true);
375
+ const history = await platformB.queryStudySessionHistory({
376
+ userId: 'user_persist',
377
+ limit: 5,
378
+ executionKinds: ['session'],
379
+ });
380
+ expect(history.records.length).toBeGreaterThan(0);
381
+ expect(history.records[0]?.executionKind).toBe('session');
382
+ expect(history.records[0]?.focusAtomIds.length).toBeGreaterThan(0);
383
+ expect(history.page.totalFilteredRecords).toBeGreaterThan(0);
384
+ expect(history.summary.executionKindBreakdown.find((item) => item.executionKind === 'session')?.recordCount).toBeGreaterThan(0);
385
+ const guardrail = await platformB.evaluateIngestGuardrails({});
386
+ expect(guardrail.latestSummary).not.toBeNull();
387
+ expect(guardrail.latestSummary?.ingestedDocuments).toBe(1);
388
+ const restored = await platformB.reloadFromStore();
389
+ expect(restored).toBe(true);
390
+ });
391
+ test('persists full source document content while tolerating older snapshots without it', async () => {
392
+ const documentContent = [
393
+ '# Water Glass',
394
+ '',
395
+ 'A water glass is a transparent drinking vessel that contains water.',
396
+ '',
397
+ 'A remote source paragraph remains available for document augmentation after restart.',
398
+ ].join('\n');
399
+ const store = (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath });
400
+ const platformA = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({
401
+ nowProvider: () => new Date(nowIso),
402
+ store,
403
+ });
404
+ await platformA.ingestKnowledge({
405
+ incremental: true,
406
+ documents: [
407
+ {
408
+ documentId: 'doc_source_content',
409
+ sourcePath: 'Knowledge_Base/source-content.md',
410
+ language: 'en',
411
+ content: documentContent,
412
+ },
413
+ ],
414
+ });
415
+ const persistedSnapshot = JSON.parse(fs.readFileSync(snapshotPath, 'utf8'));
416
+ expect(persistedSnapshot.documents).toEqual(expect.arrayContaining([
417
+ expect.objectContaining({
418
+ documentId: 'doc_source_content',
419
+ content: documentContent,
420
+ }),
421
+ ]));
422
+ persistedSnapshot.documents = persistedSnapshot.documents.map((documentSnapshot) => {
423
+ const { content: _content, ...legacyDocumentSnapshot } = documentSnapshot;
424
+ return legacyDocumentSnapshot;
425
+ });
426
+ fs.writeFileSync(snapshotPath, JSON.stringify(persistedSnapshot, null, 2), 'utf8');
427
+ const platformB = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({
428
+ nowProvider: () => new Date(nowIso),
429
+ store: (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath }),
430
+ });
431
+ await platformB.ensureReady();
432
+ const restoredQuery = await platformB.queryKnowledge({
433
+ query: 'transparent drinking vessel water',
434
+ topK: 1,
435
+ });
436
+ expect(restoredQuery.items.length).toBeGreaterThan(0);
437
+ expect(platformB.getKnowledgeState().documents).toBe(1);
438
+ });
439
+ test('replays an explicit move journal without changing the legacy document id', async () => {
440
+ const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({
441
+ nowProvider: () => new Date(nowIso),
442
+ store: (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath }),
443
+ });
444
+ await platform.ingestKnowledge({
445
+ documents: [{
446
+ documentId: 'doc_move',
447
+ sourcePath: 'Knowledge_Base/old-name.md',
448
+ sourceUri: 'note://workspace/v1/old-name.md',
449
+ language: 'en',
450
+ content: '# Move target\nThe document keeps its legacy id during a rename.',
451
+ }],
452
+ });
453
+ await platform.ingestKnowledge({
454
+ operations: [{
455
+ op: 'move',
456
+ document: {
457
+ documentId: 'doc_move',
458
+ toSourcePath: 'Knowledge_Base/new-name.md',
459
+ toSourceUri: 'note://workspace/v1/new-name.md',
460
+ toIdentityAliases: ['new-name'],
461
+ },
462
+ }],
463
+ });
464
+ const persisted = JSON.parse(fs.readFileSync(snapshotPath, 'utf8'));
465
+ expect(persisted.documents).toEqual(expect.arrayContaining([
466
+ expect.objectContaining({
467
+ documentId: 'doc_move',
468
+ sourcePath: 'Knowledge_Base/new-name.md',
469
+ sourceUri: 'note://workspace/v1/new-name.md',
470
+ identityAliases: expect.arrayContaining(['Knowledge_Base/old-name.md']),
471
+ }),
472
+ ]));
473
+ expect(persisted.identityJournal).toEqual(expect.arrayContaining([
474
+ expect.objectContaining({
475
+ documentId: 'doc_move',
476
+ fromSourcePath: 'Knowledge_Base/old-name.md',
477
+ toSourcePath: 'Knowledge_Base/new-name.md',
478
+ reason: 'move',
479
+ }),
480
+ ]));
481
+ const restored = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({
482
+ nowProvider: () => new Date(nowIso),
483
+ store: (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath }),
484
+ });
485
+ await restored.ensureReady();
486
+ const deleteResult = await restored.ingestKnowledge({
487
+ deletedDocuments: [{ sourcePath: 'Knowledge_Base/old-name.md' }],
488
+ });
489
+ expect(deleteResult.summary.deletedDocuments).toBe(1);
490
+ expect(restored.getKnowledgeState().documents).toBe(0);
491
+ });
492
+ test('keeps optional identity fields during a path-only move and resolves case-folded aliases', async () => {
493
+ const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({
494
+ nowProvider: () => new Date(nowIso),
495
+ store: (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath }),
496
+ });
497
+ await platform.ingestKnowledge({
498
+ documents: [{
499
+ documentId: 'doc_optional_move',
500
+ sourcePath: 'Knowledge_Base/Old-Name.md',
501
+ sourceUri: 'note://workspace/v1/old-name.md',
502
+ revision: 'sha256:stable',
503
+ language: 'en',
504
+ content: '# Optional identity fields\nA path-only move must not erase the URI.',
505
+ }],
506
+ });
507
+ await platform.ingestKnowledge({
508
+ operations: [{
509
+ op: 'move',
510
+ document: {
511
+ fromSourcePath: 'knowledge_base/old-name.md',
512
+ toSourcePath: 'Knowledge_Base/New-Name.md',
513
+ },
514
+ }],
515
+ });
516
+ const persisted = JSON.parse(fs.readFileSync(snapshotPath, 'utf8'));
517
+ expect(persisted.documents).toEqual(expect.arrayContaining([
518
+ expect.objectContaining({
519
+ documentId: 'doc_optional_move',
520
+ sourceUri: 'note://workspace/v1/old-name.md',
521
+ revision: 'sha256:stable',
522
+ sourcePath: 'Knowledge_Base/New-Name.md',
523
+ }),
524
+ ]));
525
+ const deleteResult = await platform.ingestKnowledge({
526
+ deletedDocuments: [{ sourceUri: 'NOTE://WORKSPACE/V1/OLD-NAME.MD' }],
527
+ });
528
+ expect(deleteResult.summary.deletedDocuments).toBe(1);
529
+ });
530
+ test('rejects a move alias collision before changing dependent owners', async () => {
531
+ const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({
532
+ nowProvider: () => new Date(nowIso),
533
+ store: (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath }),
534
+ });
535
+ await platform.ingestKnowledge({
536
+ documents: [
537
+ {
538
+ documentId: 'doc_move_source',
539
+ sourcePath: 'Knowledge_Base/source.md',
540
+ sourceUri: 'note://workspace/v1/source.md',
541
+ language: 'en',
542
+ content: '# Source\nThe source document remains addressable after a rejected move.',
543
+ },
544
+ {
545
+ documentId: 'doc_move_target',
546
+ sourcePath: 'Knowledge_Base/target.md',
547
+ sourceUri: 'note://workspace/v1/target.md',
548
+ language: 'en',
549
+ content: '# Target\nThe target alias is already owned.',
550
+ },
551
+ ],
552
+ });
553
+ await expect(platform.ingestKnowledge({
554
+ operations: [{
555
+ op: 'move',
556
+ document: {
557
+ documentId: 'doc_move_source',
558
+ toSourcePath: 'Knowledge_Base/moved.md',
559
+ toSourceUri: 'note://workspace/v1/target.md',
560
+ toIdentityAliases: ['target'],
561
+ },
562
+ }],
563
+ })).rejects.toThrow(/identity transition alias collision/i);
564
+ const persisted = JSON.parse(fs.readFileSync(snapshotPath, 'utf8'));
565
+ expect(persisted.documents).toEqual(expect.arrayContaining([
566
+ expect.objectContaining({
567
+ documentId: 'doc_move_source',
568
+ sourcePath: 'Knowledge_Base/source.md',
569
+ sourceUri: 'note://workspace/v1/source.md',
570
+ }),
571
+ ]));
572
+ expect(persisted.resourceRegistry.projections).toEqual(expect.arrayContaining([
573
+ expect.objectContaining({
574
+ documentId: 'doc_move_source',
575
+ sourcePath: 'Knowledge_Base/source.md',
576
+ }),
577
+ ]));
578
+ expect(persisted.indexLifecycle.units).toEqual(expect.arrayContaining([
579
+ expect.objectContaining({
580
+ documentId: 'doc_move_source',
581
+ sourcePath: 'Knowledge_Base/source.md',
582
+ }),
583
+ ]));
584
+ });
585
+ test('rolls back an entire mixed operation batch after a later move fails', async () => {
586
+ const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({
587
+ nowProvider: () => new Date(nowIso),
588
+ store: (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath }),
589
+ });
590
+ await platform.ingestKnowledge({
591
+ documents: [
592
+ {
593
+ documentId: 'doc_batch_first',
594
+ sourcePath: 'Knowledge_Base/batch-first.md',
595
+ language: 'en',
596
+ content: '# Batch first\nThe first operation must be rolled back with the batch.',
597
+ },
598
+ {
599
+ documentId: 'doc_batch_second',
600
+ sourcePath: 'Knowledge_Base/batch-second.md',
601
+ language: 'en',
602
+ content: '# Batch second\nThe second operation introduces a collision.',
603
+ },
604
+ ],
605
+ });
606
+ const persistedBeforeFailure = fs.readFileSync(snapshotPath, 'utf8');
607
+ await expect(platform.ingestKnowledge({
608
+ operations: [
609
+ {
610
+ op: 'move',
611
+ document: {
612
+ documentId: 'doc_batch_first',
613
+ toSourcePath: 'Knowledge_Base/batch-moved.md',
614
+ },
615
+ },
616
+ {
617
+ op: 'move',
618
+ document: {
619
+ documentId: 'doc_batch_second',
620
+ toSourcePath: 'Knowledge_Base/batch-moved.md',
621
+ },
622
+ },
623
+ ],
624
+ })).rejects.toThrow(/identity transition alias collision/i);
625
+ expect(fs.readFileSync(snapshotPath, 'utf8')).toBe(persistedBeforeFailure);
626
+ await platform.ingestKnowledge({
627
+ operations: [{
628
+ op: 'move',
629
+ document: {
630
+ fromSourcePath: 'Knowledge_Base/batch-first.md',
631
+ toSourcePath: 'Knowledge_Base/batch-recovered.md',
632
+ },
633
+ }],
634
+ });
635
+ const recovered = JSON.parse(fs.readFileSync(snapshotPath, 'utf8'));
636
+ expect(recovered.documents).toEqual(expect.arrayContaining([
637
+ expect.objectContaining({
638
+ documentId: 'doc_batch_first',
639
+ sourcePath: 'Knowledge_Base/batch-recovered.md',
640
+ }),
641
+ expect.objectContaining({
642
+ documentId: 'doc_batch_second',
643
+ sourcePath: 'Knowledge_Base/batch-second.md',
644
+ }),
645
+ ]));
646
+ });
647
+ test('rejects upsert alias collisions before creating a duplicate identity', async () => {
648
+ const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({
649
+ nowProvider: () => new Date(nowIso),
650
+ store: (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath }),
651
+ });
652
+ await platform.ingestKnowledge({
653
+ documents: [{
654
+ documentId: 'doc_existing_alias',
655
+ sourcePath: 'Knowledge_Base/existing-alias.md',
656
+ sourceUri: 'note://workspace/v1/existing-alias.md',
657
+ language: 'en',
658
+ content: '# Existing alias\nOnly one document may own this path.',
659
+ }],
660
+ });
661
+ const persistedBeforeFailure = fs.readFileSync(snapshotPath, 'utf8');
662
+ await expect(platform.ingestKnowledge({
663
+ documents: [{
664
+ documentId: 'doc_duplicate_alias',
665
+ sourcePath: 'Knowledge_Base/existing-alias.md',
666
+ language: 'en',
667
+ content: '# Duplicate alias\nThis identity must be rejected.',
668
+ }],
669
+ })).rejects.toThrow(/identity transition alias collision/i);
670
+ expect(fs.readFileSync(snapshotPath, 'utf8')).toBe(persistedBeforeFailure);
671
+ });
672
+ test('rejects an explicit move whose source alias belongs to another document', async () => {
673
+ const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({
674
+ nowProvider: () => new Date(nowIso),
675
+ store: (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath }),
676
+ });
677
+ await platform.ingestKnowledge({
678
+ documents: [
679
+ {
680
+ documentId: 'doc_explicit_source',
681
+ sourcePath: 'Knowledge_Base/explicit-source.md',
682
+ language: 'en',
683
+ content: '# Explicit source\nThe source alias must match the ID.',
684
+ },
685
+ {
686
+ documentId: 'doc_other_source',
687
+ sourcePath: 'Knowledge_Base/other-source.md',
688
+ language: 'en',
689
+ content: '# Other source\nThis alias belongs elsewhere.',
690
+ },
691
+ ],
692
+ });
693
+ const persistedBeforeFailure = fs.readFileSync(snapshotPath, 'utf8');
694
+ await expect(platform.ingestKnowledge({
695
+ operations: [{
696
+ op: 'move',
697
+ document: {
698
+ documentId: 'doc_explicit_source',
699
+ fromSourcePath: 'Knowledge_Base/other-source.md',
700
+ toSourcePath: 'Knowledge_Base/invalid-source.md',
701
+ },
702
+ }],
703
+ })).rejects.toThrow(/source aliases do not belong/i);
704
+ expect(fs.readFileSync(snapshotPath, 'utf8')).toBe(persistedBeforeFailure);
705
+ });
706
+ test('replays a successful move across resource, workspace, and index owners', async () => {
707
+ const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({
708
+ nowProvider: () => new Date(nowIso),
709
+ store: (0, store_1.createFileBackedKnowledgeGraphStore)({ filePath: snapshotPath }),
710
+ });
711
+ await platform.ingestKnowledge({
712
+ documents: [{
713
+ documentId: 'doc_owner_sync',
714
+ sourcePath: 'Knowledge_Base/old-owner.md',
715
+ sourceUri: 'note://workspace/v1/old-owner.md',
716
+ language: 'en',
717
+ content: '# Owner sync\nAll identity owners must move together.',
718
+ }],
719
+ });
720
+ await platform.ingestKnowledge({
721
+ operations: [{
722
+ op: 'move',
723
+ document: {
724
+ documentId: 'doc_owner_sync',
725
+ toSourcePath: 'Knowledge_Base/new-owner.md',
726
+ toSourceUri: 'note://workspace/v1/new-owner.md',
727
+ toIdentityAliases: ['new-owner'],
728
+ },
729
+ }],
730
+ });
731
+ const persisted = JSON.parse(fs.readFileSync(snapshotPath, 'utf8'));
732
+ expect(persisted.documents).toEqual(expect.arrayContaining([
733
+ expect.objectContaining({ documentId: 'doc_owner_sync', sourcePath: 'Knowledge_Base/new-owner.md' }),
734
+ ]));
735
+ expect(persisted.resourceRegistry.projections).toEqual(expect.arrayContaining([
736
+ expect.objectContaining({ documentId: 'doc_owner_sync', sourcePath: 'Knowledge_Base/new-owner.md' }),
737
+ ]));
738
+ expect(persisted.workspaceRegistry.bindings).toEqual(expect.arrayContaining([
739
+ expect.objectContaining({ documentId: 'doc_owner_sync', sourcePath: 'Knowledge_Base/new-owner.md' }),
740
+ ]));
741
+ expect(persisted.indexLifecycle.units).toEqual(expect.arrayContaining([
742
+ expect.objectContaining({ documentId: 'doc_owner_sync', sourcePath: 'Knowledge_Base/new-owner.md' }),
743
+ ]));
744
+ });
745
+ });