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.
- package/LICENSE +674 -21
- package/README.md +260 -1626
- package/dist/src/agent_workspace.contract.parity.test.js +159 -0
- package/dist/src/agent_workspace.frontend.test.js +10388 -0
- package/dist/src/agent_workspace.locale.contract.test.js +95 -0
- package/dist/src/agent_workspace.runtime.behavior.test.js +5072 -0
- package/dist/src/android.knowledgebase.picker.contract.test.js +102 -0
- package/dist/src/appimage.patchelf.test.js +113 -0
- package/dist/src/appimage.portability.test.js +156 -0
- package/dist/src/backend/FileLoader.js +18 -4
- package/dist/src/backend/FileLoader.test.js +125 -0
- package/dist/src/backend/GraphBuilder.identity.test.js +86 -0
- package/dist/src/backend/GraphBuilder.js +66 -18
- package/dist/src/backend/GraphBuilder.matching.test.js +127 -0
- package/dist/src/backend/GraphMetrics.js +0 -3
- package/dist/src/backend/ResourceIdentity.js +155 -0
- package/dist/src/backend/ResourceIdentity.test.js +113 -0
- package/dist/src/backend/algorithms/CycleDetection.js +0 -1
- package/dist/src/backend/algorithms/HybridEngine.js +0 -3
- package/dist/src/backend/algorithms/LayoutEngine.js +0 -1
- package/dist/src/backend/algorithms/StatisticalAnalyzer.js +0 -4
- package/dist/src/backend/algorithms/TopologicalSort.js +0 -2
- package/dist/src/backend/build_dag.js +0 -1
- package/dist/src/capacitor.bridge.serialization.contract.test.js +3 -0
- package/dist/src/capacitor.runtime.contract.test.js +11 -2
- package/dist/src/copy.assets.contract.test.js +130 -0
- package/dist/src/core/Graph.js +138 -42
- package/dist/src/core/Graph.test.js +74 -0
- package/dist/src/core/NoteConnection.js +2 -2
- package/dist/src/core/PathBridge.js +293 -5
- package/dist/src/core/ResourceReference.js +17 -0
- package/dist/src/desktop.godot.pack.test.js +142 -0
- package/dist/src/desktop.runtime.graph.test.js +66 -0
- package/dist/src/export/WorkspaceExportBundle.js +1174 -0
- package/dist/src/export/WorkspaceExportBundle.test.js +1541 -0
- package/dist/src/export/index.js +18 -0
- package/dist/src/export/types.js +2 -0
- package/dist/src/fixrisk.issue.verifier.contract.test.js +3 -1
- package/dist/src/foundation.ann.runtime.contract.test.js +81 -0
- package/dist/src/foundation.release.evidence.contract.test.js +524 -0
- package/dist/src/foundation.sqlite.runtime.contract.test.js +88 -0
- package/dist/src/frontend/README.md +260 -1626
- package/dist/src/frontend/agent_workspace.js +6011 -0
- package/dist/src/frontend/agent_workspace_runtime.js +4434 -0
- package/dist/src/frontend/analysis.js +31 -4
- package/dist/src/frontend/app.js +2178 -62
- package/dist/src/frontend/focus_mode_interactions.js +33 -0
- package/dist/src/frontend/godot_future_path_renderer.js +540 -0
- package/dist/src/frontend/godot_tree_interactions.js +178 -0
- package/dist/src/frontend/graph_state.mjs +105 -0
- package/dist/src/frontend/hosted_future_path_runtime.js +157 -0
- package/dist/src/frontend/i18n.mjs +186 -0
- package/dist/src/frontend/index.html +672 -268
- package/dist/src/frontend/knowledge_projection_contract.js +230 -0
- package/dist/src/frontend/knowledge_projection_store.js +214 -0
- package/dist/src/frontend/layout_gpu.js +12 -4
- package/dist/src/frontend/libs/path_core.js +158 -42
- package/dist/src/frontend/locales/en.json +753 -5
- package/dist/src/frontend/locales/zh.json +753 -5
- package/dist/src/frontend/main.mjs +60 -0
- package/dist/src/frontend/markdown_runtime.js +827 -0
- package/dist/src/frontend/mobile_budget_runtime.js +33 -0
- package/dist/src/frontend/mobile_exact_analyzer.js +393 -0
- package/dist/src/frontend/mobile_identity_contract.js +221 -0
- package/dist/src/frontend/mobile_semantic_comparator.js +264 -0
- package/dist/src/frontend/notemd.css +49 -0
- package/dist/src/frontend/notemd.html +7 -1
- package/dist/src/frontend/notemd.js +64 -0
- package/dist/src/frontend/path.html +113 -2
- package/dist/src/frontend/path_app.js +2108 -130
- package/dist/src/frontend/path_layout.mjs +143 -0
- package/dist/src/frontend/path_mermaid_utils.mjs +108 -0
- package/dist/src/frontend/path_modules_bridge.js +486 -0
- package/dist/src/frontend/path_state.mjs +118 -0
- package/dist/src/frontend/path_styles.css +146 -0
- package/dist/src/frontend/path_worker_bridge.mjs +85 -0
- package/dist/src/frontend/reader.js +393 -33
- package/dist/src/frontend/runtime_bridge.js +67 -54
- package/dist/src/frontend/runtime_bridge.mjs +279 -0
- package/dist/src/frontend/settings.js +130 -12
- package/dist/src/frontend/simulationWorker.js +1 -1
- package/dist/src/frontend/source_manager.js +297 -22
- package/dist/src/frontend/storage_provider.js +661 -71
- package/dist/src/frontend/styles.css +2814 -72
- package/dist/src/frontend/workbench_state.mjs +101 -0
- package/dist/src/frontend/workspace_panes.js +10272 -0
- package/dist/src/frontend.locale.contract.test.js +62 -0
- package/dist/src/frontend.runtime.assets.contract.test.js +81 -0
- package/dist/src/godot.sidecar.bootstrap.contract.test.js +244 -0
- package/dist/src/graph.answer.operator.contract.test.js +72 -0
- package/dist/src/index.js +6 -2
- package/dist/src/index.knowledge-root.test.js +118 -0
- package/dist/src/indexing/IndexLifecycle.js +217 -0
- package/dist/src/indexing/IndexLifecycle.test.js +73 -0
- package/dist/src/indexing/SegmentBuilder.js +64 -0
- package/dist/src/indexing/UnitBuilder.js +48 -0
- package/dist/src/indexing/types.js +2 -0
- package/dist/src/knowledge.api.contract.test.js +172 -0
- package/dist/src/knowledge_projection.contract.test.js +134 -0
- package/dist/src/knowledge_projection_store.test.js +200 -0
- package/dist/src/learning/AnswerQualityEvaluation.js +153 -0
- package/dist/src/learning/AnswerQualityEvaluation.test.js +118 -0
- package/dist/src/learning/KnowledgeLearningPlatform.js +11181 -0
- package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +745 -0
- package/dist/src/learning/KnowledgeLearningPlatform.program-f.test.js +99 -0
- package/dist/src/learning/KnowledgeLearningPlatform.test.js +3208 -0
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +2998 -0
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +3936 -0
- package/dist/src/learning/MeasurementEvidenceConflicts.test.js +78 -0
- package/dist/src/learning/PublicAnswerContract.test.js +85 -0
- package/dist/src/learning/PublicEvidenceSelection.test.js +94 -0
- package/dist/src/learning/PublicMeasurementDisclosure.test.js +54 -0
- package/dist/src/learning/agentConversationExecution.js +211 -0
- package/dist/src/learning/agentConversationExecution.test.js +209 -0
- package/dist/src/learning/agentConversationSerialization.js +266 -0
- package/dist/src/learning/agentConversationSerialization.test.js +165 -0
- package/dist/src/learning/agentResponseBudget.js +179 -0
- package/dist/src/learning/agentResponseBudget.test.js +97 -0
- package/dist/src/learning/agentWorkspaceCapabilityContracts.js +65 -0
- package/dist/src/learning/answerReleaseReview.js +5260 -0
- package/dist/src/learning/answerReleaseReview.test.js +4174 -0
- package/dist/src/learning/answerTaskPlan.js +473 -0
- package/dist/src/learning/api.js +2 -0
- package/dist/src/learning/conversationComposer.js +1721 -0
- package/dist/src/learning/conversationComposer.test.js +3220 -0
- package/dist/src/learning/domains/ConversationManager.js +53 -0
- package/dist/src/learning/domains/KnowledgeIngestor.js +238 -0
- package/dist/src/learning/domains/KnowledgeQuerier.js +187 -0
- package/dist/src/learning/domains/MasteryEngine.js +387 -0
- package/dist/src/learning/domains/MemoryPolicyManager.js +408 -0
- package/dist/src/learning/domains/QualityEvaluator.js +307 -0
- package/dist/src/learning/domains/TutorRouter.js +313 -0
- package/dist/src/learning/domains/index.js +33 -0
- package/dist/src/learning/domains/types.js +7 -0
- package/dist/src/learning/errors.js +29 -0
- package/dist/src/learning/evidenceContextAssembler.js +1368 -0
- package/dist/src/learning/evidenceContextAssembler.test.js +6332 -0
- package/dist/src/learning/graphAnswerCoverage.js +37 -0
- package/dist/src/learning/graphAnswerCoverage.test.js +93 -0
- package/dist/src/learning/graphAnswerCoverageCalibration.js +59 -0
- package/dist/src/learning/graphAnswerCoverageCalibration.test.js +46 -0
- package/dist/src/learning/graphAnswerFacts.js +94 -0
- package/dist/src/learning/graphAnswerFacts.test.js +39 -0
- package/dist/src/learning/graphAnswerPlan.js +908 -0
- package/dist/src/learning/graphAnswerPlan.test.js +907 -0
- package/dist/src/learning/graphAnswerQualityCalibration.js +255 -0
- package/dist/src/learning/graphAnswerQualityCalibration.test.js +72 -0
- package/dist/src/learning/graphAnswerQualityPolicy.js +30 -0
- package/dist/src/learning/graphClaimMatcher.js +104 -0
- package/dist/src/learning/graphConditionedContext.js +109 -0
- package/dist/src/learning/graphConditionedContext.test.js +99 -0
- package/dist/src/learning/graphContextAssembler.js +860 -0
- package/dist/src/learning/graphContextAssembler.test.js +1033 -0
- package/dist/src/learning/graphExpansionPolicy.js +22 -0
- package/dist/src/learning/graphExpansionPolicy.test.js +33 -0
- package/dist/src/learning/identityMetadata.test.js +26 -0
- package/dist/src/learning/index.js +29 -0
- package/dist/src/learning/mobileAnswerProjection.js +104 -0
- package/dist/src/learning/mobileAnswerProjection.test.js +102 -0
- package/dist/src/learning/queryBackend.js +1922 -0
- package/dist/src/learning/queryBackend.test.js +976 -0
- package/dist/src/learning/ragContextPack.js +356 -0
- package/dist/src/learning/ragContextPack.test.js +311 -0
- package/dist/src/learning/ragEvidenceQuality.js +96 -0
- package/dist/src/learning/ragEvidenceQuality.test.js +29 -0
- package/dist/src/learning/ragPublicText.js +101 -0
- package/dist/src/learning/ragPublicText.test.js +57 -0
- package/dist/src/learning/ragSufficiencyJudge.js +171 -0
- package/dist/src/learning/ragSufficiencyJudge.test.js +177 -0
- package/dist/src/learning/ragSufficiencyProviderJudge.js +217 -0
- package/dist/src/learning/ragSufficiencyProviderJudge.test.js +207 -0
- package/dist/src/learning/requestNormalization.js +304 -0
- package/dist/src/learning/requestNormalization.test.js +101 -0
- package/dist/src/learning/runtimeCapability.js +4677 -0
- package/dist/src/learning/runtimeCapability.test.js +3635 -0
- package/dist/src/learning/store.js +1344 -0
- package/dist/src/learning/store.test.js +1425 -0
- package/dist/src/learning/tutorAdapter.js +2 -0
- package/dist/src/learning/types.js +2 -0
- package/dist/src/learning/vectorAccelerationAdapter.js +958 -0
- package/dist/src/learning/vectorAccelerationAdapter.test.js +412 -0
- package/dist/src/learning/workspaceHydration.js +168 -0
- package/dist/src/learning/workspaceHydration.test.js +30 -0
- package/dist/src/lfs.asset.policy.contract.test.js +153 -0
- package/dist/src/license.policy.contract.test.js +71 -0
- package/dist/src/markdown/MarkdownGateway.js +4 -0
- package/dist/src/markdown/MarkdownGateway.test.js +59 -0
- package/dist/src/memory/MemoryGovernance.js +74 -0
- package/dist/src/memory/MemoryGovernance.test.js +46 -0
- package/dist/src/memory/types.js +2 -0
- package/dist/src/mermaid.frontend.guard.contract.test.js +77 -0
- package/dist/src/middleware/SseResponseWriter.js +122 -0
- package/dist/src/middleware/SseResponseWriter.test.js +54 -0
- package/dist/src/middleware/auth.js +38 -0
- package/dist/src/middleware/auth.test.js +33 -0
- package/dist/src/middleware/body-parser.js +45 -0
- package/dist/src/middleware/cors.js +44 -0
- package/dist/src/middleware/index.js +22 -0
- package/dist/src/middleware/request-trace.js +96 -0
- package/dist/src/mobile.android.evidence.contract.test.js +146 -0
- package/dist/src/mobile.android.signing.contract.test.js +66 -0
- package/dist/src/mobile.artifact.contract.test.js +144 -0
- package/dist/src/mobile.budget.contract.test.js +90 -0
- package/dist/src/mobile.canonical-id.readiness.test.js +54 -0
- package/dist/src/mobile.graph.parity.contract.test.js +207 -0
- package/dist/src/mobile.identity.contract.test.js +66 -0
- package/dist/src/mobile.identity.corpus.manifest.test.js +72 -0
- package/dist/src/mobile.identity.corpus.test.js +40 -0
- package/dist/src/mobile.native.recovery.contract.test.js +64 -0
- package/dist/src/mobile.pipeline.test.js +11 -1
- package/dist/src/mobile.profile.contract.test.js +225 -0
- package/dist/src/mobile.semantic.parity.test.js +92 -0
- package/dist/src/mobile_exact_analyzer.test.js +113 -0
- package/dist/src/notemd/AppConfigToml.js +6 -4
- package/dist/src/notemd/ContentGenerator.js +4 -9
- package/dist/src/notemd/FileProcessor.js +4 -9
- package/dist/src/notemd/MermaidProcessor.js +400 -50
- package/dist/src/notemd/NotemdService.js +506 -26
- package/dist/src/notemd/PromptManager.js +15 -0
- package/dist/src/notemd/Translator.js +4 -9
- package/dist/src/notemd/cli/commands.js +357 -0
- package/dist/src/notemd/cli/dispatcher.js +225 -0
- package/dist/src/notemd/cli/index.js +169 -0
- package/dist/src/notemd/cli/parser.js +68 -0
- package/dist/src/notemd/cli/types.js +2 -0
- package/dist/src/notemd/constants.js +43 -0
- package/dist/src/notemd/diagram/diagramGenerationService.js +78 -0
- package/dist/src/notemd/diagram/diagramSpec.js +79 -0
- package/dist/src/notemd/diagram/diagramSpecResponseParser.js +131 -0
- package/dist/src/notemd/diagram/intent.js +95 -0
- package/dist/src/notemd/diagram/planner.js +71 -0
- package/dist/src/notemd/diagram/prompts/diagramSpecPrompt.js +42 -0
- package/dist/src/notemd/diagram/types.js +18 -0
- package/dist/src/notemd/index.js +26 -0
- package/dist/src/notemd/operations/capabilityManifest.js +23 -0
- package/dist/src/notemd/operations/cliContracts.js +17 -0
- package/dist/src/notemd/operations/configProfileCommands.js +85 -0
- package/dist/src/notemd/operations/registry.contract.test.js +95 -0
- package/dist/src/notemd/operations/registry.js +991 -0
- package/dist/src/notemd/operations/types.js +2 -0
- package/dist/src/notemd/progressReporter.js +9 -0
- package/dist/src/notemd/providerDiagnostics.js +220 -0
- package/dist/src/notemd/providerProfiles.js +42 -0
- package/dist/src/notemd/providerTemplates.js +231 -0
- package/dist/src/notemd/search/DuckDuckGoProvider.js +39 -0
- package/dist/src/notemd/search/SearchManager.js +13 -0
- package/dist/src/notemd/search/SearchProvider.js +2 -0
- package/dist/src/notemd/search/TavilyProvider.js +44 -0
- package/dist/src/notemd.agent.manifest.test.js +85 -0
- package/dist/src/notemd.api.contract.test.js +14 -1
- package/dist/src/notemd.app_config_toml.test.js +2 -1
- package/dist/src/notemd.batch.workflow.test.js +117 -0
- package/dist/src/notemd.cli.e2e.test.js +136 -0
- package/dist/src/notemd.core.test.js +51 -0
- package/dist/src/notemd.diagram.pipeline.test.js +233 -0
- package/dist/src/notemd.providerTemplates.test.js +34 -0
- package/dist/src/notemd.server.integration.test.js +262 -39
- package/dist/src/notemd.workflow.pipeline.test.js +162 -0
- package/dist/src/pathbridge.handshake.contract.test.js +45 -2
- package/dist/src/pathbridge.host-adapter.contract.test.js +133 -0
- package/dist/src/pathcore.bundle.contract.test.js +8 -0
- package/dist/src/pathmode.background.contract.test.js +69 -0
- package/dist/src/pathmode.settings.api.contract.test.js +9 -0
- package/dist/src/pkg.sidecar.contract.test.js +9 -3
- package/dist/src/platform/ExportProfile.js +86 -0
- package/dist/src/platform/MobileBudget.js +11 -0
- package/dist/src/platform/PlatformCapabilities.js +59 -0
- package/dist/src/platform/PlatformCapabilities.test.js +36 -0
- package/dist/src/platform/RenderMaterializer.js +33 -0
- package/dist/src/platform/RenderMaterializer.test.js +32 -0
- package/dist/src/query_backend.external_http.integration.test.js +410 -0
- package/dist/src/reader_renderer.js +404 -3
- package/dist/src/reader_renderer.test.js +87 -0
- package/dist/src/release.godot.mirror.contract.test.js +97 -0
- package/dist/src/resources/ResourceRegistry.js +263 -0
- package/dist/src/resources/ResourceRegistry.test.js +97 -0
- package/dist/src/resources/types.js +2 -0
- package/dist/src/routes/agentWorkspaceDiagnostics.js +173 -0
- package/dist/src/routes/index.js +19 -0
- package/dist/src/routes/knowledge.js +981 -0
- package/dist/src/routes/knowledgePayload.js +185 -0
- package/dist/src/routes/knowledgePayload.test.js +53 -0
- package/dist/src/routes/markdown.js +295 -0
- package/dist/src/routes/notemd.js +1321 -0
- package/dist/src/routes/registry.contract.test.js +133 -0
- package/dist/src/routes/registry.shadow.contract.test.js +22 -0
- package/dist/src/routes/render.js +248 -0
- package/dist/src/routes/runtimeRunbookRouteOps.js +149 -0
- package/dist/src/routes/runtimeRunbookRouteOps.test.js +194 -0
- package/dist/src/routes/settings.js +6 -0
- package/dist/src/routes/staticFiles.js +94 -0
- package/dist/src/routes/types.js +2 -0
- package/dist/src/runtime.capabilities.test.js +18 -2
- package/dist/src/runtime.transport.adapter.contract.test.js +81 -0
- package/dist/src/server.js +10342 -1325
- package/dist/src/server.migration.test.js +584 -10
- package/dist/src/server.port.fallback.contract.test.js +63 -0
- package/dist/src/session/SessionStateStore.js +81 -0
- package/dist/src/session/SessionStateStore.test.js +58 -0
- package/dist/src/session/types.js +2 -0
- package/dist/src/settings.runtime.contract.test.js +50 -0
- package/dist/src/shared/types.contract.test.js +107 -0
- package/dist/src/shared/types.js +22 -0
- package/dist/src/sidecar.build.lock.contract.test.js +201 -0
- package/dist/src/sidecar.freshness.contract.test.js +184 -0
- package/dist/src/sidecar.replacement.boundary.contract.test.js +131 -0
- package/dist/src/sidecar.supply.readiness.contract.test.js +155 -0
- package/dist/src/simulation.worker.offline.test.js +104 -0
- package/dist/src/source_manager.loadflow.test.js +46 -0
- package/dist/src/startup.layout.snapshot.contract.test.js +57 -0
- package/dist/src/storage.provider.capacitor.content.contract.test.js +4 -1
- package/dist/src/storage.provider.contract.test.js +152 -1
- package/dist/src/tauri.frontend.build.contract.test.js +68 -0
- package/dist/src/tauri.sidecar.cleanup.contract.test.js +21 -0
- package/dist/src/tauri.window.evidence.execution.test.js +68 -0
- package/dist/src/utils/RuntimePaths.js +10 -13
- package/dist/src/utils/RuntimePaths.test.js +27 -0
- package/dist/src/utils/platform.js +153 -0
- package/dist/src/windows.installer.build.test.js +109 -0
- package/dist/src/windows.installer.payload.test.js +76 -0
- package/dist/src/windows.installer.runtime.test.js +69 -0
- package/dist/src/workflows/WorkflowArtifactStore.js +96 -0
- package/dist/src/workflows/WorkflowArtifactStore.test.js +80 -0
- package/dist/src/workflows/types.js +2 -0
- package/dist/src/workspace/WorkspaceRegistry.js +135 -0
- package/dist/src/workspace/WorkspaceRegistry.test.js +29 -0
- package/dist/src/workspace/types.js +2 -0
- package/package.json +80 -15
|
@@ -42,11 +42,14 @@ describe('capacitor bridge serialization contract', () => {
|
|
|
42
42
|
const source = fs.readFileSync(storageProviderPath, 'utf8');
|
|
43
43
|
expect(source).toContain('CAPACITOR_BRIDGE_MAX_CHUNK_BYTES');
|
|
44
44
|
expect(source).toContain('CAPACITOR_GRAPH_SERIALIZATION_MAX_BYTES');
|
|
45
|
+
expect(source).toContain('getMobileRuntimeBudget().maxProjectionBytes');
|
|
46
|
+
expect(source).toContain('Math.min(\n CAPACITOR_GRAPH_SERIALIZATION_MAX_BYTES,');
|
|
45
47
|
expect(source).toContain('splitCapacitorPayloadIntoChunks');
|
|
46
48
|
expect(source).toContain('writeCapacitorChunkSequenceToDirectory');
|
|
47
49
|
expect(source).toContain('appendFile');
|
|
48
50
|
expect(source).toContain('createCapacitorGraphDataJsonChunks');
|
|
49
51
|
expect(source).toContain("serializationMode: 'chunked-bridge-json-stream'");
|
|
52
|
+
expect(source).toContain('maxPayloadBytes: graphSerializationMaxBytes');
|
|
50
53
|
expect(source).not.toContain('JSON.stringify(graphData, null, 2)');
|
|
51
54
|
});
|
|
52
55
|
});
|
|
@@ -69,7 +69,16 @@ describe('capacitor runtime parity closure contract', () => {
|
|
|
69
69
|
});
|
|
70
70
|
test('storage provider keeps capacitor local build fallback path', () => {
|
|
71
71
|
const source = fs.readFileSync(storageProviderPath, 'utf8');
|
|
72
|
-
expect(source).toContain('
|
|
72
|
+
expect(source).toContain('getMobileRuntimeBudget');
|
|
73
|
+
expect(source).toContain('measureUtf8Bytes');
|
|
74
|
+
expect(source).toContain('maxBytes: getMobileRuntimeBudget().maxDocumentBytes');
|
|
75
|
+
expect(source).toContain('maxBytes: getMobileRuntimeBudget().maxProjectionBytes');
|
|
76
|
+
expect(source).toContain('maxDocuments');
|
|
77
|
+
expect(source).toContain('maxBytes: budget.maxDocumentBytes');
|
|
78
|
+
expect(source).toContain('maxTotalInputBytes');
|
|
79
|
+
expect(source).toContain('maxDepth');
|
|
80
|
+
expect(source).toContain('const entryDepth = currentDepth + 1;');
|
|
81
|
+
expect(source).toContain("MOBILE_BUDGET_EXCEEDED");
|
|
73
82
|
expect(source).toContain('collectCapacitorMarkdownFiles');
|
|
74
83
|
expect(source).toContain('buildCapacitorGraphData');
|
|
75
84
|
expect(source).toContain('buildCapacitorGraphDataWithWorkerFallback');
|
|
@@ -82,7 +91,7 @@ describe('capacitor runtime parity closure contract', () => {
|
|
|
82
91
|
expect(source).toContain('supportsMobileWasmCompute');
|
|
83
92
|
expect(source).toContain('mobileWasmReason');
|
|
84
93
|
expect(source).toContain('capacitorBuildGraph');
|
|
85
|
-
expect(source).toContain("return await capacitorReadText(normalized
|
|
94
|
+
expect(source).toContain("return await capacitorReadText(normalized, {");
|
|
86
95
|
});
|
|
87
96
|
test('source panel no longer hard-blocks capacitor load action before cache/build flow', () => {
|
|
88
97
|
const source = fs.readFileSync(sourceManagerPath, 'utf8');
|
|
@@ -0,0 +1,130 @@
|
|
|
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
|
+
class TempDir {
|
|
40
|
+
constructor(prefix) {
|
|
41
|
+
this.path = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), `${prefix}-`));
|
|
42
|
+
}
|
|
43
|
+
child(relative) {
|
|
44
|
+
return path.join(this.path, relative);
|
|
45
|
+
}
|
|
46
|
+
mkdir(relative) {
|
|
47
|
+
const target = this.child(relative);
|
|
48
|
+
fs.mkdirSync(target, { recursive: true });
|
|
49
|
+
return target;
|
|
50
|
+
}
|
|
51
|
+
file(relative, content) {
|
|
52
|
+
const target = this.child(relative);
|
|
53
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
54
|
+
fs.writeFileSync(target, content, 'utf8');
|
|
55
|
+
return target;
|
|
56
|
+
}
|
|
57
|
+
cleanup() {
|
|
58
|
+
fs.rmSync(this.path, { recursive: true, force: true });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
describe('copy-assets runtime-first contract', () => {
|
|
62
|
+
const repoRoot = path.resolve(__dirname, '..');
|
|
63
|
+
const copyAssetsPath = path.join(repoRoot, 'scripts', 'copy-assets.js');
|
|
64
|
+
let temp;
|
|
65
|
+
let srcDir;
|
|
66
|
+
let destDir;
|
|
67
|
+
let copyProjectAssets;
|
|
68
|
+
beforeAll(() => {
|
|
69
|
+
({ copyProjectAssets } = require(copyAssetsPath));
|
|
70
|
+
});
|
|
71
|
+
beforeEach(() => {
|
|
72
|
+
temp = new TempDir('noteconnection-copy-assets');
|
|
73
|
+
srcDir = temp.mkdir('src');
|
|
74
|
+
destDir = temp.mkdir('dest');
|
|
75
|
+
});
|
|
76
|
+
afterEach(() => {
|
|
77
|
+
temp.cleanup();
|
|
78
|
+
});
|
|
79
|
+
test('excludes generated graph payloads by default', () => {
|
|
80
|
+
temp.file(path.join('src', 'app.js'), 'console.log("app");');
|
|
81
|
+
temp.file(path.join('src', 'data.js'), 'const graphData = {"nodes":[{"id":"A"}],"edges":[]}');
|
|
82
|
+
temp.file(path.join('src', 'graph_data.json'), '{"nodes":[{"id":"A"}],"edges":[]}');
|
|
83
|
+
copyProjectAssets({
|
|
84
|
+
src: srcDir,
|
|
85
|
+
dest: destDir,
|
|
86
|
+
logger: console
|
|
87
|
+
});
|
|
88
|
+
expect(fs.existsSync(path.join(destDir, 'app.js'))).toBe(true);
|
|
89
|
+
expect(fs.existsSync(path.join(destDir, 'data.js'))).toBe(false);
|
|
90
|
+
expect(fs.existsSync(path.join(destDir, 'graph_data.json'))).toBe(false);
|
|
91
|
+
});
|
|
92
|
+
test('copies generated graph payloads only when explicitly requested', () => {
|
|
93
|
+
temp.file(path.join('src', 'data.js'), 'const graphData = {"nodes":[{"id":"A"}],"edges":[]}');
|
|
94
|
+
temp.file(path.join('src', 'graph_data.json'), '{"nodes":[{"id":"A"}],"edges":[]}');
|
|
95
|
+
copyProjectAssets({
|
|
96
|
+
src: srcDir,
|
|
97
|
+
dest: destDir,
|
|
98
|
+
includeGeneratedGraphAssets: true,
|
|
99
|
+
logger: console
|
|
100
|
+
});
|
|
101
|
+
expect(fs.existsSync(path.join(destDir, 'data.js'))).toBe(true);
|
|
102
|
+
expect(fs.existsSync(path.join(destDir, 'graph_data.json'))).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
test('full mode remains valid when repository head no longer ships bundled graph payload files', () => {
|
|
105
|
+
temp.file(path.join('src', 'app.js'), 'console.log("app");');
|
|
106
|
+
expect(() => copyProjectAssets({
|
|
107
|
+
src: srcDir,
|
|
108
|
+
dest: destDir,
|
|
109
|
+
includeGeneratedGraphAssets: true,
|
|
110
|
+
logger: console
|
|
111
|
+
})).not.toThrow();
|
|
112
|
+
expect(fs.existsSync(path.join(destDir, 'app.js'))).toBe(true);
|
|
113
|
+
expect(fs.existsSync(path.join(destDir, 'data.js'))).toBe(false);
|
|
114
|
+
expect(fs.existsSync(path.join(destDir, 'graph_data.json'))).toBe(false);
|
|
115
|
+
});
|
|
116
|
+
test('does not copy LFS pointer placeholders even in explicit full mode', () => {
|
|
117
|
+
temp.file(path.join('src', 'data.js'), [
|
|
118
|
+
'version https://git-lfs.github.com/spec/v1',
|
|
119
|
+
'oid sha256:abc123',
|
|
120
|
+
'size 177419264'
|
|
121
|
+
].join('\n'));
|
|
122
|
+
copyProjectAssets({
|
|
123
|
+
src: srcDir,
|
|
124
|
+
dest: destDir,
|
|
125
|
+
includeGeneratedGraphAssets: true,
|
|
126
|
+
logger: console
|
|
127
|
+
});
|
|
128
|
+
expect(fs.existsSync(path.join(destDir, 'data.js'))).toBe(false);
|
|
129
|
+
});
|
|
130
|
+
});
|
package/dist/src/core/Graph.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Graph = void 0;
|
|
4
|
+
const ResourceReference_1 = require("./ResourceReference");
|
|
4
5
|
/**
|
|
5
6
|
* Directed Graph implementation for managing notes and dependencies.
|
|
6
7
|
* 用于管理笔记和依赖关系的有向图实现。
|
|
@@ -10,6 +11,7 @@ class Graph {
|
|
|
10
11
|
this.nodes = new Map();
|
|
11
12
|
this.adjacencyList = new Map();
|
|
12
13
|
this.reverseAdjacencyList = new Map();
|
|
14
|
+
this.aliases = new Map();
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
17
|
* Adds a node to the graph.
|
|
@@ -17,11 +19,90 @@ class Graph {
|
|
|
17
19
|
* @param node The node to add | 要添加的节点
|
|
18
20
|
*/
|
|
19
21
|
addNode(node) {
|
|
20
|
-
if (
|
|
21
|
-
|
|
22
|
-
this.adjacencyList.set(node.id, []);
|
|
23
|
-
this.reverseAdjacencyList.set(node.id, []);
|
|
22
|
+
if (this.nodes.has(node.id)) {
|
|
23
|
+
return;
|
|
24
24
|
}
|
|
25
|
+
const aliases = [node.id, node.sourceUri, ...(node.identityAliases ?? [])]
|
|
26
|
+
.filter((alias) => typeof alias === 'string' && alias.length > 0);
|
|
27
|
+
const normalizedAliases = new Set(aliases.map(alias => (0, ResourceReference_1.normalizeResourceReference)(alias)));
|
|
28
|
+
normalizedAliases.forEach(alias => {
|
|
29
|
+
const existingNodeId = this.aliases.get(alias);
|
|
30
|
+
if (existingNodeId && existingNodeId !== node.id) {
|
|
31
|
+
throw new Error(`Resource identity alias collision: "${alias}" is claimed by both "${existingNodeId}" and "${node.id}"`);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
this.nodes.set(node.id, { ...node, inDegree: 0, outDegree: 0 });
|
|
35
|
+
this.adjacencyList.set(node.id, []);
|
|
36
|
+
this.reverseAdjacencyList.set(node.id, []);
|
|
37
|
+
normalizedAliases.forEach(alias => {
|
|
38
|
+
this.aliases.set(alias, node.id);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Rehydrates a graph from either a current or legacy JSON snapshot.
|
|
43
|
+
*
|
|
44
|
+
* The snapshot is validated before mutating the returned graph. Edges must
|
|
45
|
+
* reference declared nodes so a corrupt or partially-written snapshot cannot
|
|
46
|
+
* silently create synthetic nodes and change graph semantics during replay.
|
|
47
|
+
*/
|
|
48
|
+
static fromJSON(data) {
|
|
49
|
+
if (!data || typeof data !== 'object' || Array.isArray(data)) {
|
|
50
|
+
throw new Error('Graph snapshot must be an object.');
|
|
51
|
+
}
|
|
52
|
+
const snapshot = data;
|
|
53
|
+
if (!Array.isArray(snapshot.nodes) || !Array.isArray(snapshot.edges)) {
|
|
54
|
+
throw new Error('Graph snapshot must contain nodes and edges arrays.');
|
|
55
|
+
}
|
|
56
|
+
const graph = new Graph();
|
|
57
|
+
const nodeIds = new Set();
|
|
58
|
+
snapshot.nodes.forEach((rawNode, index) => {
|
|
59
|
+
if (!rawNode || typeof rawNode !== 'object' || Array.isArray(rawNode)) {
|
|
60
|
+
throw new Error(`Graph snapshot node at index ${index} must be an object.`);
|
|
61
|
+
}
|
|
62
|
+
const node = rawNode;
|
|
63
|
+
if (typeof node.id !== 'string' || node.id.trim().length === 0) {
|
|
64
|
+
throw new Error(`Graph snapshot node at index ${index} requires a non-empty id.`);
|
|
65
|
+
}
|
|
66
|
+
if (nodeIds.has(node.id)) {
|
|
67
|
+
throw new Error(`Graph snapshot contains duplicate node id: ${node.id}.`);
|
|
68
|
+
}
|
|
69
|
+
nodeIds.add(node.id);
|
|
70
|
+
graph.addNode({
|
|
71
|
+
...node,
|
|
72
|
+
id: node.id,
|
|
73
|
+
label: typeof node.label === 'string' && node.label.length > 0 ? node.label : node.id,
|
|
74
|
+
inDegree: 0,
|
|
75
|
+
outDegree: 0,
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
snapshot.edges.forEach((rawEdge, index) => {
|
|
79
|
+
if (!rawEdge || typeof rawEdge !== 'object' || Array.isArray(rawEdge)) {
|
|
80
|
+
throw new Error(`Graph snapshot edge at index ${index} must be an object.`);
|
|
81
|
+
}
|
|
82
|
+
const edge = rawEdge;
|
|
83
|
+
if (typeof edge.source !== 'string' || typeof edge.target !== 'string') {
|
|
84
|
+
throw new Error(`Graph snapshot edge at index ${index} requires source and target ids.`);
|
|
85
|
+
}
|
|
86
|
+
if (!graph.hasNode(edge.source) || !graph.hasNode(edge.target)) {
|
|
87
|
+
throw new Error(`Graph snapshot edge at index ${index} references an undeclared node: ${edge.source} -> ${edge.target}.`);
|
|
88
|
+
}
|
|
89
|
+
graph.addEdge(edge.source, edge.target, edge.type, edge.weight);
|
|
90
|
+
});
|
|
91
|
+
return graph;
|
|
92
|
+
}
|
|
93
|
+
/** Restore this instance atomically from a legacy or current JSON snapshot. */
|
|
94
|
+
restore(data) {
|
|
95
|
+
const restored = Graph.fromJSON(data);
|
|
96
|
+
this.nodes = restored.nodes;
|
|
97
|
+
this.adjacencyList = restored.adjacencyList;
|
|
98
|
+
this.reverseAdjacencyList = restored.reverseAdjacencyList;
|
|
99
|
+
this.aliases = restored.aliases;
|
|
100
|
+
}
|
|
101
|
+
resolveNodeId(reference) {
|
|
102
|
+
if (this.nodes.has(reference)) {
|
|
103
|
+
return reference;
|
|
104
|
+
}
|
|
105
|
+
return this.aliases.get((0, ResourceReference_1.normalizeResourceReference)(reference));
|
|
25
106
|
}
|
|
26
107
|
/**
|
|
27
108
|
* Retrieves a node by its ID.
|
|
@@ -29,16 +110,17 @@ class Graph {
|
|
|
29
110
|
* @param id The node ID | 节点 ID
|
|
30
111
|
* @returns The node or undefined if not found | 节点,如果未找到则返回 undefined
|
|
31
112
|
*/
|
|
32
|
-
getNode(
|
|
33
|
-
|
|
113
|
+
getNode(reference) {
|
|
114
|
+
const nodeId = this.resolveNodeId(reference);
|
|
115
|
+
return nodeId ? this.nodes.get(nodeId) : undefined;
|
|
34
116
|
}
|
|
35
117
|
/**
|
|
36
118
|
* Checks if a node exists in the graph.
|
|
37
119
|
* 检查图中是否存在该节点。
|
|
38
120
|
* @param id The node ID | 节点 ID
|
|
39
121
|
*/
|
|
40
|
-
hasNode(
|
|
41
|
-
return this.
|
|
122
|
+
hasNode(reference) {
|
|
123
|
+
return this.resolveNodeId(reference) !== undefined;
|
|
42
124
|
}
|
|
43
125
|
/**
|
|
44
126
|
* Adds a directed edge between two nodes.
|
|
@@ -49,30 +131,32 @@ class Graph {
|
|
|
49
131
|
* @param weight Edge weight (confidence) | 边权重 (置信度)
|
|
50
132
|
*/
|
|
51
133
|
addEdge(source, target, type = 'dependency', weight = 1) {
|
|
52
|
-
|
|
53
|
-
|
|
134
|
+
const sourceId = this.resolveNodeId(source) ?? source;
|
|
135
|
+
const targetId = this.resolveNodeId(target) ?? target;
|
|
136
|
+
if (!this.nodes.has(sourceId)) {
|
|
137
|
+
this.addNode({ id: sourceId, label: sourceId, inDegree: 0, outDegree: 0 });
|
|
54
138
|
}
|
|
55
|
-
if (!this.nodes.has(
|
|
56
|
-
this.addNode({ id:
|
|
139
|
+
if (!this.nodes.has(targetId)) {
|
|
140
|
+
this.addNode({ id: targetId, label: targetId, inDegree: 0, outDegree: 0 });
|
|
57
141
|
}
|
|
58
|
-
const edge = { source, target, type, weight };
|
|
142
|
+
const edge = { source: sourceId, target: targetId, type, weight };
|
|
59
143
|
// Add to adjacency list (outgoing)
|
|
60
|
-
const outgoing = this.adjacencyList.get(
|
|
144
|
+
const outgoing = this.adjacencyList.get(sourceId) || [];
|
|
61
145
|
// Prevent duplicate edges
|
|
62
|
-
if (!outgoing.some(e => e.target ===
|
|
146
|
+
if (!outgoing.some(e => e.target === targetId && e.type === type)) {
|
|
63
147
|
outgoing.push(edge);
|
|
64
|
-
this.adjacencyList.set(
|
|
148
|
+
this.adjacencyList.set(sourceId, outgoing);
|
|
65
149
|
// Update out-degree
|
|
66
|
-
const sourceNode = this.nodes.get(
|
|
150
|
+
const sourceNode = this.nodes.get(sourceId);
|
|
67
151
|
sourceNode.outDegree++;
|
|
68
152
|
}
|
|
69
153
|
// Add to reverse adjacency list (incoming)
|
|
70
|
-
const incoming = this.reverseAdjacencyList.get(
|
|
71
|
-
if (!incoming.some(e => e.source ===
|
|
154
|
+
const incoming = this.reverseAdjacencyList.get(targetId) || [];
|
|
155
|
+
if (!incoming.some(e => e.source === sourceId && e.type === type)) {
|
|
72
156
|
incoming.push(edge);
|
|
73
|
-
this.reverseAdjacencyList.set(
|
|
157
|
+
this.reverseAdjacencyList.set(targetId, incoming);
|
|
74
158
|
// Update in-degree
|
|
75
|
-
const targetNode = this.nodes.get(
|
|
159
|
+
const targetNode = this.nodes.get(targetId);
|
|
76
160
|
targetNode.inDegree++;
|
|
77
161
|
}
|
|
78
162
|
}
|
|
@@ -81,16 +165,17 @@ class Graph {
|
|
|
81
165
|
* 获取节点的所有出边。
|
|
82
166
|
* @param id Node ID | 节点 ID
|
|
83
167
|
*/
|
|
84
|
-
getOutgoingEdges(
|
|
85
|
-
|
|
168
|
+
getOutgoingEdges(reference) {
|
|
169
|
+
const nodeId = this.resolveNodeId(reference);
|
|
170
|
+
return nodeId ? (this.adjacencyList.get(nodeId) || []) : [];
|
|
86
171
|
}
|
|
87
172
|
/**
|
|
88
173
|
* Gets all outgoing neighbor IDs for a node.
|
|
89
174
|
* 获取节点的所有出度邻居 ID。
|
|
90
175
|
* @param id Node ID | 节点 ID
|
|
91
176
|
*/
|
|
92
|
-
getNeighbors(
|
|
93
|
-
return
|
|
177
|
+
getNeighbors(reference) {
|
|
178
|
+
return this.getOutgoingEdges(reference).map(edge => edge.target);
|
|
94
179
|
}
|
|
95
180
|
/**
|
|
96
181
|
* Gets all nodes in the graph.
|
|
@@ -111,8 +196,9 @@ class Graph {
|
|
|
111
196
|
* 获取节点的所有入边。
|
|
112
197
|
* @param id Node ID | 节点 ID
|
|
113
198
|
*/
|
|
114
|
-
getIncomingEdges(
|
|
115
|
-
|
|
199
|
+
getIncomingEdges(reference) {
|
|
200
|
+
const nodeId = this.resolveNodeId(reference);
|
|
201
|
+
return nodeId ? (this.reverseAdjacencyList.get(nodeId) || []) : [];
|
|
116
202
|
}
|
|
117
203
|
/**
|
|
118
204
|
* Returns the graph data in a serializable format.
|
|
@@ -129,11 +215,14 @@ class Graph {
|
|
|
129
215
|
* 获取所有前驱节点(入边的传递闭包)。
|
|
130
216
|
* @param id Target node ID
|
|
131
217
|
*/
|
|
132
|
-
getPredecessors(
|
|
218
|
+
getPredecessors(reference) {
|
|
133
219
|
const predecessors = new Set();
|
|
134
|
-
const
|
|
220
|
+
const nodeId = this.resolveNodeId(reference);
|
|
221
|
+
if (!nodeId)
|
|
222
|
+
return predecessors;
|
|
223
|
+
const queue = [nodeId];
|
|
135
224
|
const visited = new Set();
|
|
136
|
-
visited.add(
|
|
225
|
+
visited.add(nodeId);
|
|
137
226
|
while (queue.length > 0) {
|
|
138
227
|
const current = queue.shift();
|
|
139
228
|
const incoming = this.getIncomingEdges(current);
|
|
@@ -152,11 +241,14 @@ class Graph {
|
|
|
152
241
|
* 获取所有后继节点(出边的传递闭包)。
|
|
153
242
|
* @param id Source node ID
|
|
154
243
|
*/
|
|
155
|
-
getSuccessors(
|
|
244
|
+
getSuccessors(reference) {
|
|
156
245
|
const successors = new Set();
|
|
157
|
-
const
|
|
246
|
+
const nodeId = this.resolveNodeId(reference);
|
|
247
|
+
if (!nodeId)
|
|
248
|
+
return successors;
|
|
249
|
+
const queue = [nodeId];
|
|
158
250
|
const visited = new Set();
|
|
159
|
-
visited.add(
|
|
251
|
+
visited.add(nodeId);
|
|
160
252
|
while (queue.length > 0) {
|
|
161
253
|
const current = queue.shift();
|
|
162
254
|
const outgoing = this.getOutgoingEdges(current);
|
|
@@ -178,15 +270,19 @@ class Graph {
|
|
|
178
270
|
* @returns Array of node IDs representing the path, or empty if no path found
|
|
179
271
|
*/
|
|
180
272
|
getShortestPath(source, target) {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
273
|
+
const sourceId = this.resolveNodeId(source);
|
|
274
|
+
const targetId = this.resolveNodeId(target);
|
|
275
|
+
if (!sourceId || !targetId)
|
|
276
|
+
return [];
|
|
277
|
+
if (sourceId === targetId)
|
|
278
|
+
return [sourceId];
|
|
279
|
+
const queue = [sourceId];
|
|
184
280
|
const visited = new Set();
|
|
185
281
|
const parent = new Map();
|
|
186
|
-
visited.add(
|
|
282
|
+
visited.add(sourceId);
|
|
187
283
|
while (queue.length > 0) {
|
|
188
284
|
const current = queue.shift();
|
|
189
|
-
if (current ===
|
|
285
|
+
if (current === targetId)
|
|
190
286
|
break;
|
|
191
287
|
const neighbors = this.getNeighbors(current);
|
|
192
288
|
for (const neighbor of neighbors) {
|
|
@@ -197,12 +293,12 @@ class Graph {
|
|
|
197
293
|
}
|
|
198
294
|
}
|
|
199
295
|
}
|
|
200
|
-
if (!visited.has(
|
|
296
|
+
if (!visited.has(targetId))
|
|
201
297
|
return [];
|
|
202
298
|
// Reconstruct path
|
|
203
|
-
const path = [
|
|
204
|
-
let curr =
|
|
205
|
-
while (curr !==
|
|
299
|
+
const path = [targetId];
|
|
300
|
+
let curr = targetId;
|
|
301
|
+
while (curr !== sourceId) {
|
|
206
302
|
curr = parent.get(curr);
|
|
207
303
|
path.unshift(curr);
|
|
208
304
|
}
|
|
@@ -34,4 +34,78 @@ describe('Graph Core', () => {
|
|
|
34
34
|
expect(nodeA?.outDegree).toBe(1);
|
|
35
35
|
expect(graph.getOutgoingEdges('A')).toHaveLength(1);
|
|
36
36
|
});
|
|
37
|
+
test('resolves source URI and relative path aliases without changing the public node ID', () => {
|
|
38
|
+
graph.addNode({
|
|
39
|
+
id: 'Index',
|
|
40
|
+
label: 'Index',
|
|
41
|
+
inDegree: 0,
|
|
42
|
+
outDegree: 0,
|
|
43
|
+
sourceUri: 'note://workspace/v1/algebra/index.md',
|
|
44
|
+
revision: 'sha256:revision',
|
|
45
|
+
identityAliases: ['algebra/index.md', 'Index'],
|
|
46
|
+
});
|
|
47
|
+
graph.addNode({ id: 'Limits', label: 'Limits', inDegree: 0, outDegree: 0 });
|
|
48
|
+
expect(graph.getNode('note://workspace/v1/algebra/index.md')?.id).toBe('Index');
|
|
49
|
+
expect(graph.getNode('algebra\\index.md')?.id).toBe('Index');
|
|
50
|
+
expect(graph.hasNode('INDEX')).toBe(true);
|
|
51
|
+
graph.addEdge('algebra/index.md', 'Limits', 'explicit-next');
|
|
52
|
+
expect(graph.getOutgoingEdges('Index')[0]).toEqual(expect.objectContaining({
|
|
53
|
+
source: 'Index',
|
|
54
|
+
target: 'Limits',
|
|
55
|
+
type: 'explicit-next',
|
|
56
|
+
}));
|
|
57
|
+
});
|
|
58
|
+
test('rejects an alias claimed by two different nodes', () => {
|
|
59
|
+
graph.addNode({
|
|
60
|
+
id: 'A',
|
|
61
|
+
label: 'A',
|
|
62
|
+
inDegree: 0,
|
|
63
|
+
outDegree: 0,
|
|
64
|
+
identityAliases: ['shared/path.md'],
|
|
65
|
+
});
|
|
66
|
+
expect(() => graph.addNode({
|
|
67
|
+
id: 'B',
|
|
68
|
+
label: 'B',
|
|
69
|
+
inDegree: 0,
|
|
70
|
+
outDegree: 0,
|
|
71
|
+
identityAliases: ['shared/path.md'],
|
|
72
|
+
})).toThrow(/alias/i);
|
|
73
|
+
});
|
|
74
|
+
test('replays legacy snapshots without identity metadata and preserves alias-aware edges', () => {
|
|
75
|
+
const restored = Graph_1.Graph.fromJSON({
|
|
76
|
+
nodes: [
|
|
77
|
+
{ id: 'A', label: 'A', inDegree: 0, outDegree: 1 },
|
|
78
|
+
{ id: 'B', label: 'B', inDegree: 1, outDegree: 0 },
|
|
79
|
+
],
|
|
80
|
+
edges: [{ source: 'A', target: 'B', type: 'legacy-link', weight: 0.5 }],
|
|
81
|
+
});
|
|
82
|
+
expect(restored.getNode('A')).toEqual(expect.objectContaining({ id: 'A', inDegree: 0, outDegree: 1 }));
|
|
83
|
+
expect(restored.getOutgoingEdges('A')).toEqual([
|
|
84
|
+
{ source: 'A', target: 'B', type: 'legacy-link', weight: 0.5 },
|
|
85
|
+
]);
|
|
86
|
+
});
|
|
87
|
+
test('rejects an edge that references a missing node before restoring', () => {
|
|
88
|
+
expect(() => Graph_1.Graph.fromJSON({
|
|
89
|
+
nodes: [{ id: 'A', label: 'A' }],
|
|
90
|
+
edges: [{ source: 'A', target: 'missing' }],
|
|
91
|
+
})).toThrow(/undeclared node/i);
|
|
92
|
+
});
|
|
93
|
+
test('restores an existing instance atomically', () => {
|
|
94
|
+
graph.addNode({ id: 'old', label: 'old', inDegree: 0, outDegree: 0 });
|
|
95
|
+
expect(() => graph.restore({
|
|
96
|
+
nodes: [{ id: 'new', label: 'new' }],
|
|
97
|
+
edges: [],
|
|
98
|
+
})).not.toThrow();
|
|
99
|
+
expect(graph.hasNode('old')).toBe(false);
|
|
100
|
+
expect(graph.hasNode('new')).toBe(true);
|
|
101
|
+
});
|
|
102
|
+
test('keeps the previous graph when an incoming snapshot fails validation', () => {
|
|
103
|
+
graph.addNode({ id: 'stable', label: 'stable', inDegree: 0, outDegree: 0 });
|
|
104
|
+
expect(() => graph.restore({
|
|
105
|
+
nodes: [{ id: 'candidate', label: 'candidate' }],
|
|
106
|
+
edges: [{ source: 'candidate', target: 'missing' }],
|
|
107
|
+
})).toThrow(/undeclared node/i);
|
|
108
|
+
expect(graph.hasNode('stable')).toBe(true);
|
|
109
|
+
expect(graph.hasNode('candidate')).toBe(false);
|
|
110
|
+
});
|
|
37
111
|
});
|
|
@@ -79,7 +79,7 @@ class NoteConnection {
|
|
|
79
79
|
}
|
|
80
80
|
// 2. Resolve Directory
|
|
81
81
|
const projectRoot = options.projectRoot || path.resolve(__dirname, '..', '..');
|
|
82
|
-
const kbRoot = path.join(projectRoot, 'Knowledge_Base');
|
|
82
|
+
const kbRoot = path.resolve(options.knowledgeBaseRoot || path.join(projectRoot, 'Knowledge_Base'));
|
|
83
83
|
let conceptDir;
|
|
84
84
|
if (options.targetPath) {
|
|
85
85
|
if (path.isAbsolute(options.targetPath)) {
|
|
@@ -97,7 +97,7 @@ class NoteConnection {
|
|
|
97
97
|
}
|
|
98
98
|
// 3. Load Files
|
|
99
99
|
log(`Loading files from: ${conceptDir}`);
|
|
100
|
-
const files = await FileLoader_1.FileLoader.loadFiles(conceptDir);
|
|
100
|
+
const files = await FileLoader_1.FileLoader.loadFiles(conceptDir, ['.md'], kbRoot);
|
|
101
101
|
log(`Loaded ${files.length} files.`);
|
|
102
102
|
// 4. Load Layout (Optional)
|
|
103
103
|
// Note: Layout logic is slightly coupled to file system here,
|